【PHP8.x】Dom\Entity::nodeValueプロパティの使い方
nodeValueプロパティの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
nodeValueプロパティは、Dom\Entityクラスに属し、ノードの値を保持するプロパティです。Dom\Entityクラスは、XMLやHTMLのDTD(Document Type Definition)で定義される「実体(エンティティ)」を表します。実体とは、文書内で頻繁に使用されるテキストや特殊文字などを名前で参照できるように定義し、再利用性を高めるための仕組みです。
このnodeValueプロパティは、通常、ノードのテキストコンテンツを取得するために使用されますが、Dom\Entityインスタンスに対してこのプロパティを参照すると、常にnullを返します。これは、DOM(Document Object Model)の仕様上、実体ノード自体が直接的なテキスト値を持つわけではないためです。実体は、その参照箇所で別のコンテンツに「置き換えられる」ものであり、実体ノードそのものが特定の値を保持する役割ではありません。
したがって、Dom\Entityオブジェクトから実体の実際のコンテンツ(置換テキスト)を取得するためには、このnodeValueプロパティではなく、実体の持つ内容にアクセスするための別のプロパティやメソッドを利用する必要があります。このnodeValueプロパティは読み取り専用であり、値を設定することはできません。
構文(syntax)
1<?php 2 3// Dom\Document を作成し、DTDでエンティティを定義します。 4$dom = new Dom\Document(); 5$dom->loadXML('<?xml version="1.0"?> 6<!DOCTYPE doc [ 7 <!ENTITY myEntity "Some Entity Text"> 8]> 9<root/>'); 10 11// DTDから "myEntity" という名前の Dom\Entity ノードを取得します。 12// Dom\Entity は直接インスタンス化できないため、このようにして取得します。 13$entityNode = $dom->doctype->entities->getNamedItem('myEntity'); 14 15// Dom\Entity の nodeValue プロパティにアクセスする構文です。 16// Dom\Entity の nodeValue は常に NULL を返します。 17$value = $entityNode->nodeValue; 18 19?>
引数(parameters)
引数なし
引数はありません
戻り値(return)
string|null
このプロパティは、ノードのテキストコンテンツを表す文字列、またはノードにテキストコンテンツがない場合はnullを返します。
サンプルコード
PHP DOMDocument nodeValue 取得
1<?php 2 3/** 4 * Dom\Entity::nodeValue の使用方法を実演する関数。 5 * 6 * この関数は、DTD (Document Type Definition) に定義されたエンティティから 7 * その nodeValue プロパティを取得する方法を示します。 8 * nodeValue は、エンティティの定義値(置き換え文字列)を返します。 9 * 10 * 注意: PHP 8で導入されたDom名前空間のクラス (例: Dom\Entity) は、 11 * 従来のDOM拡張のクラス (例: DOMEntity) の現代的な代替ですが、 12 * 多くの既存のDOM操作関数は引き続きDOM*クラスのインスタンスを返します。 13 * このサンプルコードでは、従来のDOM拡張から取得されるDOMEntityオブジェクトを使用していますが、 14 * nodeValue プロパティの振る舞いは Dom\Entity と共通です。 15 */ 16function demonstrateDomEntityNodeValue(): void 17{ 18 // DTDにエンティティが定義されたXML文字列を作成します。 19 // <!ENTITY name "value"> の形式でエンティティを定義します。 20 $xmlString = <<<XML 21<?xml version="1.0" encoding="UTF-8"?> 22<!DOCTYPE root [ 23 <!ENTITY company "Example Solutions Inc."> 24 <!ENTITY year "2023"> 25]> 26<root> 27 <copyright>&company; &year;</copyright> 28 <product>My Awesome App</product> 29</root> 30XML; 31 32 // DOMDocument オブジェクトを生成し、XMLをロードします。 33 $dom = new DOMDocument('1.0', 'UTF-8'); 34 $dom->loadXML($xmlString); 35 36 // ドキュメントタイプ (DOCTYPE) ノードを取得します。 37 // DOCTYPEノードは、DTD情報(エンティティ定義など)を含んでいます。 38 $doctype = $dom->doctype; 39 40 if ($doctype && $doctype->entities) { 41 echo "DOCTYPEからエンティティ情報を取得します。\n\n"; 42 43 // 'company' という名前のエンティティを取得します。 44 // entities プロパティは DOMNamedNodeMap を返し、そこから DOMEntity オブジェクトを取得します。 45 $entityCompany = $doctype->entities->getNamedItem('company'); 46 47 if ($entityCompany instanceof DOMEntity) { 48 echo "エンティティ名: " . $entityCompany->nodeName . "\n"; 49 // Dom\Entity (または DOMEntity) の nodeValue は、エンティティの定義値(置き換え文字列)を返します。 50 echo "nodeValue (定義値): " . $entityCompany->nodeValue . "\n"; 51 echo "----------------------------------------\n"; 52 } else { 53 echo "'company' エンティティが見つからないか、DOMEntity型ではありません。\n"; 54 } 55 56 // 'year' という名前のエンティティも同様に取得します。 57 $entityYear = $doctype->entities->getNamedItem('year'); 58 if ($entityYear instanceof DOMEntity) { 59 echo "エンティティ名: " . $entityYear->nodeName . "\n"; 60 echo "nodeValue (定義値): " . $entityYear->nodeValue . "\n"; 61 echo "----------------------------------------\n"; 62 } else { 63 echo "'year' エンティティが見つからないか、DOMEntity型ではありません。\n"; 64 } 65 66 } else { 67 echo "XML文書にDOCTYPEまたはエンティティ定義が見つかりませんでした。\n"; 68 } 69} 70 71// 関数を実行し、結果を出力します。 72demonstrateDomEntityNodeValue();
このサンプルコードは、XMLのDTD(Document Type Definition)で定義されたエンティティから、その値を取得する方法を示しています。PHP 8で導入されたDom\EntityクラスのnodeValueプロパティは、このようなエンティティの定義値を文字列として提供します。
まず、コードはDTDにcompanyやyearといったエンティティが定義されたXML文字列を用意し、それをDOMDocumentオブジェクトにロードします。次に、ロードしたXML文書からDOCTYPEノードを通じてエンティティのリストを取得し、特定の名前(例: company)を持つDOMEntityオブジェクトを取り出します。DOMEntityは、PHP 8で推奨されるDom\EntityクラスとnodeValueプロパティの挙動が共通です。
取得したDOMEntityオブジェクトのnodeValueプロパティを参照すると、そのエンティティがDTD内で定義されている「置き換え文字列」を直接取得できます。例えば、<!ENTITY company "Example Solutions Inc.">と定義されたエンティティからは、"Example Solutions Inc."という文字列が返されます。このプロパティは引数を取らず、エンティティの定義値が文字列(string)として返されますが、もし値が存在しない場合や取得できない場合はnullが返される可能性があります。これにより、XML内で再利用される定義済みテキストの内容をプログラムで簡単に読み取ることが可能になります。
PHP 8ではDOM操作のために新しいDom\名前空間が導入されましたが、既存の多くのDOM関数は引き続き従来のDOM*クラス(例: DOMEntity)のオブジェクトを返します。サンプルコードでもDOMEntityを使用している点に留意してください。Dom\Entity::nodeValueは、DTDで定義されたエンティティの「定義値(置き換え文字列)」を返します。これはエンティティ名そのものではなく、エンティティに置き換えられる内容を指します。DOCTYPEやエンティティが未定義の場合、または指定のエンティティが存在しない場合はnullを返す可能性があるため、nodeValueを利用する前には必ず値の存在チェックを行うようにしてください。取得したオブジェクトがDOMEntity型であるかinstanceofで確認すると、より安全に処理を進められます。
nodeValueとtextContentの違いを理解する
1<?php 2 3/** 4 * DOMNodeのnodeValueとtextContentプロパティの違いを比較して表示します。 5 * 6 * `nodeValue` と `textContent` は、どちらもノードに関連するテキストを取得しますが、 7 * どのノードから値を取得するかによって挙動が大きく異なります。 8 * このサンプルコードは、その違いを明確に示します。 9 */ 10function demonstrateNodeValueVsTextContent(): void 11{ 12 // 比較用のXML文字列を準備 13 $xmlString = <<<XML 14 <?xml version="1.0" encoding="UTF-8"?> 15 <article> 16 <title>PHPの基本</title> 17 <content> 18 これは本文です。<b>重要</b>な部分も含まれます。 19 </content> 20 <!-- 2023-10-27 draft --> 21 </article> 22 XML; 23 24 // DOMDocumentオブジェクトを作成し、XMLを読み込む 25 $dom = new DOMDocument(); 26 $dom->loadXML($xmlString); 27 28 // --- 比較1: 子要素を持つ要素ノード (<content>) --- 29 // <content>要素は、内部にテキストノードと<b>要素を持っています。 30 $contentElement = $dom->getElementsByTagName('content')->item(0); 31 32 echo "■ 1. 子要素を持つ要素ノード (<content>) での比較:" . PHP_EOL; 33 34 // `nodeValue`は、要素ノード(Element)自体にはテキスト値を持たないため、常にnullを返します。 35 printf( 36 " - nodeValue: %s (要素ノード自体は値を持たないため)\n", 37 json_encode($contentElement->nodeValue) 38 ); 39 40 // `textContent`は、そのノードと、そのすべての子孫ノードのテキストを連結して返します。 41 // この場合、「これは本文です。」「重要」「な部分も含まれます。」が連結されます。 42 printf( 43 " - textContent: %s (子孫のテキストもすべて連結される)\n", 44 json_encode(trim(preg_replace('/\s+/', ' ', $contentElement->textContent))) 45 ); 46 47 echo PHP_EOL; 48 49 // --- 比較2: テキストノード (<title>の中身) --- 50 // <title>要素の最初の子ノードであるテキストノード「PHPの基本」を取得します。 51 $titleTextNode = $dom->getElementsByTagName('title')->item(0)->firstChild; 52 53 echo "■ 2. テキストノード (「PHPの基本」) での比較:" . PHP_EOL; 54 55 // テキストノードやコメントノードの場合、`nodeValue`と`textContent`は同じ値を返します。 56 printf( 57 " - nodeValue: %s\n", 58 json_encode($titleTextNode->nodeValue) 59 ); 60 printf( 61 " - textContent: %s\n", 62 json_encode($titleTextNode->textContent) 63 ); 64} 65 66// 関数を実行して結果を表示します 67demonstrateNodeValueVsTextContent();
Dom\EntityクラスのnodeValueプロパティは、DOMツリー内のノードが持つ値を取得するために使用します。このプロパティに引数はなく、ノードの種類に応じてその値の文字列、または値を持たない場合はnullを返します。
nodeValueの挙動を理解するには、よく似たtextContentプロパティとの違いを知ることが重要です。サンプルコードの<content>のような要素ノードに対してnodeValueを使用すると、要素ノード自体はテキスト値を持たないため、常にnullが返されます。一方、textContentは、その要素が内包するすべての子孫ノードのテキストを連結した文字列を返します。
これに対して、サンプルコードの<title>内の「PHPの基本」のようなテキストノードの場合、nodeValueとtextContentはどちらも同じ挙動を示し、そのノードが持つテキスト文字列そのものを返します。
このようにnodeValueは、テキストノードやコメントノードなど、それ自体が固有の値を持つ特定のノードから直接値を取得する際に利用します。要素全体のテキストを構造を無視して取得したい場合はtextContentが適しています。
nodeValueプロパティは、扱うノードの種類によって挙動が大きく変わる点に注意が必要です。サンプルコードの<content>のような要素ノード(タグ)に対してnodeValueを使用すると、常にnullが返されます。これは要素ノード自体がテキスト値を持たないためで、初心者がテキストを取得する際に間違いやすいポイントです。一方、テキストノードやコメントノードに対しては、その内容の文字列を返します。タグ内の子要素も含めた全てのテキストをまとめて取得したい場合はtextContentを、特定のテキストノードの値だけが必要な場合はnodeValueを使う、という使い分けを意識しましょう。nodeValueはnullを返す可能性があるため、取得した値を利用する前にはnullチェックを行うと、より安全なコードになります。
PHP Dom\Entity nodeValue 取得
1<?php 2 3/** 4 * Dom\Entity クラスの nodeValue プロパティの基本的な使用方法を示します。 5 * 6 * Dom\Entity は抽象クラスであり、Dom\Element, Dom\Attr, Dom\Text, Dom\Comment, 7 * Dom\CDATASection などの具体的なノードクラスがこれを継承しています。 8 * nodeValue プロパティは、ノードの種類によって異なる値を返します。 9 * 10 * - Dom\Text: テキストノードの内容 11 * - Dom\Attr: 属性の値 12 * - Dom\Element: 通常は null (要素の子ノードの結合されたテキストコンテンツは textContent プロパティで取得) 13 * - Dom\Comment: コメントの内容 14 * - Dom\CDATASection: CDATAセクションの内容 15 */ 16function demonstrateDomNodeValue(): void 17{ 18 // サンプルXML文字列を定義します。 19 $xmlString = <<<XML 20<root> 21 <item id="unique-id"> 22 これはアイテムのテキストです。 23 <!-- これはコメントです --> 24 </item> 25 <data><![CDATA[これはCDATAセクションです。<bold>HTMLタグもそのまま</bold>]]></data> 26</root> 27XML; 28 29 // Dom\Document オブジェクトを作成し、XMLを読み込みます。 30 $document = new Dom\Document(); 31 $document->loadXML($xmlString); 32 33 echo "--- 1. Dom\\Element の nodeValue ---" . PHP_EOL; 34 // 'item' 要素を取得します。 35 $itemElement = $document->getElementsByTagName('item')->item(0); 36 if ($itemElement instanceof Dom\Element) { 37 // Dom\Element の nodeValue は通常 null を返します。 38 // 要素のテキストコンテンツをまとめて取得するには、textContent プロパティを使用するのが一般的です。 39 echo "要素 <item> の nodeValue: " . var_export($itemElement->nodeValue, true) . PHP_EOL; 40 echo "要素 <item> の textContent: " . $itemElement->textContent . PHP_EOL; 41 } 42 43 echo PHP_EOL . "--- 2. Dom\\Attr の nodeValue ---" . PHP_EOL; 44 // 'item' 要素の 'id' 属性ノードを取得します。 45 if ($itemElement instanceof Dom\Element) { 46 $idAttribute = $itemElement->getAttributeNode('id'); 47 if ($idAttribute instanceof Dom\Attr) { 48 // Dom\Attr の nodeValue は属性の値を返します。 49 echo "属性 'id' の nodeValue: " . $idAttribute->nodeValue . PHP_EOL; 50 } 51 } 52 53 echo PHP_EOL . "--- 3. Dom\\Text の nodeValue ---" . PHP_EOL; 54 // 'item' 要素の子であるテキストノードを取得します。 55 // XML整形による改行もテキストノードとして扱われるため、空白でないノードを探します。 56 if ($itemElement instanceof Dom\Element) { 57 foreach ($itemElement->childNodes as $node) { 58 if ($node instanceof Dom\Text && trim($node->nodeValue) !== '') { 59 echo "テキストノードの nodeValue: " . $node->nodeValue . PHP_EOL; 60 break; // 最初の有効なテキストノードで終了 61 } 62 } 63 } 64 65 echo PHP_EOL . "--- 4. Dom\\Comment の nodeValue ---" . PHP_EOL; 66 // 'item' 要素の子であるコメントノードを取得します。 67 if ($itemElement instanceof Dom\Element) { 68 foreach ($itemElement->childNodes as $node) { 69 if ($node instanceof Dom\Comment) { 70 // Dom\Comment の nodeValue はコメントの内容を返します。 71 echo "コメントノードの nodeValue: " . $node->nodeValue . PHP_EOL; 72 break; 73 } 74 } 75 } 76 77 echo PHP_EOL . "--- 5. Dom\\CDATASection の nodeValue ---" . PHP_EOL; 78 // 'data' 要素の子であるCDATAセクションノードを取得します。 79 $dataElement = $document->getElementsByTagName('data')->item(0); 80 if ($dataElement instanceof Dom\Element) { 81 $cdataNode = $dataElement->firstChild; 82 if ($cdataNode instanceof Dom\CDATASection) { 83 // Dom\CDATASection の nodeValue はCDATAセクションの内容を返します。 84 echo "CDATASection の nodeValue: " . $cdataNode->nodeValue . PHP_EOL; 85 } 86 } 87} 88 89// 関数を実行します。 90demonstrateDomNodeValue();
PHPのDom\Entity::nodeValueプロパティは、XMLやHTMLドキュメントの構造を扱うDOM拡張機能において、各ノードの具体的な「値」を取得するために使用されます。このプロパティは引数を取らず、戻り値としてstring型またはnullを返します。Dom\Entityは抽象クラスですが、これを継承するDom\Text、Dom\Attr、Dom\Comment、Dom\CDATASectionなどの具体的なノードクラスでその挙動が異なります。
具体的には、Dom\Textノードではそのテキストコンテンツ、Dom\Attrノードでは属性値、Dom\Commentノードではコメントの内容、Dom\CDATASectionノードではCDATAセクションの内容が取得されます。一方、Dom\Elementノードの場合、nodeValueは通常nullを返します。要素の持つテキストコンテンツをまとめて取得したい場合は、代わりにtextContentプロパティを利用するのが一般的です。このようにnodeValueは、ノードの種類に応じて異なる内容を提供するため、DOM操作でノードの詳細な情報を参照する際に非常に重要な役割を果たします。
Dom\EntityクラスのnodeValueプロパティは、ノードの種類によって返される値が異なりますので注意が必要です。特にDom\Element(要素)の場合、通常はnullを返します。要素内のすべてのテキストコンテンツをまとめて取得したい場合は、textContentプロパティを使用するのが一般的で適切です。一方、Dom\Attr(属性)、Dom\Text(テキスト)、Dom\Comment(コメント)、Dom\CDATASection(CDATAセクション)などのノードでは、それぞれの内容が文字列として返されます。このプロパティの戻り値はstringまたはnullであるため、値を扱う際はnullチェックを行い、nullが返される可能性を考慮したコードを記述することが、予期せぬエラーを防ぐために重要です。