【PHP8.x】Dom\Entity::childNodesプロパティの使い方
childNodesプロパティの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
childNodesプロパティは、Dom\Entityオブジェクトが持つ子ノードのリストを保持するプロパティです。Dom\Entityは、XMLやHTMLドキュメント内で定義された実体(エンティティ)を表す特殊なノードです。例えば、XMLドキュメントのDTD(Document Type Definition)で定義されたエンティティがドキュメント内で参照された場合、そのエンティティの実体の内容がパースされ、その結果として生じる子ノード群がこのchildNodesプロパティによって提供されます。
このプロパティが保持する値は、Dom\NodeListオブジェクトです。Dom\NodeListは、読み取り専用のノードのコレクションであり、エンティティの実体に含まれるすべての子要素やテキストノードなどを、定義された順序で参照することを可能にします。これにより、エンティティが実際に展開されたときにどのような構造や内容を持つのかをプログラムから詳細に調べることができます。
具体的には、ドキュメント内でエンティティ参照を見つけ、その実体がどのような構成になっているかを解析したい場合に、このchildNodesプロパティを利用します。例えば、エンティティが複数のテキストノードや要素ノードから構成されている場合、それらのノードにアクセスして内容を抽出したり、特定の条件に基づいて処理を行ったりする際に非常に有用です。このプロパティは、複雑なXMLドキュメントの構造を理解し、その中から特定の情報を抽出する作業において、重要な役割を果たします。
構文(syntax)
1<?php 2$document = new Dom\Document(); 3$document->loadXML('<!DOCTYPE root [<!ENTITY myentity "entity content">]><root/>'); 4$entity = $document->doctype->entities->item(0); 5 6$childNodesList = $entity->childNodes;
引数(parameters)
引数なし
引数はありません
戻り値(return)
Dom\NodeList
Dom\Entity オブジェクトの子ノードのリストを Dom\NodeList オブジェクトとして返します。
サンプルコード
PHP DOM childNodesでエンティティ子ノード表示
1<?php 2 3/** 4 * Dom\EntityのchildNodesプロパティの使用例を示します。 5 * 6 * この関数は、DTD(文書型定義)で宣言されたエンティティを取得し、 7 * そのエンティティが持つ子ノードのリストを走査して情報を表示します。 8 */ 9function displayEntityChildNodes(): void 10{ 11 // DTDでエンティティを定義したXML文字列。 12 // エンティティ'user_info'は、テキストノードと要素ノード(<b>)を含んでいます。 13 $xmlString = <<<XML 14 <?xml version="1.0" encoding="UTF-8"?> 15 <!DOCTYPE profile [ 16 <!ENTITY user_info "Name: Alex, Role: <b>Developer</b>."> 17 ]> 18 <profile> 19 <user>&user_info;</user> 20 </profile> 21 XML; 22 23 // DOMDocumentオブジェクトを生成します 24 $doc = new DOMDocument(); 25 26 // DTDをロードするためにオプションを指定してXMLを読み込みます 27 // このオプションがないと、doctypeプロパティがnullになる場合があります 28 $doc->loadXML($xmlString, LIBXML_DTDLOAD); 29 30 // DocumentTypeノード (<!DOCTYPE ...> の部分) を取得します 31 $doctype = $doc->doctype; 32 if ($doctype === null) { 33 echo "DOCTYPEが見つかりません。" . PHP_EOL; 34 return; 35 } 36 37 // 'entities'プロパティから、宣言されたエンティティのリストを取得します 38 // これは DOMNamedNodeMap を返します 39 $entities = $doctype->entities; 40 41 // 名前を指定して 'user_info' エンティティ(Dom\Entity)を取得します 42 /** @var DOMEntity|null $entity */ 43 $entity = $entities->getNamedItem('user_info'); 44 if ($entity === null) { 45 echo "エンティティ 'user_info' が見つかりませんでした。" . PHP_EOL; 46 return; 47 } 48 49 echo "エンティティ '{$entity->nodeName}' の子ノード一覧:" . PHP_EOL; 50 echo "-----------------------------------------" . PHP_EOL; 51 52 // childNodesプロパティで子ノードのリスト(Dom\NodeList)を取得します 53 $childNodes = $entity->childNodes; 54 55 // 子ノードが存在するかチェックします 56 if ($childNodes->length > 0) { 57 // NodeListをループして、各子ノードの情報を表示します 58 foreach ($childNodes as $index => $child) { 59 /** @var DOMNode $child */ 60 // nodeType 3はテキストノード、1は要素ノードです 61 echo sprintf( 62 "[%d] NodeType: %-2d | NodeName: %-8s | NodeValue: '%s'\n", 63 $index, 64 $child->nodeType, 65 $child->nodeName, 66 trim($child->nodeValue ?? $child->textContent) 67 ); 68 } 69 } else { 70 echo "子ノードはありません。" . PHP_EOL; 71 } 72} 73 74// 関数を実行して結果を表示します 75displayEntityChildNodes(); 76
Dom\EntityクラスのchildNodesプロパティは、XMLのDTD(文書型定義)で定義されたエンティティが持つ子ノードのリストを取得するために使用します。このプロパティは引数を取らず、戻り値として子ノードの集合であるDom\NodeListオブジェクトを返します。
サンプルコードでは、まずDTD内でuser_infoという名前のエンティティを定義したXML文字列を用意しています。このエンティティは、テキストと<b>要素で構成されています。次にDOMDocumentオブジェクトを使ってこのXMLを読み込み、getNamedItemメソッドでuser_infoエンティティ(Dom\Entityオブジェクト)を取得します。
続いて、$entity->childNodesという形でchildNodesプロパティにアクセスし、エンティティが持つすべての子ノードをDom\NodeListとして取得します。このNodeListは配列のようにforeachループで処理できるため、各子ノードを順番に取り出し、その種類(nodeType)、名前(nodeName)、値(nodeValue)を表示しています。この結果、user_infoエンティティが「テキストノード」と「b要素ノード」から構成されていることがわかります。このようにchildNodesプロパティは、エンティティの内部構造をプログラムで詳細に分析する際に役立ちます。
childNodesプロパティは、要素だけでなくテキストノードも含むDom\NodeListを返します。改行やインデントのための空白文字もテキストノードとして認識されるため、ループ処理では意図しないノードが含まれる可能性に注意が必要です。サンプルにあるようにDTDで定義されたエンティティを扱うには、loadXMLメソッドの第二引数にLIBXML_DTDLOAD定数を指定することが不可欠です。これを忘れるとエンティティが正しく読み込まれません。また、doctypeプロパティやgetNamedItemメソッドは対象が見つからない場合にnullを返すため、必ずnullチェックを行いましょう。要素ノードのnodeValueはnullになるため、テキスト内容を取得するにはtextContentプロパティの利用が適切です。