【PHP8.x】DOMEntityReference::childNodesプロパティの使い方
childNodesプロパティの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
『childNodesプロパティは、DOMEntityReferenceノードのすべての子ノードのコレクションを保持するプロパティです。このプロパティが返す値はDOMNodeListオブジェクトであり、すべての子ノードが順序付けられたリストとして格納されています。子ノードが存在しない場合、このリストは空になります。childNodesプロパティが返すDOMNodeListは「ライブコレクション」として機能する点が特徴です。これは、元のノードに対して子ノードが追加されたり削除されたりすると、DOMNodeListオブジェクトの内容も自動的にリアルタイムで更新されることを意味します。そのため、常に最新の子ノードの状態にアクセスすることが可能です。ただし、DOMEntityReferenceノードはXMLのエンティティ参照を表しており、DOMツリーが構築される際にその内容に置き換えられるのが一般的です。そのため、仕様上DOMEntityReferenceノード自体が子ノードを持つことはなく、このプロパティは通常、空のDOMNodeListを返します。このプロパティは、より汎用的な親クラスであるDOMNodeから継承された機能です。』
構文(syntax)
1<?php 2// DTDでエンティティを定義したXML文字列を用意 3$xmlString = <<<XML 4<?xml version="1.0" encoding="utf-8"?> 5<!DOCTYPE root [ 6<!ENTITY myEntity "entity text"> 7]> 8<root>&myEntity;</root> 9XML; 10 11// DOMDocumentオブジェクトを作成し、XMLを読み込む 12$doc = new DOMDocument(); 13$doc->loadXML($xmlString); 14 15// root要素の最初の子ノード(エンティティ参照ノード)を取得 16$entityRef = $doc->documentElement->firstChild; // $entityRefはDOMEntityReferenceオブジェクト 17 18// DOMEntityReferenceのchildNodesプロパティにアクセスし、 19// 子ノードのリスト(DOMNodeList)を取得 20$nodeList = $entityRef->childNodes; 21 22// 子ノードリストに含まれるノードの数を出力(この場合は1) 23echo $nodeList->length;
引数(parameters)
引数なし
引数はありません
戻り値(return)
DOMNodeList|null
DOMEntityReferenceオブジェクトの直下にある子ノードのリスト、または子ノードがない場合はnullを返します。
サンプルコード
PHP DOM childNodes でエンティティ参照の子ノードを取得する
1<?php 2 3/** 4 * DOMEntityReferenceのchildNodesプロパティの使用例を示す関数です。 5 * 6 * XML内のエンティティ参照ノード(&writer;)を取得し、 7 * そのchildNodesプロパティにアクセスして、エンティティが展開された後の 8 * 子ノードのリストを表示します。 9 */ 10function demonstrateDomEntityReferenceChildNodes(): void 11{ 12 // DTD(文書型定義) を含むXML文字列を定義します。 13 // DTD内で 'writer' という名前のエンティティを定義しています。 14 // このエンティティは、2つの要素ノードから構成される内容に展開されます。 15 $xmlString = <<<XML 16 <?xml version="1.0" encoding="UTF-8"?> 17 <!DOCTYPE book [ 18 <!ENTITY writer "<firstname>Taro</firstname><lastname>Yamada</lastname>"> 19 ]> 20 <book> 21 <title>PHP DOM Programming</title> 22 <author>&writer;</author> 23 </book> 24 XML; 25 26 // DOMDocumentオブジェクトを作成します。 27 $dom = new DOMDocument(); 28 29 // エンティティ参照ノードをそのまま保持するため、オプションなしでXMLを読み込みます。 30 $dom->loadXML($xmlString); 31 32 // <author>要素を取得します。 33 // item(0)は、見つかった要素リストの最初の要素を返します。 34 $authorElement = $dom->getElementsByTagName('author')->item(0); 35 36 // <author>要素の最初の子ノードはエンティティ参照ノード(&writer;)です。 37 $entityRefNode = $authorElement->firstChild; 38 39 // 取得したノードがDOMEntityReferenceのインスタンスであることを確認します。 40 if ($entityRefNode instanceof DOMEntityReference) { 41 echo "エンティティ参照ノード '&{$entityRefNode->nodeName};' を取得しました。\n"; 42 echo "このノードの childNodes プロパティの内容:\n"; 43 44 // DOMEntityReference::childNodes プロパティにアクセスします。 45 // 戻り値は、エンティティの置換テキストから生成された子ノードの DOMNodeList です。 46 $childNodes = $entityRefNode->childNodes; 47 48 // 子ノードリストをループ処理して、各ノードの情報を出力します。 49 foreach ($childNodes as $child) { 50 // 要素ノード(<firstname>, <lastname>)のみを対象とします。 51 if ($child instanceof DOMElement) { 52 printf( 53 "- NodeName: %s, TextContent: %s\n", 54 $child->nodeName, // ノード名 (e.g., firstname) 55 $child->textContent // ノードのテキスト内容 (e.g., Taro) 56 ); 57 } 58 } 59 } else { 60 echo "エンティティ参照ノードが見つかりませんでした。\n"; 61 } 62} 63 64// 関数を実行して結果を表示します。 65demonstrateDomEntityReferenceChildNodes();
DOMEntityReferenceクラスのchildNodesプロパティは、XML文書内のエンティティ参照が展開された後の中身、つまり子ノードのリストを取得するために使用されます。エンティティ参照とは、&writer;のように、あらかじめ定義された文字列やXML要素の断片を文書内に挿入するための仕組みです。
このサンプルコードでは、まずXMLのDTD(文書型定義)内で&writer;というエンティティを定義しています。このエンティティは、<firstname>と<lastname>という2つの要素で構成されています。
PHPコードでは、XMLを読み込んだ後、<author>要素の子であるエンティティ参照ノード (&writer;) を取得します。そして、そのノードのchildNodesプロパティにアクセスします。このプロパティは引数を取りません。戻り値として、エンティティの定義内容から生成された子ノードの集合であるDOMNodeListオブジェクトが返されます。子ノードが存在しない場合はnullの可能性があります。
最後に、取得したDOMNodeListをforeachでループ処理し、リスト内の各子ノード(この例では<firstname>要素と<lastname>要素)の情報を取り出して表示しています。これにより、エンティティ参照の中身をプログラムで具体的に操作できることがわかります。
DOMEntityReferenceのchildNodesプロパティを利用するには、まずDOMDocument::loadXMLをオプション指定なしで実行し、エンティティ参照をノードとして保持させる必要があります。このプロパティが返すのは、エンティティ参照が展開された後の中身である子ノードのリストです。注意点として、このプロパティは読み取り専用のため、取得したリストを通してXML構造を直接変更することはできません。また、子ノードのリストには要素だけでなく、改行などの空白文字がテキストノードとして含まれることがあります。サンプルコードのように、instanceofでノードの種類をチェックしてから処理を行うと、予期せぬエラーを防ぐことができます。
PHP DOMDocument childNodes でエンティティ参照の子ノードを取得する
1<?php 2 3declare(strict_types=1); 4 5/** 6 * DOMEntityReferenceのchildNodesプロパティの使用例を示します。 7 * 8 * XMLドキュメント内に定義されたエンティティ参照ノードを見つけ、 9 * その子ノード(エンティティが展開された後のノード)の一覧を取得して表示します。 10 */ 11function displayEntityReferenceChildNodes(): void 12{ 13 // DTD(文書型定義)で内部エンティティを定義したXML文字列を作成します。 14 // エンティティ 'content' は '<b>World</b>' というマークアップを含みます。 15 // <message>要素の中に、エンティティ参照 '&content;' を配置します。 16 $xmlString = <<<XML 17 <?xml version="1.0" encoding="UTF-8"?> 18 <!DOCTYPE root [ 19 <!ENTITY content "<b>World</b>"> 20 ]> 21 <root> 22 <message>Hello, &content;!</message> 23 </root> 24 XML; 25 26 // DOMDocumentオブジェクトのインスタンスを生成します。 27 $dom = new DOMDocument(); 28 29 // XML文字列を読み込み、DOMツリーを構築します。 30 // デフォルトのオプションでは、エンティティ参照はDOMEntityReferenceノードとして扱われます。 31 $dom->loadXML($xmlString); 32 33 // <message>要素を取得します。 34 $messageElement = $dom->getElementsByTagName('message')->item(0); 35 36 // <message>要素の子ノードを走査し、エンティティ参照ノードを探します。 37 foreach ($messageElement->childNodes as $node) { 38 // ノードがDOMEntityReferenceのインスタンスであるかを確認します。 39 if ($node instanceof DOMEntityReference) { 40 echo "エンティティ参照ノード (&{$node->nodeName};) を見つけました。\n"; 41 echo "----------------------------------------\n"; 42 43 // DOMEntityReference::childNodes プロパティにアクセスします。 44 // これはエンティティが展開された結果のノードリスト(DOMNodeList)を返します。 45 // この例では '<b>World</b>' がパースされた結果のノードが含まれます。 46 $childNodes = $node->childNodes; 47 48 if ($childNodes && $childNodes->length > 0) { 49 echo "エンティティの子ノード一覧:\n"; 50 51 // DOMNodeListをループして、各子ノードの情報を表示します。 52 foreach ($childNodes as $index => $child) { 53 printf( 54 " [%d] 型: %s, 名前: %s, 値: \"%s\"\n", 55 $index, 56 get_class($child), 57 $child->nodeName, 58 trim($child->nodeValue ?? '') 59 ); 60 } 61 } else { 62 echo "このエンティティに子ノードはありませんでした。\n"; 63 } 64 // 処理が完了したらループを抜けます。 65 break; 66 } 67 } 68} 69 70// 関数を実行して結果を表示します。 71displayEntityReferenceChildNodes(); 72 73?>
PHPのDOMEntityReference::childNodesプロパティは、XMLドキュメント内のエンティティ参照が展開された結果として得られる、子ノードのリストを取得するために使用します。このプロパティに引数はなく、戻り値としてDOMNodeListオブジェクト、または子ノードが存在しない場合はnullを返します。
このサンプルコードでは、まずDTD(文書型定義)で&content;というエンティティを<b>World</b>という内容で定義したXML文字列を作成します。次に、DOMDocumentを使ってこのXMLを読み込みます。このとき、<message>要素内の&content;はDOMEntityReferenceという特殊なノードとして扱われます。
コードは<message>要素の子ノードを順に調べ、DOMEntityReferenceノードを見つけ出します。そして、そのノードのchildNodesプロパティにアクセスします。これにより、エンティティ&content;の中身である<b>World</b>が解析された結果のノード(この場合は<b>要素ノード)がDOMNodeListとして取得できます。最後に、そのリスト内の各ノードの情報を表示しています。このように、childNodesプロパティを使うと、エンティティ参照の具体的な構造にプログラムでアクセスできます。
DOMDocumentでXMLを読み込む際、デフォルト設定ではエンティティ参照がDOMEntityReferenceノードとして扱われます。もしLIBXML_NOENTオプションを指定すると、エンティティは自動的に展開され、このノードは生成されないため注意が必要です。childNodesプロパティは、エンティティが展開された後のノードのリストを返します。サンプルコードの&content;のようにマークアップが含まれている場合、その構造(例:<b>要素)が子ノードとして取得されます。このプロパティの戻り値はDOMNodeListまたはnullになりうるため、使用する前にnullでないことを確認すると、エラーを防ぐことができ安全です。