【PHP8.x】childNodesプロパティの使い方

childNodesプロパティの使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

childNodesプロパティは、あるノードが持つすべての子ノードの集合を保持するプロパティです。このプロパティはDOMDocumentTypeクラスに属しており、XMLやHTML文書における文書型定義(DTD)を表すノードで利用されます。しかし、DOMDocumentTypeノードは、その定義上、子ノードを持つことができないという重要な特性があります。例えば、<!DOCTYPE html>のような文書型宣言は、それ自体が他の要素を内包する構造ではないためです。したがって、DOMDocumentTypeオブジェクトのchildNodesプロパティにアクセスした場合、常に空のDOMNodeListオブジェクトが返されます。この返されたDOMNodeListオブジェクトのlengthプロパティ(要素数)は常に0となります。このプロパティは読み取り専用のため、内容を直接変更することはできません。DOMツリーの階層構造を操作する際に汎用的に提供されているプロパティですが、DOMDocumentTypeにおいては子ノードが存在しないことを示すものとして機能します。

構文(syntax)

1<?php
2
3$xmlString = <<<XML
4<?xml version="1.0" encoding="UTF-8"?>
5<!DOCTYPE greeting [
6    <!ENTITY author "World">
7    <!NOTATION type-jpeg PUBLIC "image/jpeg">
8]>
9<message>Hello, &author;!</message>
10XML;
11
12$dom = new DOMDocument();
13$dom->loadXML($xmlString);
14
15$doctype = $dom->doctype;
16
17// DOMDocumentTypeのchildNodesプロパティにアクセスします。
18// これにはDTD内のノード(エンティティ、ノーテーションなど)のリストが含まれます。
19$nodeList = $doctype->childNodes;
20
21foreach ($nodeList as $child) {
22    echo $child->nodeName . PHP_EOL;
23}
24
25?>

引数(parameters)

引数なし

引数はありません

戻り値(return)

DOMNodeList

DOMDocumentType オブジェクトの子ノードのリストを DOMNodeList オブジェクトとして返します。

サンプルコード

PHP DOM childNodes でDOCTYPEノードを取得する

1<?php
2
3/**
4 * DOMDocumentTypeオブジェクトからchildNodesプロパティを取得し、その内容を表示する関数。
5 *
6 * DOMDocumentType::childNodesプロパティは、DOCTYPE宣言内のエンティティ宣言や記法宣言などを
7 * DOMNodeListとして返します。一般的なHTML5のDOCTYPEでは通常空になりますが、
8 * この例ではDTD内部サブセットを持つXMLを使用し、childNodesに要素が含まれることを示します。
9 */
10function demonstrateDomDocumentTypeChildNodes(): void
11{
12    // 内部DTDサブセットを含むXML文字列を定義します。
13    // このDOCTYPE宣言には、"my_entity" というエンティティ宣言と "gif" という記法宣言が含まれています。
14    $xmlString = <<<XML
15<?xml version="1.0" encoding="UTF-8"?>
16<!DOCTYPE root [
17  <!ENTITY my_entity "このテキストはエンティティです。">
18  <!NOTATION gif SYSTEM "image/gif">
19]>
20<root>
21  <element>&my_entity;</element>
22</root>
23XML;
24
25    $dom = new DOMDocument('1.0', 'UTF-8');
26    // XML文字列をDOMDocumentオブジェクトにロードします。
27    // ロードが成功したかを確認します。
28    if (!$dom->loadXML($xmlString)) {
29        echo "XMLのロードに失敗しました。\n";
30        return;
31    }
32
33    // DOMDocumentオブジェクトからDOCTYPEノードを取得します。
34    // `doctype`プロパティはDOMDocumentTypeオブジェクトを返します。
35    $doctype = $dom->doctype;
36
37    if ($doctype instanceof DOMDocumentType) {
38        echo "--- DOMDocumentType::childNodesのデモンストレーション ---\n";
39        echo "DOCTYPE名: " . $doctype->name . "\n";
40        echo "システムID: " . ($doctype->systemId ?: "なし") . "\n"; // 外部DTDの場所を示すURI (この例では内部DTDなのでなし)
41        echo "公開ID: " . ($doctype->publicId ?: "なし") . "\n";   // 公開識別子 (この例では内部DTDなのでなし)
42
43        // childNodesプロパティにアクセスします。
44        // これはDOCTYPE宣言内で定義されたノードのリスト (DOMNodeList) を返します。
45        $childNodes = $doctype->childNodes;
46
47        echo "\nDOCTYPEの内部サブセットに定義された子ノード数: " . $childNodes->length . "\n";
48
49        if ($childNodes->length > 0) {
50            echo "--- 各子ノードの詳細 ---\n";
51            foreach ($childNodes as $index => $node) {
52                echo "ノード " . ($index + 1) . ":\n";
53                echo "  ノード名: " . $node->nodeName . "\n";
54                echo "  ノードタイプ: " . $node->nodeType . " (" . getNodeTypeName($node->nodeType) . ")\n";
55
56                // DOMEntityノードの場合、その値(エンティティの内容)を表示
57                if ($node instanceof DOMEntity) {
58                    echo "  エンティティ値: " . $node->nodeValue . "\n";
59                }
60                // DOMNotationノードの場合、その属性(システムIDや公開ID)を表示
61                if ($node instanceof DOMNotation) {
62                    echo "  記法システムID: " . ($node->systemId ?: "なし") . "\n";
63                    echo "  記法公開ID: " . ($node->publicId ?: "なし") . "\n";
64                }
65                echo "\n";
66            }
67        } else {
68            echo "DOCTYPEの内部サブセットに子ノードは定義されていません。\n";
69        }
70    } else {
71        echo "文書にDOCTYPE宣言が見つかりませんでした。\n";
72    }
73}
74
75/**
76 * ノードタイプを示す定数値を人間に読みやすい文字列に変換するヘルパー関数。
77 * (DOMNodeの定数を使用)
78 *
79 * @param int $type DOMNode::NODE_TYPE_* のいずれかの値
80 * @return string ノードタイプを示す文字列
81 */
82function getNodeTypeName(int $type): string
83{
84    return match ($type) {
85        XML_ELEMENT_NODE       => 'ELEMENT_NODE',
86        XML_ATTRIBUTE_NODE     => 'ATTRIBUTE_NODE',
87        XML_TEXT_NODE          => 'TEXT_NODE',
88        XML_CDATA_SECTION_NODE => 'CDATA_SECTION_NODE',
89        XML_ENTITY_REF_NODE    => 'ENTITY_REF_NODE',
90        XML_ENTITY_NODE        => 'ENTITY_NODE', // DOMDocumentType::childNodesが返すノード
91        XML_PI_NODE            => 'PROCESSING_INSTRUCTION_NODE',
92        XML_COMMENT_NODE       => 'COMMENT_NODE',
93        XML_DOCUMENT_NODE      => 'DOCUMENT_NODE',
94        XML_DOCUMENT_TYPE_NODE => 'DOCUMENT_TYPE_NODE',
95        XML_DOCUMENT_FRAG_NODE => 'DOCUMENT_FRAGMENT_NODE',
96        XML_NOTATION_NODE      => 'NOTATION_NODE', // DOMDocumentType::childNodesが返すノード
97        XML_HTML_DOCUMENT_NODE => 'HTML_DOCUMENT_NODE',
98        default                => 'UNKNOWN_NODE_TYPE',
99    };
100}
101
102// 関数の実行
103demonstrateDomDocumentTypeChildNodes();

DOMDocumentType::childNodesは、PHPのDOM拡張機能において、XML文書のDOCTYPE(文書型定義)宣言内に記述された内部サブセットの情報を取得するためのプロパティです。このプロパティは引数を取らず、戻り値としてDOMNodeListオブジェクトを返します。DOMNodeListには、DOCTYPE宣言内で定義されたエンティティ宣言(DOMEntityノード)や記法宣言(DOMNotationノード)などが含まれます。

一般的なHTML5のDOCTYPEでは内部サブセットがないため、通常childNodesは空のリストを返しますが、サンプルコードでは内部DTDサブセットを持つXMLを例に、childNodesが実際に情報を保持するケースを示しています。コードではまず、エンティティ宣言と記法宣言を含むXML文字列を定義し、それをDOMDocumentオブジェクトにロードします。次に、$dom->doctypeプロパティを通じてDOMDocumentTypeオブジェクトを取得し、そのchildNodesプロパティにアクセスしています。

取得したDOMNodeListはループ処理によって個々の子ノードにアクセスでき、それぞれのノード名、ノードタイプ、そしてDOMEntityの場合はエンティティ値、DOMNotationの場合はシステムIDや公開IDといった具体的な詳細情報を表示しています。このように、DOMDocumentType::childNodesを利用することで、DOCTYPE宣言の内部構造をプログラムから詳細に調べ、操作することが可能になります。

DOMDocumentType::childNodesプロパティは、DOCTYPE宣言内の内部サブセットで定義されたエンティティ宣言や記法宣言などのノードを取得します。一般的なHTML5のDOCTYPE宣言(例: <!DOCTYPE html>)では通常子ノードは含まれず、返されるDOMNodeListは空になるため注意が必要です。このサンプルコードは、DTDの内部サブセットを持つXMLを使用して、子ノードが存在する場合の動作を示しています。取得されるノードはDOMEntityDOMNotationといった特定の型の場合があるため、ループ内でinstanceofを使って型を判別すると安全に処理できます。XMLの読み込みに失敗していないか、また$dom->doctypeDOMDocumentTypeオブジェクトとして正しく取得されているかを必ず確認してからプロパティにアクセスしてください。

関連コンテンツ

関連プログラミング言語

【PHP8.x】childNodesプロパティの使い方 | いっしー@Webエンジニア