【PHP8.x】nextSiblingプロパティの使い方
nextSiblingプロパティの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
『nextSiblingプロパティは、DOMツリーにおいて、現在のノードの直後に位置する兄弟ノードを保持するプロパティです。DOMツリーでは、同じ親ノードを持つノード同士を兄弟ノードと呼びます。このプロパティにアクセスすると、現在のノードのすぐ次にある兄弟ノードが Dom\Node オブジェクトとして返されます。もし、現在のノードが親ノードの最後の子ノードであり、次に兄弟ノードが存在しない場合には null を返します。この性質は、while ループなどを用いて、あるノード以降のすべての兄弟ノードを順番に処理する際の終了条件としてよく利用されます。例えば、特定の要素以降のすべての兄弟要素をたどるような処理を実装できます。このプロパティは読み取り専用であり、直接値を代入してDOM構造を変更することはできません。ノードの順序を変更するには insertBefore メソッドなどを使用する必要があります。また、要素ノードだけでなく、要素間の空白文字などが原因で生成されるテキストノードや、コメントノードなども兄弟ノードとして取得される点に注意が必要です。
構文(syntax)
1<?php 2 3$html = '<div><p>段落1</p><p>段落2</p></div>'; 4 5$dom = new DOMDocument(); 6$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); 7 8// 最初の <p> 要素ノードを取得 9$p1 = $dom->getElementsByTagName('p')->item(0); 10 11// nextSibling プロパティで、同じ階層の次のノードを取得 12$siblingNode = $p1->nextSibling; 13 14if ($siblingNode) { 15 // 出力: 段落2 16 echo $siblingNode->textContent; 17} 18 19?>
引数(parameters)
引数なし
引数はありません
戻り値(return)
Dom\Node|null
次に兄弟ノードが存在する場合はそのノードオブジェクトを返します。存在しない場合はnullを返します。
サンプルコード
PHP DOM nextSibling で兄弟ノードを辿る
1<?php 2 3/** 4 * ノードタイプIDに対応する名前を返すヘルパー関数 5 * 6 * @param int $type ノードタイプID (例: XML_ELEMENT_NODE, XML_TEXT_NODE など) 7 * @return string ノードタイプ名 8 */ 9function getNodeTypeName(int $type): string 10{ 11 return match ($type) { 12 XML_ELEMENT_NODE => '要素ノード', 13 XML_ATTRIBUTE_NODE => '属性ノード', 14 XML_TEXT_NODE => 'テキストノード', 15 XML_CDATA_SECTION_NODE => 'CDATAセクションノード', 16 XML_ENTITY_REF_NODE => 'エンティティ参照ノード', 17 XML_ENTITY_NODE => 'エンティティノード', 18 XML_PI_NODE => '処理命令ノード', 19 XML_COMMENT_NODE => 'コメントノード', 20 XML_DOCUMENT_NODE => 'ドキュメントノード', 21 XML_DOCUMENT_TYPE_NODE => 'ドキュメントタイプノード', 22 XML_DOCUMENT_FRAG_NODE => 'ドキュメントフラグメントノード', 23 XML_NOTATION_NODE => '記法ノード', 24 default => '不明なノード', 25 }; 26} 27 28/** 29 * PHPのDom\Node::nextSibling プロパティの使用方法をデモンストレーションします。 30 * 31 * nextSibling プロパティは、現在のノードの次の兄弟ノードを返します。 32 * 兄弟ノードが存在しない場合は null を返します。 33 */ 34function demonstrateDomNextSibling(): void 35{ 36 // 1. サンプルとなるHTML文字列を作成します。 37 // 異なる種類のノード (要素、コメント、テキスト) が含まれるようにします。 38 // 要素間の改行やインデントもテキストノードとして扱われる点に注意してください。 39 $html = <<<HTML 40 <div id="container"> 41 <p>最初のパラグラフ</p> 42 <!-- これはコメントノードです --> 43 <span>スパン要素</span> 44 これは要素ではないテキストノードです。 45 <a href="https://example.com">リンク</a> 46 </div> 47 HTML; 48 49 echo "--- Dom\\Node::nextSibling プロパティのデモンストレーション ---" . PHP_EOL . PHP_EOL; 50 51 // 2. DOMDocument オブジェクトを作成し、HTMLをロードします。 52 $dom = new DOMDocument(); 53 // HTML5互換でないHTMLのパースエラーを抑制するために、エラーハンドリングを一時的に無効にします。 54 libxml_use_internal_errors(true); 55 $dom->loadHTML($html); 56 libxml_clear_errors(); // エラーをクリアします。 57 58 // 3. ID 'container' を持つ親要素を取得します。 59 // この要素の子ノードを辿って nextSibling を使用します。 60 $container = $dom->getElementById('container'); 61 62 if (!$container) { 63 echo "エラー: 'container' 要素が見つかりませんでした。" . PHP_EOL; 64 return; 65 } 66 67 echo "親要素: '{$container->nodeName}' の子ノードを辿ります。" . PHP_EOL; 68 echo "----------------------------------------------------" . PHP_EOL; 69 70 // 4. 親要素の最初の子ノードから開始し、nextSibling プロパティを使って兄弟ノードを順に辿ります。 71 // PHP 8 では、DOMノード関連のクラスは Dom\Node インターフェースを実装しています。 72 // nextSibling は Dom\Node または null を返します。 73 $currentNode = $container->firstChild; 74 $nodeIndex = 0; 75 76 while ($currentNode instanceof Dom\Node) { 77 $nodeIndex++; 78 echo "ノード {$nodeIndex}:" . PHP_EOL; 79 echo " - タイプ: " . getNodeTypeName($currentNode->nodeType) . " ({$currentNode->nodeType})" . PHP_EOL; 80 echo " - 名前: " . ($currentNode->nodeName === '#text' ? '#text (テキストノード)' : $currentNode->nodeName) . PHP_EOL; 81 // テキストノードの場合、nodeValueには内容が含まれます。 82 // 要素ノードの場合、nodeValueは通常空です。 83 $nodeValueDisplay = trim($currentNode->nodeValue); 84 if (mb_strlen($nodeValueDisplay) > 50) { 85 $nodeValueDisplay = mb_substr($nodeValueDisplay, 0, 50) . '...'; 86 } 87 echo " - 値: " . (empty($nodeValueDisplay) ? '[なし]' : $nodeValueDisplay) . PHP_EOL; 88 echo "----------------------------------------------------" . PHP_EOL; 89 90 // 次の兄弟ノードへ移動します。兄弟ノードがなければ null を返します。 91 $currentNode = $currentNode->nextSibling; 92 } 93 94 if ($nodeIndex === 0) { 95 echo "子ノードが見つかりませんでした。" . PHP_EOL; 96 } 97} 98 99// スクリプトの実行 100demonstrateDomNextSibling(); 101 102?>
Dom\NodeクラスのnextSiblingプロパティは、現在のノードの次の兄弟ノードを取得するために使用します。兄弟ノードが存在する場合、Dom\Nodeオブジェクトが返されます。もし次の兄弟ノードが存在しない場合、nullが返されます。
サンプルコードでは、まずHTML文字列をDOMDocumentオブジェクトに読み込みます。次に、getElementByIdメソッドで特定のIDを持つ要素(この例ではcontainer)を取得します。container要素が存在すれば、firstChildプロパティで最初の子ノードを取得し、そこからnextSiblingプロパティを使って兄弟ノードを順番に辿ります。各ノードについて、ノードタイプ、ノード名、ノード値を表示します。この処理をnextSiblingがnullを返すまで繰り返すことで、container要素の子ノードをすべて列挙しています。この例では、要素ノード、テキストノード、コメントノードが混在したHTMLを扱うことで、nextSiblingプロパティの挙動を理解しやすくしています。
nextSiblingは、指定した要素の直後の兄弟要素を取得するプロパティです。兄弟要素が存在しない場合、nullを返します。HTMLを扱う際、改行やインデントもテキストノードとして認識されるため、予期せぬノードが返されることがあります。loadHTML関数を使用する際は、HTML5非互換のエラーが発生することがあります。libxml_use_internal_errors(true)でエラーを抑制し、libxml_clear_errors()でエラーをクリアすることで、安全に処理できます。取得したノードのタイプをnodeTypeで確認し、テキストノードの場合はnodeValueで内容を取得できます。要素ノードの場合は、nodeValueは通常空です。