Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

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

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

作成日: 更新日:

基本的な使い方

childNodesプロパティは、DOMNodeオブジェクトの子ノードを保持するプロパティです。このプロパティは、DOMNodeオブジェクトが持つ全ての子ノードをNodeListオブジェクトとして返します。NodeListオブジェクトは、ノードの順序付きリストであり、インデックスを使用して個々のノードにアクセスできます。

childNodesプロパティは読み取り専用であり、直接値を設定することはできません。子ノードを変更するには、DOMDocumentオブジェクトが提供するメソッド(appendChild、insertBefore、removeChildなど)を使用する必要があります。

childNodesプロパティを使用することで、DOMツリーを辿り、特定の要素の子ノードを効率的に取得できます。取得したNodeListオブジェクトをループ処理することで、各子ノードに対して必要な操作を実行できます。

例えば、あるHTML要素(DOMNodeオブジェクト)の子要素をすべて取得し、それぞれの要素のテキストコンテンツを出力する場合などにchildNodesプロパティが役立ちます。これにより、Webページの構造をプログラム的に解析し、必要な情報を抽出したり、動的にコンテンツを生成したりすることが可能になります。DOM操作における基本的なプロパティの一つであり、DOMDocumentとDOMNodeオブジェクトを理解する上で重要な役割を果たします。

構文(syntax)

1DOMNode::$childNodes;

引数(parameters)

引数なし

引数はありません

戻り値(return)

DOMNodeList

DOMNodeオブジェクトの子ノードのコレクション(DOMNodeList)を返します。

サンプルコード

PHP DOM childNodes で子ノードを列挙する

1<?php
2
3/**
4 * HTML文字列からDOM要素の子ノードを列挙するサンプル関数。
5 *
6 * この関数は、システムエンジニアを目指す初心者がDOM操作の基本、特に
7 * DOMNode::childNodes プロパティの使い方を理解できるように設計されています。
8 * 指定されたHTML文字列をパースし、<body>要素の子ノードを検索して、
9 * そのタイプと内容を表示します。
10 */
11function displayBodyChildNodesExample(): void
12{
13    // 1. サンプルとなるHTML文字列を定義
14    $html = <<<HTML
15<!DOCTYPE html>
16<html>
17<head>
18    <title>DOM ChildNodes サンプル</title>
19</head>
20<body>
21    <h1>DOM操作の基本</h1>
22    <p>この段落は<body>要素の直接の子です。</p>
23    <div>
24        <span>これはネストされた要素です。</span>
25        <!-- ここにコメントがあります -->
26        また別のテキストノード。
27    </div>
28    最後の段落。
29</body>
30</html>
31HTML;
32
33    // 2. DOMDocumentオブジェクトを初期化し、HTMLをロード
34    $dom = new DOMDocument();
35    // HTMLのパース中に発生する警告を抑制(libxml_clear_errorsで後でクリア)
36    libxml_use_internal_errors(true);
37    $dom->loadHTML($html);
38    libxml_clear_errors(); // 蓄積されたエラーをクリア
39
40    echo "--- DOMNode::childNodes プロパティの使用例 ---\n\n";
41    echo "対象HTML:\n" . $html . "\n\n";
42
43    // 3. 'body'要素を取得
44    // getElementsByTagNameはDOMNodeListを返すため、最初の要素(.item(0))を取得します。
45    $bodyElements = $dom->getElementsByTagName('body');
46    if ($bodyElements->count() === 0) {
47        echo "エラー: 'body'要素が見つかりませんでした。\n";
48        return;
49    }
50    $bodyNode = $bodyElements->item(0);
51
52    echo "<body>要素の直接の子ノードを列挙します:\n";
53
54    // 4. DOMNode::childNodes プロパティにアクセスして子ノードリストを取得
55    // このプロパティはDOMNodeListオブジェクトを返します。
56    $childNodes = $bodyNode->childNodes;
57
58    // 5. DOMNodeList をループし、各子ノードの情報を表示
59    foreach ($childNodes as $index => $node) {
60        echo "  [子ノード " . ($index + 1) . "]:\n";
61        echo "    ノード名: " . $node->nodeName; // 要素ノードはタグ名、テキストノードは #text、コメントノードは #comment
62        echo " (タイプコード: " . $node->nodeType . ")\n"; // 1:要素ノード (XML_ELEMENT_NODE)、3:テキストノード (XML_TEXT_NODE)、8:コメントノード (XML_COMMENT_NODE) など
63
64        // ノードタイプに応じて詳細情報を表示
65        switch ($node->nodeType) {
66            case XML_ELEMENT_NODE: // 要素ノードの場合
67                echo "    タグ名: " . $node->tagName . "\n";
68                // 要素のテキストコンテンツを短く表示
69                $text = trim($node->textContent);
70                echo "    テキスト内容: " . (strlen($text) > 50 ? substr($text, 0, 47) . '...' : $text) . "\n";
71                break;
72            case XML_TEXT_NODE: // テキストノードの場合
73                // テキストノードの値を短く表示
74                $value = trim($node->nodeValue);
75                if ($value !== '') { // 空のテキストノード(整形目的の改行など)はスキップ
76                    echo "    値: " . (strlen($value) > 50 ? substr($value, 0, 47) . '...' : $value) . "\n";
77                } else {
78                    echo "    値: (空白のテキストノード)\n";
79                }
80                break;
81            case XML_COMMENT_NODE: // コメントノードの場合
82                echo "    コメント: " . $node->nodeValue . "\n";
83                break;
84            // その他のノードタイプ(例:XML_DOCUMENT_TYPE_NODEなど)はここでは省略
85            default:
86                echo "    その他の情報: nodeValue = " . $node->nodeValue . "\n";
87                break;
88        }
89        echo "\n";
90    }
91}
92
93// 関数を実行してサンプルコードの動作を確認
94displayBodyChildNodesExample();
95

このサンプルコードは、PHPのDOM拡張機能におけるDOMNode::childNodesプロパティの基本的な使い方を示しています。このプロパティは、特定のDOMノード(例:HTML要素)が持つ直接の子ノード全てをリストとして取得するために使用されます。引数はなく、戻り値としてDOMNodeListオブジェクトを返します。DOMNodeListは、子ノードが順番に格納されたコレクションであり、foreachループなどで一つずつ取り出して処理できます。

コードではまず、HTML文字列をDOMDocumentオブジェクトにロードし、パースしています。次に、getElementsByTagNameメソッドを使ってHTMLドキュメントから<body>要素を取得します。取得した<body>要素のchildNodesプロパティにアクセスすることで、その直下に存在するすべての子ノードのリストがDOMNodeListとして得られます。このリストには、<h1><p>といった要素ノードだけでなく、要素間の改行や空白を含むテキストノード、さらにはコメントノードも含まれます。

サンプルコードは、取得したDOMNodeListforeachループで反復処理し、各子ノードのノード名(nodeName)やノードタイプ(nodeType)、具体的な内容(textContentnodeValue)を表示しています。これにより、HTML構造がどのようにDOMツリーとして表現され、childNodesプロパティを通じてどのようにアクセスできるかを確認できます。DOM操作の基本として非常に重要なステップであり、HTML文書の構造をプログラムで解析・操作する上で頻繁に利用されます。

DOMNode::childNodesプロパティは、HTMLの要素ノードの他に、整形による改行やインデントなどの空白テキストノード、コメントノードも含む全ての子ノードをDOMNodeListとして返します。そのため、意図しない空白テキストノードを処理しないよう、nodeTypeでフィルタリングしたり、nodeValuetrim()で確認したりする工夫が必要です。このDOMNodeListはライブコレクションであり、元のDOMツリーの変更に連動して内容が自動的に更新されます。PHPのDOM拡張モジュールが必須であり、DOMDocument::loadHTML()利用時には、パースエラーの警告を抑制し、処理後にlibxml_clear_errors()でクリアするのが一般的です。

PHP DOMDocument childNodesで子ノードを取得する

1<?php
2
3/**
4 * DOMNode::childNodes プロパティの使用例を示します。
5 * 指定されたHTML文字列からDOMツリーを構築し、特定の要素の子ノードを
6 * DOMNodeList として取得して、その内容を列挙します。
7 */
8function demonstrateDomChildNodes(): void
9{
10    // 新しい DOMDocument オブジェクトを作成します。
11    // DOMDocument はHTMLやXML文書を表現し、操作するためのクラスです。
12    $dom = new DOMDocument();
13
14    // 解析するHTML文字列を定義します。
15    // このHTMLは、body内に様々なタイプの子ノード(要素、テキスト、コメント)を含みます。
16    $html = <<<HTML
17<html>
18<head>
19    <title>サンプルページ</title>
20</head>
21<body>
22    <h1>ようこそ!</h1>
23    <p>これは最初の段落です。</p>
24    <!-- これはHTMLコメントノードです -->
25    <span>追加情報</span>
26    テキストノードもここにあります。
27</body>
28</html>
29HTML;
30
31    // HTML文字列をパースしてDOMツリーを構築します。
32    // LIBXML_HTML_NOIMPLIED: <html> や <body> タグを自動で追加しないようにします。
33    // LIBXML_NOWARNING: パース中の警告を表示しないようにします。
34    $dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_NOWARNING);
35
36    // 文書内から最初の <body> 要素を取得します。
37    // getElementsByTagName は指定されたタグ名を持つ全ての要素を DOMNodeList で返します。
38    // item(0) でそのリストの最初の要素(つまり最初の <body>)を取得します。
39    $body = $dom->getElementsByTagName('body')->item(0);
40
41    // <body> 要素が正常に取得できたかを確認します。
42    if ($body instanceof DOMElement) {
43        echo "<body> 要素の子ノード一覧:\n";
44
45        // $body は DOMElement のインスタンスであり、DOMNode を継承しています。
46        // DOMNode::childNodes プロパティにアクセスすると、
47        // そのノードの直下にある全ての子ノードを DOMNodeList オブジェクトとして取得できます。
48        $childNodes = $body->childNodes;
49
50        // DOMNodeList は Traversable インターフェースを実装しているため、foreach ループで
51        // 各子ノードにアクセスできます。
52        foreach ($childNodes as $node) {
53            // 各子ノードのタイプと名前を表示します。
54            // DOMNode::nodeType: ノードのタイプを示す整数定数(例: XML_ELEMENT_NODE, XML_TEXT_NODE)。
55            // DOMNode::nodeName: ノードの名前(要素名はタグ名、テキストノードは '#text'、コメントノードは '#comment')。
56            echo "  タイプ: " . getNodeTypeName($node->nodeType) . ", 名前: " . $node->nodeName;
57
58            // テキストノードやコメントノードの場合、その内容 (nodeValue) も表示します。
59            if ($node->nodeType === XML_TEXT_NODE || $node->nodeType === XML_COMMENT_NODE) {
60                // trim() を使って、余分な空白文字や改行を削除し、見やすくします。
61                echo ", 値: '" . trim($node->nodeValue) . "'";
62            }
63            echo "\n";
64        }
65    } else {
66        echo "エラー: <body> 要素が見つかりませんでした。\n";
67    }
68}
69
70/**
71 * DOMノードタイプ定数に対応する、人間が読める文字列を返します。
72 *
73 * @param int $nodeType DOMノードタイプ定数
74 * @return string ノードタイプの名前
75 */
76function getNodeTypeName(int $nodeType): string
77{
78    return match ($nodeType) {
79        XML_ELEMENT_NODE => '要素 (Element)',
80        XML_ATTRIBUTE_NODE => '属性 (Attribute)',
81        XML_TEXT_NODE => 'テキスト (Text)',
82        XML_CDATA_SECTION_NODE => 'CDATAセクション (CDATA Section)',
83        XML_ENTITY_REF_NODE => 'エンティティ参照 (Entity Reference)',
84        XML_ENTITY_NODE => 'エンティティ (Entity)',
85        XML_PI_NODE => '処理命令 (Processing Instruction)',
86        XML_COMMENT_NODE => 'コメント (Comment)',
87        XML_DOCUMENT_NODE => 'ドキュメント (Document)',
88        XML_DOCUMENT_TYPE_NODE => 'ドキュメントタイプ (Document Type)',
89        XML_DOCUMENT_FRAG_NODE => 'ドキュメントフラグメント (Document Fragment)',
90        XML_NOTATION_NODE => '記法 (Notation)',
91        default => '不明 (Unknown)'
92    };
93}
94
95// 上記の関数を実行して、サンプルコードの動作を確認します。
96demonstrateDomChildNodes();

DOMNode::childNodesプロパティは、PHPでHTMLやXMLなどのDOM文書を扱う際に、特定のノードが持つ直接の子ノード全てを取得するためのものです。このプロパティは引数を取らず、戻り値としてDOMNodeListオブジェクトを返します。DOMNodeListは、取得した全ての子ノードを順序立てて格納するリストであり、個々の子ノードにはforeachループなどでアクセスできます。

サンプルコードでは、まずDOMDocumentクラスのインスタンスを作成し、定義されたHTML文字列を読み込んでDOMツリーを構築しています。次に、getElementsByTagNameメソッドを使って文書から最初の<body>要素を取得しています。この<body>要素はDOMNodeを継承したDOMElementのインスタンスであるため、childNodesプロパティにアクセスが可能です。

$body->childNodesと記述することで、<body>要素の直下にある全ての子ノードがDOMNodeListとして取得されます。これには、<h1><p>といった要素ノードだけでなく、テキストノードやコメントノードなども含まれます。取得されたDOMNodeListforeachループで反復処理され、各子ノードのタイプ(要素、テキスト、コメントなど)と名前、そしてテキストノードやコメントノードの場合はその内容が表示されます。この一連の処理により、DOMNode::childNodesプロパティが、ノードの多様な子要素をどのように取得し、利用できるかが確認できます。

DOMNode::childNodesプロパティは、対象ノードの直下にある全ての子ノードをDOMNodeListとして返します。初心者は、HTMLのソースコード上の改行やインデントもテキストノードとして含まれる点に特に注意が必要です。これらのテキストノードはnodeValueプロパティで内容を確認し、不要な空白を除去したい場合はtrim()関数を使うと良いでしょう。また、取得されるノードには要素だけでなく、コメントノードなども含まれるため、意図したノードだけを処理するには$node->nodeTypeでノードの種類を適切に判別することが重要です。DOMNodeListは動的なリストであり、取得後にDOMツリーが変更されると、リストの内容もリアルタイムで更新されるため、ループ中にツリーを変更する際は注意が必要です。要素を取得する際には、対象が存在しない場合にnullが返される可能性があるので、instanceofによる型チェックなどで安全性を確保してください。

PHP: XPathでDOMNodeの子ノードを取得する

1<?php
2
3/**
4 * 指定されたXML文字列からXPathを使って特定の親ノードを特定し、
5 * その子ノードを列挙して表示する関数です。
6 *
7 * この関数は、DOMNode::childNodes プロパティの使用例を示します。
8 * DOMNode::childNodes は、特定のノードの直接の子ノードのリスト (DOMNodeList) を返します。
9 *
10 * @param string $xmlString 分析対象のXML文字列。
11 * @param string $xpathQuery 親ノードを選択するためのXPathクエリ。
12 *                           例: '/library/book[@id="bk101"]'
13 * @return void
14 */
15function displayChildNodesOfNode(string $xmlString, string $xpathQuery): void
16{
17    // 1. DOMDocument オブジェクトを作成し、XMLをロードします。
18    $dom = new DOMDocument();
19    // loadXML() が失敗した場合、エラーメッセージを出力して終了します。
20    if (!@$dom->loadXML($xmlString)) {
21        echo "エラー: XMLのロードに失敗しました。無効なXML形式である可能性があります。\n";
22        return;
23    }
24
25    // 2. DOMXPath オブジェクトを作成し、DOMDocumentに関連付けます。
26    // これにより、XMLドキュメント全体に対してXPathクエリを実行できるようになります。
27    $xpath = new DOMXPath($dom);
28
29    // 3. XPathクエリを実行して、指定された親ノードを検索します。
30    // query() メソッドは、XPathクエリに一致するすべてのノードを含む DOMNodeList を返します。
31    $parentNodeList = $xpath->query($xpathQuery);
32
33    // クエリに一致するノードが一つもない場合、メッセージを出力して終了します。
34    if ($parentNodeList->length === 0) {
35        echo "情報: XPathクエリ '{$xpathQuery}' に一致する親ノードが見つかりませんでした。\n";
36        return;
37    }
38
39    // XPathクエリに一致する最初のノードを親ノードとして選択します。
40    $parentNode = $parentNodeList->item(0);
41
42    echo "--------------------------------------------------------\n";
43    echo "親ノード '<{$parentNode->nodeName}>' (XPath: '{$xpathQuery}') の子ノード:\n";
44    echo "--------------------------------------------------------\n";
45
46    // 4. DOMNode::childNodes プロパティを使用して、親ノードのすべての子ノードを取得します。
47    // このプロパティは、テキストノードやコメントノードなども含め、直接の子を返します。
48    $childNodes = $parentNode->childNodes;
49
50    // 5. 取得した子ノードリストを繰り返し処理し、各子ノードの情報を表示します。
51    // DOMNodeList はイテレート可能なオブジェクトです。
52    if ($childNodes->length === 0) {
53        echo "  - この親ノードには子ノードがありません。\n";
54    } else {
55        foreach ($childNodes as $index => $childNode) {
56            // ノードのタイプによって表示内容を分けます。
57            // XML_ELEMENT_NODE は、HTMLのタグのような要素ノードを表します (例: <title>, <author>)。
58            if ($childNode->nodeType === XML_ELEMENT_NODE) {
59                echo "  [{$index}] 要素ノード: <{$childNode->nodeName}>\n";
60            }
61            // XML_TEXT_NODE は、要素内のテキストコンテンツを表します。
62            // XML文書の整形のための改行やインデントもテキストノードとして扱われるため、
63            // 空白のみのテキストノードはスキップすることが一般的です。
64            elseif ($childNode->nodeType === XML_TEXT_NODE && trim($childNode->nodeValue) !== '') {
65                echo "  [{$index}] テキストノード: '{$childNode->nodeValue}'\n";
66            }
67            // その他のノードタイプ(コメントノード、処理命令ノードなど)も存在しますが、
68            // 初心者向けサンプルとして要素とテキストに焦点を当てます。
69            else {
70                // その他のノードタイプが存在する場合でも表示します。
71                // (例: コメントノード, CDATAセクションノードなど)
72                $nodeTypeName = match ($childNode->nodeType) {
73                    XML_ATTRIBUTE_NODE => '属性',
74                    XML_CDATA_SECTION_NODE => 'CDATAセクション',
75                    XML_ENTITY_REF_NODE => '実体参照',
76                    XML_ENTITY_NODE => '実体',
77                    XML_PI_NODE => '処理命令',
78                    XML_COMMENT_NODE => 'コメント',
79                    XML_DOCUMENT_NODE => '文書',
80                    XML_DOCUMENT_TYPE_NODE => '文書型',
81                    XML_DOCUMENT_FRAG_NODE => '文書フラグメント',
82                    XML_NOTATION_NODE => '記法',
83                    default => '不明なタイプ'
84                };
85                echo "  [{$index}] その他のノード ({$nodeTypeName}, Type: {$childNode->nodeType}): {$childNode->nodeName}\n";
86            }
87        }
88    }
89    echo "\n";
90}
91
92// --- サンプルXMLデータ ---
93$sampleXml = <<<XML
94<library>
95    <!-- これはコメントです -->
96    <book id="bk101">
97        <title>PHP Programming for Beginners</title>
98        <author>John Doe</author>
99        <price>29.99</price>
100    </book>
101    <book id="bk102">
102        <title>Advanced Web Development</title>
103        <author>Jane Smith</author>
104        <price>45.00</price>
105    </book>
106</library>
107XML;
108
109// --- 実行例 ---
110
111// 例1: <library> ノードの直接の子ノードを表示
112displayChildNodesOfNode($sampleXml, '/library');
113
114// 例2: id="bk101" の <book> ノードの直接の子ノードを表示
115displayChildNodesOfNode($sampleXml, '/library/book[@id="bk101"]');
116
117// 例3: 存在しないノードをXPathで指定した場合の例
118// この場合、親ノードが見つからないため、メッセージが出力されます。
119displayChildNodesOfNode($sampleXml, '/library/magazine');
120
121// 例4: 子ノードがない要素の例 (存在しない要素を仮定)
122// このXPathはXMLには存在しないため、上記と同様に「見つかりません」と表示されます。
123displayChildNodesOfNode($sampleXml, '/library/book/publisher');
124
125?>

PHP 8のDOM拡張機能に属するDOMNode::childNodesは、XMLやHTMLのDOMツリー構造において、特定のノードの直接の子ノード全てを取得するための重要なプロパティです。このプロパティには引数はなく、戻り値としてDOMNodeListオブジェクトを返します。このDOMNodeListは、要素ノードだけでなく、テキストノードやコメントノードなども含む、指定したノードの直接の子ノードのリストです。

提示されたサンプルコードは、まずXML文字列をDOMDocumentにロードし、DOMXPathを使用して指定されたXPathクエリに合致する親ノードを特定します。親ノードが見つかると、そのDOMNodeオブジェクトからchildNodesプロパティにアクセスし、全ての子ノードをDOMNodeListとして取得しています。そして、取得したDOMNodeListを繰り返し処理し、各子ノードのタイプ(要素ノード、テキストノードなど)と名前を表示しています。これにより、XMLドキュメント内の複雑な構造から、特定の親ノードに属する子ノードを効率的に抽出し、その情報を確認する方法を学ぶことができます。このプロパティは、XMLデータの解析や変更を行う際に頻繁に使用されるため、システムエンジニアを目指す上で非常に役立つでしょう。

DOMNode::childNodesは、要素ノードだけでなく、XMLの整形のための改行やインデントを含むテキストノードやコメントノードなど、全ての直接の子ノードをDOMNodeListとして返します。空白のみのテキストノードが頻繁に含まれるため、意図しないノードを処理しないよう、nodeTypeでフィルタリングし、テキストノードはtrim()で内容を確認することが重要です。DOMNodeListは配列ではないため、foreachでループするか、lengthプロパティとitem()メソッドを使ってアクセスしてください。また、loadXMLの失敗時は@でエラーを抑制せず、適切なエラーハンドリングを行うとより安全です。

関連コンテンツ

関連プログラミング言語