【PHP8.x】DOMEntity::nodeValueプロパティの使い方
nodeValueプロパティの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
nodeValueプロパティは、DOMEntityクラスに属し、ノードの値を保持するプロパティです。DOMEntityクラスは、XMLやHTMLドキュメント内で使用される実体(Entity)の定義を表すノードです。通常、このnodeValueプロパティはノードのテキスト内容を保持しますが、DOMEntityクラスのインスタンスにおいては、その振る舞いが特殊です。
DOMEntityのnodeValueプロパティは、常にNULLを返します。これは、DOMEntityノード自体が実体参照の「定義」や「宣言」であり、それ自身が直接的なテキスト内容を持っているわけではないためです。実体参照が指し示す具体的なテキストや構造は、ドキュメントの解析時に展開され、別のノードとして扱われることが一般的です。したがって、DOMEntityのnodeValueプロパティにアクセスしても、実体が展開された後のテキスト内容を直接取得することはできません。このプロパティは読み取り専用であり、NULL以外の値を設定しようとするとエラーが発生しますのでご注意ください。PHPのDOM拡張機能でDOMEntityノードを扱う際は、このnodeValueプロパティが常にNULLを返すという点を理解しておくことが重要です。
構文(syntax)
1<?php 2$xmlString = '<!DOCTYPE root [<!ENTITY myEntity "This is the entity replacement text.">]><root/>'; 3 4$dom = new DOMDocument(); 5$dom->loadXML($xmlString); 6 7$entities = $dom->doctype->entities; 8 9if ($entities->length > 0) { 10 /** @var DOMEntity $entity */ 11 $entity = $entities->item(0); // DTDから最初のDOMEntityノードを取得 12 13 // DOMEntityのnodeValueプロパティは、エンティティの置換テキストを返します。 14 echo $entity->nodeValue; 15} 16?>
引数(parameters)
引数なし
引数はありません
戻り値(return)
?string
DOMEntityオブジェクトのノード値を返します。ノード値が存在しない場合はnullが返されます。
サンプルコード
PHP DOMEntityのnodeValueを取得する
1<?php 2 3/** 4 * DOMEntityのnodeValueプロパティの例を示します。 5 * 6 * DOMEntityのnodeValueは、仕様上常にnullを返します。 7 * このサンプルでは、XML文書内のDTDで定義されたエンティティを取得し、 8 * そのnodeValueがnullであることを確認します。 9 */ 10function demonstrateDomEntityNodeValue(): void 11{ 12 // DTDでエンティティが定義されたXML文字列 13 $xmlString = <<<XML 14<?xml version="1.0" encoding="utf-8"?> 15<!DOCTYPE book [ 16 <!ENTITY authorName "Sample Author"> 17]> 18<book> 19 <title>Sample Book</title> 20 <author>&authorName;</author> 21</book> 22XML; 23 24 // DOMDocumentオブジェクトを作成 25 $dom = new DOMDocument(); 26 27 // XML文字列を読み込む 28 $dom->loadXML($xmlString); 29 30 // ドキュメントタイプ定義 (DTD) を取得 31 $doctype = $dom->doctype; 32 33 // DTDから 'authorName' という名前のエンティティノード (DOMEntity) を取得 34 // $doctype->entities はエンティティのリスト (DOMNamedNodeMap) を保持しています 35 $entity = $doctype->entities->getNamedItem('authorName'); 36 37 // DOMEntityのプロパティを出力 38 // nodeNameにはエンティティ名が格納されています 39 echo 'Node Name: ' . $entity->nodeName . PHP_EOL; 40 41 // nodeValueはDOMEntityの場合、常にnullを返します 42 echo 'Node Value: '; 43 var_dump($entity->nodeValue); 44} 45 46// 関数を実行 47demonstrateDomEntityNodeValue();
このPHPサンプルコードは、XMLのエンティティを表すDOMEntityオブジェクトのnodeValueプロパティの動作を解説します。nodeValueプロパティは、ノードが持つ値を取得するためのものですが、DOMEntityクラスで用いる場合は特殊な挙動を示します。
コードではまず、DTD(文書型定義)で authorName というエンティティを定義したXML文字列を準備します。次にDOMDocumentクラスでこのXMLを読み込み、doctypeプロパティを通じてauthorNameという名前のDOMEntityオブジェクトを取得します。
DOMEntityオブジェクトのnodeNameプロパティは、エンティティ名(この場合は authorName)を文字列として返します。一方、nodeValueプロパティは、仕様により常にnullを返すように定められています。これは、エンティティ自体が値を持つのではなく、その置換内容は子ノードとして表現されるためです。サンプルコードの実行結果でvar_dump()の出力がNULLとなることで、この仕様を確認できます。
このように、DOMEntityのnodeValueプロパティは引数を取らず、戻り値は常にnullとなります。
DOMEntityのnodeValueプロパティは、エンティティで定義された値(サンプルの "Sample Author")を返すわけではなく、仕様上常にnullを返す点に注意が必要です。エンティティの値を取得したい場合は、nodeValueの代わりに、そのエンティティノードが持つ子ノード(childNodes)を調べる必要があります。また、このサンプルはXML文書内にDTD(文書型定義)とエンティティ定義が存在することが前提です。$dom->doctypeや$doctype->entities->getNamedItem()は対象が存在しない場合にnullを返す可能性があるため、実際の開発では戻り値を確認してからプロパティにアクセスすると、エラーを防ぐことができ安全です。
PHP nodeValueでHTML要素の値を取得する
1<?php 2 3declare(strict_types=1); 4 5/** 6 * 指定されたHTML文字列からDOMを構築し、要素のnodeValueを取得して表示します。 7 * 8 * DOMElementのnodeValueは、その要素が持つすべての子孫テキストノードの値を 9 * 連結したものを返します。これは、textContentプロパティと同じ値です。 10 * 一方、DOMTextノードのnodeValueは、そのノード自身のテキスト内容を返します。 11 */ 12function displayHtmlNodeValue(): void 13{ 14 // 解析対象のHTML文字列 15 $html = <<<HTML 16 <!DOCTYPE html> 17 <html lang="ja"> 18 <head> 19 <title>サンプル</title> 20 </head> 21 <body> 22 <p>これは<strong>重要</strong>なテキストです。</p> 23 </body> 24 </html> 25 HTML; 26 27 // DOMDocumentオブジェクトを初期化 28 $dom = new DOMDocument(); 29 30 // HTMLのパース時に発生する警告を抑制するため、内部エラー処理を有効化 31 libxml_use_internal_errors(true); 32 // HTML文字列を読み込む 33 $dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); 34 // エラー情報をクリア 35 libxml_clear_errors(); 36 37 // pタグを取得する (DOMNodeList) 38 $pElements = $dom->getElementsByTagName('p'); 39 // 最初のp要素を取得する (DOMElement) 40 $pElement = $pElements->item(0); 41 42 // p要素が存在する場合 43 if ($pElement instanceof DOMElement) { 44 // DOMElementのnodeValueは、子要素のタグを除いたテキストコンテンツ全体を返す 45 echo "--- p要素 (DOMElement) の nodeValue ---\n"; 46 echo $pElement->nodeValue . "\n\n"; // 出力: これは重要なテキストです。 47 48 // p要素の直接の子ノードをループして、それぞれのnodeValueを確認する 49 echo "--- p要素の各子ノード (childNodes) の nodeValue ---\n"; 50 foreach ($pElement->childNodes as $childNode) { 51 // ノードのクラス名を取得 52 $nodeClass = get_class($childNode); 53 // ノードの値をエスケープして表示 54 $nodeValue = htmlspecialchars(trim($childNode->nodeValue), ENT_QUOTES, 'UTF-8'); 55 56 // テキストノードと要素ノードでnodeValueが何を指すかを示す 57 if (!empty($nodeValue)) { 58 echo "{$nodeClass}: 「{$nodeValue}」\n"; 59 } 60 } 61 } 62} 63 64// 関数を実行 65displayHtmlNodeValue();
PHPのnodeValueプロパティは、HTML文書などを構成する各ノードが持つ値を取得するために使用します。このプロパティは引数を取らず、戻り値としてノードの値を文字列で返しますが、値が存在しないノードの場合はnullを返すことがあります。
nodeValueが返す値は、対象となるノードの種類によって大きく異なります。サンプルコードの<p>タグのような要素ノード(DOMElement)に対して使用した場合、その要素が内包するすべての子孫ノードのテキストを連結した文字列を返します。このとき、<strong>などのHTMLタグ自体は結果に含まれません。これにより、画面に表示されるテキスト全体を一度に取得できます。
一方で、「これは」や「なテキストです。」といった文字列そのものを表すテキストノード(DOMText)に対してnodeValueを使用すると、そのノードが持つ純粋なテキスト文字列そのものが返されます。このようにnodeValueは、要素全体のテキストをまとめて抽出したいのか、あるいは個別のテキスト部分だけを扱いたいのかによって、どの種類のノードに対して使用するかを意識することが重要なプロパティです。
DOMElementのnodeValueプロパティは、<strong>のような子要素のHTMLタグは含まず、その要素が持つ全ての子孫テキストを連結した文字列を返します。一方、テキストそのものを表すDOMTextノードのnodeValueは、そのノード自身のテキスト内容を返します。このように、ノードの種類によってnodeValueが示す範囲が異なる点に注意が必要です。また、nodeValueはノードの種類によってはnullを返す可能性があるため、取得した値を利用する前にはnullでないか確認すると、より安全なコードになります。日本語などのマルチバイト文字を扱う際は、文字化けを防ぐためにHTMLの文字エンコーディングを正しく指定することも重要です。