【PHP8.x】Dom\EntityReference::nodeValueプロパティの使い方
nodeValueプロパティの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
nodeValueプロパティは、Dom\EntityReferenceオブジェクトが表すノードの値を保持するプロパティです。ただし、エンティティ参照ノードの特性上、このプロパティは常にnullを返します。エンティティ参照(例: ©)は、それ自体が具体的なテキスト値を持つのではなく、ドキュメント型定義(DTD)などで定義された置換テキストへの参照を示す役割を持つためです。したがって、このノード自身の値は存在しないと解釈され、nodeValueはnullとなります。このプロパティは読み取り専用であり、値を代入しようとしても無視されます。もしエンティティ参照が展開された後の実際のテキスト内容を取得したい場合は、childNodesプロパティなどを介して子ノードのリストにアクセスし、そこに含まれるテキストノードなどのnodeValueプロパティを参照する必要があります。このように、nodeValueプロパティの挙動はノードの型によって異なり、Dom\EntityReferenceの場合は常にnullを返すという点を理解しておくことが重要です。
構文(syntax)
1<?php 2 3$doc = new DOMDocument(); 4 5// "example" という名前のエンティティ参照ノードを作成します。 6$entityRef = $doc->createEntityReference("example"); 7 8// Dom\EntityReference の nodeValue プロパティにアクセスします。 9// このプロパティの値は常に null です。 10$value = $entityRef->nodeValue; 11 12var_dump($value);
引数(parameters)
引数なし
引数はありません
戻り値(return)
string|null
Dom\EntityReference クラスの nodeValue プロパティは、指定されたノードのテキストコンテンツを文字列として返します。ノードにテキストコンテンツがない場合は null を返します。
サンプルコード
PHP DOM: EntityReferenceのnodeValueを調べる
1<?php 2 3/** 4 * DOMEntityReferenceのnodeValueプロパティの動作を確認するサンプル関数 5 * 6 * XMLドキュメント内のエンティティ参照ノードを取得し、 7 * そのnodeValueプロパティの値を出力します。 8 * DOMEntityReferenceのnodeValueは常にnullを返します。 9 */ 10function demonstrateEntityReferenceNodeValue(): void 11{ 12 // エンティティを含むXML文字列を定義 13 // DTD(文書型定義)で 'author' というエンティティを宣言 14 $xmlString = <<<XML 15 <?xml version="1.0" encoding="UTF-8"?> 16 <!DOCTYPE book [ 17 <!ENTITY author "John Doe"> 18 ]> 19 <book> 20 <title>PHP DOM Guide</title> 21 <author>&author;</author> 22 </book> 23 XML; 24 25 // DOMDocumentオブジェクトを作成 26 $dom = new DOMDocument(); 27 28 // エンティティ参照を展開せず、DOMEntityReferenceノードとして保持するように設定 29 // このオプションがfalseでないと、エンティティ参照(&author;)は 30 // その置換テキスト("John Doe")に置き換えられてしまいます。 31 $dom->substituteEntities = false; 32 33 // XML文字列を読み込む 34 $dom->loadXML($xmlString); 35 36 // 'author'タグを取得 37 $authorElement = $dom->getElementsByTagName('author')->item(0); 38 39 // 'author'タグの子ノード(エンティティ参照ノード)を取得 40 // $authorElement->childNodes[0] が DOMEntityReference オブジェクトに該当 41 $entityRefNode = $authorElement->childNodes->item(0); 42 43 // ノードがDOMEntityReferenceであるかを確認 44 if ($entityRefNode instanceof DOMEntityReference) { 45 echo 'ノードのクラス: ' . get_class($entityRefNode) . PHP_EOL; 46 // nodeNameにはエンティティ名('author')が格納される 47 echo 'nodeName: ' . $entityRefNode->nodeName . PHP_EOL; 48 // nodeValueはDOMEntityReferenceの場合、常にnullとなる 49 echo 'nodeValue: '; 50 var_dump($entityRefNode->nodeValue); 51 } 52} 53 54// 関数を実行 55demonstrateEntityReferenceNodeValue(); 56 57?>
このサンプルコードは、PHPのDOMEntityReferenceクラスが持つnodeValueプロパティの動作を解説するものです。nodeValueはノードの値を表すプロパティですが、DOMEntityReferenceオブジェクトの場合、その値は常にnullを返します。
サンプルコードでは、まずDTD(文書型定義)を用いて&author;というエンティティ参照を定義したXML文字列を作成します。次に、DOMDocumentオブジェクトの設定でsubstituteEntitiesプロパティをfalseにしています。これは、&author;のようなエンティティ参照をその置換テキスト(この例では "John Doe")に置き換えず、エンティティ参照ノードとして扱うための重要な設定です。
XMLを読み込んだ後、<author>要素の子ノードとしてDOMEntityReferenceオブジェクトを取得します。このオブジェクトのnodeNameプロパティはエンティティ名であるauthorを返しますが、nodeValueプロパティにアクセスすると、仕様通りnullが出力されます。
このプロパティは値を取得するものであり、引数は取りません。戻り値は、DOMEntityReferenceのコンテキストにおいては常にnullとなります。このように、エンティティ参照自体の値を取得するためのプロパティではない点に注意が必要です。
DOMEntityReferenceノードを扱うには、DOMDocumentオブジェクトのsubstituteEntitiesプロパティをfalseに設定することが不可欠です。この設定を忘れると、エンティティ参照(&author;など)は自動的にその値のテキストに置き換えられてしまい、DOMEntityReferenceノード自体を取得できなくなります。また、DOMEntityReferenceのnodeValueプロパティは仕様上、常にnullを返すという点が重要です。エンティティが参照している実際の値はここには格納されていません。nodeNameプロパティにはエンティティ名が格納されるため、この違いを理解しておきましょう。エンティティの値を取得したい場合は、親要素のtextContentプロパティなどを参照する必要があります。
PHP DOM nodeValueとtextContentを比較する
1<?php 2 3/** 4 * DOMにおける nodeValue と textContent プロパティの違いを比較します。 5 * 6 * `nodeValue` はノード自身の直接的な値を返します。 7 * 要素ノード(DOMElement)の場合、これは常に null です。 8 * 値を持つのはテキストノードや属性ノードなどです。 9 * 10 * `textContent` は、そのノードとすべての子孫ノードに含まれるテキストを 11 * 連結した文字列を返します。HTML/XMLタグは除去されます。 12 */ 13function compareNodeValueAndTextContent(): void 14{ 15 // 比較用のシンプルなXML文字列を準備します。 16 // <greeting>要素は、テキストノードと子要素<b>を内包しています。 17 $xmlString = '<root><greeting>Hello, <b>World</b>!</greeting></root>'; 18 19 // DOMDocumentオブジェクトを生成し、XMLを読み込みます。 20 $dom = new DOMDocument(); 21 $dom->loadXML($xmlString); 22 23 // <greeting>要素ノードを取得します。 24 // item(0) は最初に見つかった要素を取得します。 25 $greetingElement = $dom->getElementsByTagName('greeting')->item(0); 26 27 // --- 比較1: 要素ノード (<greeting>) --- 28 29 // 要素ノードの`nodeValue`は、値を持たないため null になります。 30 echo '要素ノードの nodeValue:' . PHP_EOL; 31 var_dump($greetingElement->nodeValue); 32 // 出力: NULL 33 34 echo PHP_EOL; 35 36 // 要素ノードの`textContent`は、子孫のテキストを連結した値 "Hello, World!" になります。 37 echo '要素ノードの textContent:' . PHP_EOL; 38 var_dump($greetingElement->textContent); 39 // 出力: string(14) "Hello, World!" 40 41 echo PHP_EOL; 42 43 // --- 比較2: テキストノード ("Hello, ") --- 44 45 // <greeting>要素の最初の子ノードであるテキストノードを取得します。 46 $textNode = $greetingElement->firstChild; 47 48 // テキストノードの`nodeValue`は、そのノードのテキスト自体 "Hello, " を返します。 49 echo 'テキストノードの nodeValue:' . PHP_EOL; 50 var_dump($textNode->nodeValue); 51 // 出力: string(7) "Hello, " 52 53 echo PHP_EOL; 54 55 // テキストノードの`textContent`も、`nodeValue`と同じ値を返します。 56 echo 'テキストノードの textContent:' . PHP_EOL; 57 var_dump($textNode->textContent); 58 // 出力: string(7) "Hello, " 59} 60 61// 関数を実行して結果を確認します。 62compareNodeValueAndTextContent();
このPHPサンプルコードは、XMLやHTMLのデータを操作する際に使われる nodeValue と textContent という二つのプロパティの違いを解説するものです。
nodeValue プロパティは、選択したノードが持つ直接的な値を文字列として返します。引数はありません。サンプルコードで示されているように、<greeting>のような要素ノード自体はテキスト値を持たないため、このプロパティで値を取得しようとすると null が返されます。一方で、"Hello, " のようなテキストノードに対して使用すると、その文字列そのものが返されます。
それに対して textContent プロパティは、選択したノードとそのすべての子孫ノードに含まれるテキスト内容を連結し、一つの文字列として返します。このとき、HTMLやXMLのタグはすべて無視されます。そのため、<greeting>要素に適用すると、その中にあるテキスト "Hello, " と、子要素<b>の中の "World!" が結合された "Hello, World!" という文字列が得られます。
つまり、nodeValue はノード単体の値を取得する場合に使い、textContent は要素のタグを除いた中身全体のテキストをまとめて取得したい場合に用いる、という使い分けができます。
要素ノードからテキストを取得したい場合、nodeValueではなくtextContentを使用してください。サンプルコードが示すように、<div>や<p>のような要素ノード自体のnodeValueは常にnullを返します。これは、nodeValueが値を持つのはテキストノードや属性ノードなどに限定されるためです。一方、textContentは要素とそのすべての子孫に含まれるテキストを連結して取得できるため、タグに囲まれた文字列全体が欲しい場合に便利です。また、getElementsByTagNameなどのメソッドは、対象の要素が見つからない場合にnullを返す可能性があります。そのため、取得したオブジェクトのプロパティにアクセスする前には、nullでないことを確認する習慣をつけると、より安全なコードになります。