【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>といった要素ノードだけでなく、要素間の改行や空白を含むテキストノード、さらにはコメントノードも含まれます。
サンプルコードは、取得したDOMNodeListをforeachループで反復処理し、各子ノードのノード名(nodeName)やノードタイプ(nodeType)、具体的な内容(textContentやnodeValue)を表示しています。これにより、HTML構造がどのようにDOMツリーとして表現され、childNodesプロパティを通じてどのようにアクセスできるかを確認できます。DOM操作の基本として非常に重要なステップであり、HTML文書の構造をプログラムで解析・操作する上で頻繁に利用されます。
DOMNode::childNodesプロパティは、HTMLの要素ノードの他に、整形による改行やインデントなどの空白テキストノード、コメントノードも含む全ての子ノードをDOMNodeListとして返します。そのため、意図しない空白テキストノードを処理しないよう、nodeTypeでフィルタリングしたり、nodeValueをtrim()で確認したりする工夫が必要です。この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>といった要素ノードだけでなく、テキストノードやコメントノードなども含まれます。取得されたDOMNodeListはforeachループで反復処理され、各子ノードのタイプ(要素、テキスト、コメントなど)と名前、そしてテキストノードやコメントノードの場合はその内容が表示されます。この一連の処理により、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の失敗時は@でエラーを抑制せず、適切なエラーハンドリングを行うとより安全です。