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

【PHP8.x】Dom\ProcessingInstruction::nextSiblingプロパティの使い方

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

作成日: 更新日:

基本的な使い方

『nextSiblingプロパティは、DOMツリーにおいて、現在の処理命令ノードの直後に位置する兄弟ノードを保持するプロパティです。』 PHPのDom拡張機能は、XMLやHTML文書をプログラムで操作するために、文書全体を階層的なツリー構造として表現します。このツリーは、要素、テキスト、コメントなど、文書を構成する様々な部分に対応する「ノード」の集まりで成り立っています。同じ親ノードに属するノード同士は「兄弟ノード」と呼ばれ、文書に記述された順序で並んでいます。このnextSiblingプロパティは、現在のノードのすぐ隣、つまり直後に存在する兄弟ノードを取得するために使用されます。もし現在のノードが親にとって最後の子ノードであり、次に続く兄弟ノードが存在しない場合は、このプロパティはnullを返します。したがって、このプロパティを使って取得したノードを操作する前には、nullでないことを確認する処理が一般的に必要です。このプロパティは読み取り専用であり、特定のノードから順に兄弟ノードをたどっていくような処理を実装する際に役立ちます。

構文(syntax)

1<?php
2
3// 処理命令を含むXML文字列を準備します。
4$xml = '<?xml version="1.0" encoding="UTF-8"?>
5<?php-instruction data?>
6<root>Hello</root>';
7
8// DOMDocumentオブジェクトを作成し、XMLを読み込みます。
9$doc = new DOMDocument();
10$doc->loadXML($xml);
11
12// 最初の処理命令ノードを取得します (<?php-instruction data?>)。
13$pi = $doc->getElementsByTagName('php-instruction')->item(0);
14
15// ProcessingInstructionノードの次の兄弟ノードを取得します。
16// この場合、改行とインデントのテキストノードが取得されます。
17// さらにその次の兄弟ノードが <root> 要素になります。
18$next = $pi->nextSibling->nextSibling;
19
20// 次の兄弟ノードのノード名を出力します。
21// 出力: root
22echo $next->nodeName;
23
24?>

引数(parameters)

引数なし

引数はありません

戻り値(return)

?Dom\Node

このプロパティは、現在のノードの後に続く兄弟ノードを返します。後続の兄弟ノードが存在しない場合は、null を返します。

サンプルコード

PHP DOM: processing-instruction の nextSibling を取得する

1<?php
2
3declare(strict_types=1);
4
5/**
6 * Dom\ProcessingInstruction の nextSibling プロパティの使用例を示します。
7 *
8 * XMLドキュメント内の処理命令ノードを探し、
9 * その直後にある兄弟ノードを取得して情報を表示します。
10 */
11function demonstratePiNextSibling(): void
12{
13    // サンプルXML文字列を定義します。
14    // `<?php-pi ...?>` が処理命令(Processing Instruction)ノードです。
15    // 整形のための改行やインデントは、テキストノードとして解釈される点に注意してください。
16    $xmlString = <<<XML
17<?xml version="1.0" encoding="UTF-8"?>
18<root>
19  <item>First Item</item>
20  <?php-pi process-data?>
21  <item>Second Item</item>
22</root>
23XML;
24
25    // DOMDocumentオブジェクトを作成し、XMLを読み込みます。
26    // PHP 8.0以降で推奨される新しい `Dom` 名前空間のクラスを使用します。
27    $dom = new \Dom\Document();
28    $dom->loadXML($xmlString);
29
30    // XPathを使用して処理命令ノードを特定します。
31    // `processing-instruction('php-pi')` は、ターゲットが 'php-pi' のノードを選択します。
32    $xpath = new \Dom\XPath($dom);
33    $piNodeList = $xpath->query("//processing-instruction('php-pi')");
34
35    // 処理命令ノードが存在するか確認します。
36    if ($piNodeList->length > 0) {
37        /** @var \Dom\ProcessingInstruction $piNode */
38        $piNode = $piNodeList[0];
39
40        echo "処理命令ノードが見つかりました:\n";
41        echo "  ターゲット: " . $piNode->target . "\n"; // php-pi
42        echo "  データ: " . $piNode->data . "\n\n";     // process-data
43
44        // nextSibling プロパティを使って、次の兄弟ノードを取得します。
45        $sibling = $piNode->nextSibling;
46
47        // 次の兄弟ノードが存在するかどうかを確認します。
48        if ($sibling) {
49            echo "nextSibling プロパティで取得したノードの情報:\n";
50
51            // nextSiblingは要素だけでなく、テキスト(改行や空白)もノードとして取得します。
52            if ($sibling->nodeType === XML_TEXT_NODE) {
53                echo "  種類: テキストノード\n";
54                echo "  ノード名: " . $sibling->nodeName . "\n"; // #text
55                echo "  値(改行とスペース): " . json_encode($sibling->nodeValue) . "\n\n";
56
57                // テキストノードのさらに次の兄弟ノードを取得することもできます。
58                $nextElement = $sibling->nextSibling;
59                if ($nextElement) {
60                    echo "テキストノードのさらに次の兄弟ノードの情報:\n";
61                    echo "  種類: 要素ノード\n";
62                    echo "  ノード名: " . $nextElement->nodeName . "\n"; // item
63                    echo "  テキスト: " . $nextElement->textContent . "\n"; // Second Item
64                }
65            } else {
66                echo "  種類: 要素ノードまたはその他\n";
67                echo "  ノード名: " . $sibling->nodeName . "\n";
68            }
69        } else {
70            echo "この処理命令ノードには次の兄弟ノードがありません。\n";
71        }
72    } else {
73        echo "対象の処理命令ノードが見つかりませんでした。\n";
74    }
75}
76
77// 関数を実行します。
78demonstratePiNextSibling();

このPHPコードは、XML文書内にある特定のノードの「すぐ隣の兄弟ノード」を取得する方法を示します。ここでは Dom\ProcessingInstruction クラスの nextSibling プロパティを使用します。

nextSibling は、あるノードと同じ階層にあり、その直後に現れるノード(兄弟ノード)を取得するためのプロパティです。引数は必要なく、プロパティにアクセスするだけで値を取得できます。戻り値は、次の兄弟ノードが存在すればそのノードオブジェクト (Dom\Node) を、存在しなければ null を返します。

サンプルコードでは、まず <?php-pi process-data?> という処理命令ノードをXML文書から探し出します。そして、このノードの nextSibling プロパティを使って、次の兄弟ノードを取得しています。

ここで重要なのは、XML内の改行や空白も「テキストノード」として扱われる点です。そのため、処理命令ノードの直後にあるのは、次の <item> 要素ではなく、その間にある改行とスペースで構成されたテキストノードになります。コードでは、このテキストノードを取得したあと、さらにそのノードの nextSibling を調べることで、目的の <item> 要素を取得しています。このように nextSibling を使うと、ノードを順番にたどることができます。

nextSiblingプロパティは、XML内の改行や空白も「テキストノード」として取得する点に注意が必要です。サンプルコードのように要素間に改行があると、次の要素ではなく、その改行文字を含むテキストノードが返されます。期待する要素ノードを取得するには、取得したノードの種類をnodeTypeプロパティで確認し、テキストノードならさらにnextSiblingを呼び出すといった処理が必要になる場合があります。また、対象ノードが最後の子である場合、次の兄弟は存在しないためnextSiblingnullを返します。プロパティを利用する際は、必ずnullでないことを確認してから操作を行うようにしてください。

PHP DOM ProcessingInstructionのnextSiblingを取得する

1<?php
2
3/**
4 * Dom\ProcessingInstruction の nextSibling プロパティの使用例を示します。
5 *
6 * この関数は、XMLドキュメント内の処理命令ノードを特定し、
7 * その直後にある兄弟ノード(nextSibling)を取得して情報を表示します。
8 */
9function showProcessingInstructionNextSibling(): void
10{
11    // 処理命令 (<?xml-stylesheet ...?>) を含むHTML文字列を定義
12    $htmlString = <<<HTML
13<!DOCTYPE html>
14<html>
15<head>
16    <meta charset="UTF-8">
17    <?xml-stylesheet type="text/css" href="style.css"?>
18    <title>サンプルページ</title>
19</head>
20<body>
21    <h1>こんにちは</h1>
22</body>
23</html>
24HTML;
25
26    // DOMDocument オブジェクトを作成
27    $dom = new DOMDocument();
28
29    // HTML を安全に読み込む
30    // LIBXML_NOERROR を指定して、HTML5 の警告などを抑制
31    @$dom->loadHTML($htmlString, LIBXML_NOERROR);
32
33    // 処理命令ノード (ProcessingInstruction) を見つける
34    $processingInstructionNode = null;
35
36    // <head> タグの子ノードを順番に調べる
37    $head = $dom->getElementsByTagName('head')->item(0);
38    if ($head) {
39        foreach ($head->childNodes as $node) {
40            // ノードが処理命令 (DOMProcessingInstruction) かどうかを判定
41            if ($node instanceof DOMProcessingInstruction) {
42                $processingInstructionNode = $node;
43                break; // 最初に見つかったものを使用
44            }
45        }
46    }
47
48    // 処理命令ノードが見つかった場合
49    if ($processingInstructionNode) {
50        echo "処理命令ノードが見つかりました。\n";
51        echo "ターゲット: " . $processingInstructionNode->target . "\n"; // "xml-stylesheet"
52        echo "データ: " . $processingInstructionNode->data . "\n\n";   // 'type="text/css" href="style.css"'
53
54        // nextSibling プロパティで、処理命令の「次の兄弟ノード」を取得します。
55        // HTML構造上、改行などがテキストノードとして解釈されることがあるため、
56        // 要素ノードが見つかるまで次の兄弟をたどります。
57        $nextSiblingNode = $processingInstructionNode->nextSibling;
58        while ($nextSiblingNode && $nextSiblingNode->nodeType === XML_TEXT_NODE) {
59            $nextSiblingNode = $nextSiblingNode->nextSibling;
60        }
61
62        // 次の兄弟ノードが存在するかどうかを確認
63        if ($nextSiblingNode) {
64            echo "nextSibling プロパティで次の兄弟ノードを取得しました。\n";
65            // このサンプルでは <title> タグが該当します。
66            echo "ノード名: " . $nextSiblingNode->nodeName . "\n";    // "title"
67            echo "ノードの内容: " . $nextSiblingNode->textContent . "\n"; // "サンプルページ"
68        } else {
69            echo "次の兄弟ノードは見つかりませんでした。\n";
70        }
71    } else {
72        echo "処理命令ノードが見つかりませんでした。\n";
73    }
74}
75
76// 関数を実行して結果を表示
77showProcessingInstructionNextSibling();

Dom\ProcessingInstructionクラスのnextSiblingプロパティは、XMLやHTMLドキュメント内にある特定の処理命令ノードを基準として、その直後にある兄弟ノードを取得するために使用します。兄弟ノードとは、同じ親要素を持つ、隣同士のノード(要素、テキストなど)のことです。

このサンプルコードでは、まずHTMLドキュメントの中から<?xml-stylesheet ...?>という処理命令ノードを探し出します。そして、見つかった処理命令ノードに対してnextSiblingプロパティを呼び出すことで、そのすぐ後ろに位置するノードの取得を試みています。

HTMLでは、要素と要素の間にある改行や空白文字も「テキストノード」として解釈される場合があります。そのため、このコードでは目的の要素ノード(この場合は<title>タグ)が見つかるまで、不要なテキストノードを読み飛ばす処理を行っています。最終的に、処理命令の次に配置されている<title>ノードを取得し、そのタグ名と内部のテキスト(「サンプルページ」)を表示します。

このプロパティに引数はありません。戻り値として、直後に兄弟ノードが存在する場合はそのノードを表すDom\Nodeオブジェクトが返されます。もし対象が最後のノードで次に兄弟ノードが存在しない場合はnullが返されます。

nextSiblingプロパティを利用する際、HTMLソースコード上の改行や空白文字も「テキストノード」として取得される点に注意が必要です。このため、次のタグ(要素ノード)を期待していても、間に存在するテキストノードが返されることがあります。サンプルコードのように、取得したノードの種類(nodeType)を確認し、意図しないノードであればさらに次の兄弟ノードをたどる処理を実装するのが安全です。また、次の兄弟ノードが存在しない場合、このプロパティはnullを返します。nullに対して操作を行うとエラーが発生するため、利用前には必ずnullでないことを確認してください。

関連コンテンツ

関連プログラミング言語

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