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

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

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

作成日: 更新日:

基本的な使い方

previousSiblingプロパティは、DOMNodeオブジェクトにおいて、現在のノードの直前の兄弟ノードを表す読み取り専用のプロパティです。DOM(Document Object Model)は、HTMLやXMLドキュメントをプログラムから操作するためのAPIであり、ノードはドキュメントを構成する要素、属性、テキストなどの個々の部品を指します。

兄弟ノードとは、同じ親ノードを持つノードのことです。例えば、ある要素の中に複数の子要素がある場合、それらの子要素はお互いに兄弟ノードの関係にあります。previousSiblingプロパティを使用することで、DOMツリーを辿り、現在のノードから見て直前の兄弟ノードにアクセスできます。

このプロパティが返す値は、DOMNodeオブジェクト、またはNULLです。直前の兄弟ノードが存在する場合、そのノードを表すDOMNodeオブジェクトが返されます。直前の兄弟ノードが存在しない場合(例えば、現在のノードが親ノードの最初の子ノードである場合)は、NULLが返されます。

previousSiblingプロパティは読み取り専用であるため、このプロパティに値を代入して兄弟ノードを変更することはできません。ノードの追加、削除、挿入などの操作は、別のDOMメソッドを使用する必要があります。

システムエンジニアがDOMを操作する際、previousSiblingプロパティは、特定のノードの文脈における兄弟関係を把握し、効率的にDOMツリーをナビゲートするために非常に重要な役割を果たします。例えば、特定の要素の直前に新しい要素を挿入したり、兄弟要素の属性を比較したりする場合などに利用されます。

構文(syntax)

1DOMNode::$previousSibling;

引数(parameters)

引数なし

引数はありません

戻り値(return)

DOMNode|null

DOMNodeクラスのpreviousSiblingプロパティは、現在のノードの直前の兄弟ノードを返します。直前に兄弟ノードが存在しない場合はnullを返します。

サンプルコード

PHP: DOMNode::previousSibling で前の兄弟ノードを取得する

1<?php
2
3/**
4 * DOMNode::previousSibling プロパティの動作を実演する関数。
5 *
6 * このプロパティは、現在のノードの直前の兄弟ノード(同じ親を持つノード)を取得します。
7 * キーワード「previous() php」は、DOMツリーを遡り「前の」ノードを探索する操作を指し、
8 * この DOMNode::previousSibling プロパティがその操作の最も基本的な手段の一つとなります。
9 *
10 * DOMNode::previousSibling は要素ノードだけでなく、テキストノード、コメントノードなど、
11 * あらゆる種類のノードを対象とすることに注意が必要です。
12 * 存在しない場合は `null` を返します。
13 */
14function demonstratePreviousSiblingProperty(): void
15{
16    // HTML ドキュメントを文字列で定義します。
17    // <span>要素の直前にはコメントノード、その前にはテキストノード(改行とスペース)が存在します。
18    $html = <<<HTML
19<html>
20<body>
21    <div id="container">
22        <p>最初の段落です。</p>
23        <!-- これはコメントノードです -->
24        <span>ターゲット要素</span>
25        <a href="#">リンク要素</a>
26    </div>
27</body>
28</html>
29HTML;
30
31    // DOMDocument オブジェクトを作成し、HTML をロードします。
32    $dom = new DOMDocument();
33    // HTMLのロード中に発生する警告を抑制し、シンプルなHTML解析を試みます。
34    @$dom->loadHTML($html);
35
36    // id="container" の要素を取得します。
37    $container = $dom->getElementById('container');
38
39    if ($container === null) {
40        echo "エラー: 'container' 要素が見つかりませんでした。\n";
41        return;
42    }
43
44    // ターゲットとなる <span> 要素を取得します。
45    // getElementsByTagName() を使用して、ドキュメント内の最初の <span> 要素を取得します。
46    $spanElements = $dom->getElementsByTagName('span');
47    $targetSpan = ($spanElements->length > 0) ? $spanElements->item(0) : null;
48
49    if ($targetSpan === null) {
50        echo "エラー: ターゲットの <span> 要素が見つかりませんでした。\n";
51        return;
52    }
53
54    echo "--- ターゲット要素の情報 ---\n";
55    echo "ノード名: " . $targetSpan->nodeName . "\n";
56    echo "ノード値: '" . trim($targetSpan->nodeValue) . "'\n\n";
57
58    // ターゲット要素の直前の兄弟ノードを取得します。
59    // 今回のHTML構造では、「<!-- これはコメントノードです -->」が取得されます。
60    $previousSiblingNode = $targetSpan->previousSibling;
61
62    echo "--- ターゲット要素の直前の兄弟ノードの情報 ---\n";
63    if ($previousSiblingNode !== null) {
64        echo "直前の兄弟ノードが見つかりました。\n";
65        echo "  ノード名 (タイプ): " . $previousSiblingNode->nodeName . "\n";
66        // ノードタイプコードは、そのノードが何であるかを示します。
67        // 主要なノードタイプ: DOM_ELEMENT_NODE (1), DOM_TEXT_NODE (3), DOM_COMMENT_NODE (8)
68        echo "  ノードタイプコード: " . $previousSiblingNode->nodeType . "\n";
69        // テキストノードやコメントノードの場合、値には改行や空白が含まれる可能性があるため、trim()で整形して表示します。
70        echo "  ノード値: '" . trim($previousSiblingNode->nodeValue) . "'\n";
71        echo "  (この例では、`<!-- これはコメントノードです -->` というコメントノードが取得されました。)\n";
72
73        // さらにその前の兄弟ノードも見てみましょう。
74        // 今回のHTML構造では、`<p>...</p>` と `<!-- ... -->` の間の
75        // 「改行とスペース」がテキストノードとして取得されます。
76        $previousOfPreviousNode = $previousSiblingNode->previousSibling;
77        if ($previousOfPreviousNode !== null) {
78             echo "\n--- さらにその前の兄弟ノードの情報 ---\n";
79             echo "  ノード名 (タイプ): " . $previousOfPreviousNode->nodeName . "\n";
80             echo "  ノードタイプコード: " . $previousOfPreviousNode->nodeType . "\n";
81             // 空のテキストノードは値が空文字列になります。
82             $nodeValue = trim($previousOfPreviousNode->nodeValue);
83             echo "  ノード値: '" . ($nodeValue === '' ? '[空のテキストノード]' : $nodeValue) . "'\n";
84             echo "  (これは、HTMLソースコードの改行やインデントとして存在するテキストノードです。)\n";
85        } else {
86            echo "\nさらにその前の兄弟ノードは見つかりませんでした。\n";
87        }
88
89    } else {
90        echo "直前の兄弟ノードは見つかりませんでした。\n";
91        echo "(これはターゲット要素が親の最初の子ノードである場合に発生します。)\n";
92    }
93}
94
95// 関数を実行して、DOMNode::previousSibling プロパティの動作を確認します。
96demonstratePreviousSiblingProperty();
97
98?>

PHPのDOMNode::previousSiblingプロパティは、DOMツリー内で現在のノードの直前に位置する兄弟ノードを取得するために使用されます。これは、ウェブページなどのHTMLやXML構造をプログラムで操作する際に「前の要素」を探す基本的な手段の一つであり、「previous() php」といった検索キーワードで探されるような操作に該当します。

このプロパティは引数を持ちません。戻り値は、直前の兄弟ノードが存在すればDOMNodeオブジェクトを返しますが、存在しない場合(例えば、現在のノードが親の最初の子ノードである場合)はnullを返します。

サンプルコードでは、HTMLドキュメントから特定の<span>要素をターゲットとしています。<span>要素の直前にはコメントノード、さらにその前には改行やスペースによるテキストノードが存在します。previousSiblingプロパティを使用すると、まず<!-- これはコメントノードです -->というコメントノードが取得され、続けて呼び出すことでその前のテキストノードも取得される様子が示されています。このように、このプロパティは要素ノードだけでなく、コメントノードやテキストノードといったあらゆる種類のノードを対象とします。これにより、DOMツリーを柔軟に探索し、必要な情報を取得することが可能になります。

DOMNode::previousSiblingプロパティは、現在のノードの直前の兄弟ノードを取得しますが、存在しない場合はnullを返します。そのため、必ず取得結果がnullでないかを確認してから利用してください。このプロパティはHTML要素だけでなく、ソースコード上の改行やインデントといった空白文字もテキストノードとして、またコメントもコメントノードとして取得します。もし特定の要素ノードだけを扱いたい場合は、取得したノードのnodeType(例: DOM_ELEMENT_NODE)やnodeNameを確認し、意図するノードであるかを判別する追加の処理が必要です。HTMLの解析や要素の取得が失敗する可能性も考慮し、適切なエラーハンドリングを実装することが、より堅牢なプログラム作成に繋がります。

DOMNode::previousSiblingで直前兄弟ノードを取得する

1<?php
2
3/**
4 * DOMNode::previousSibling プロパティの使用例を示す関数です。
5 * このプロパティは、現在のノードの直前の兄弟ノードを取得するために使用されます。
6 * HTMLドキュメント内のDOM操作の基本的な理解を助けることを目的としており、
7 * システムエンジニアを目指す初心者にも理解しやすいよう、簡潔に記述されています。
8 */
9function demonstrateDomPreviousSibling(): void
10{
11    // 1. 新しい DOMDocument オブジェクトを初期化します。
12    // このオブジェクトはHTMLやXMLドキュメントを解析・操作するために使われます。
13    $dom = new DOMDocument();
14
15    // 2. 解析するHTMLコンテンツを定義します。
16    // 注意: HTMLソースの改行やインデントは、DOMツリーでは「テキストノード」として解釈されることがあります。
17    // この例では、改行を含んだHTML文字列を使用し、その挙動も示します。
18    $htmlContent = <<<HTML
19        <div id="container">
20            <!-- これはDOMツリー上のコメントノードです -->
21            <p>最初の要素です。</p>
22            <span>ターゲット要素です。</span>
23            <label>最後の要素です。</label>
24        </div>
25    HTML;
26
27    // 3. 定義したHTMLコンテンツを DOMDocument にロードします。
28    // loadHTML() はエラーを出す可能性があるため、@ を付けて抑制しています。
29    @$dom->loadHTML($htmlContent);
30
31    echo "--- DOMNode::previousSibling の基本的な使用例 ---\n\n";
32
33    // 4. 操作対象となるノード(ここでは最初の <span> 要素)を取得します。
34    // getElementsByTagName() は指定されたタグ名を持つすべての要素のリストを返します。
35    $spanElements = $dom->getElementsByTagName('span');
36
37    if ($spanElements->length > 0) {
38        $targetNode = $spanElements->item(0); // リストの最初の <span> 要素を取得
39        echo "現在のターゲットノード: <" . $targetNode->nodeName . "> (内容: '" . trim($targetNode->textContent) . "')\n\n";
40
41        // 5. previousSibling プロパティを使用して、現在のノードの直前の兄弟ノードを取得します。
42        // 戻り値は DOMNode オブジェクトか、存在しない場合は null です。
43        $previousSibling = $targetNode->previousSibling;
44
45        if ($previousSibling instanceof DOMNode) {
46            echo "【直前の兄弟ノードが見つかりました】\n";
47            echo "  ノードの種類 (nodeName): " . $previousSibling->nodeName . "\n";
48            // nodeValue はノードの種類によって異なります。テキストノードではその内容、要素ノードでは通常空です。
49            // 見やすいように改行文字をエスケープして表示しています。
50            echo "  ノードの値 (nodeValue): '" . str_replace(["\n", "\r"], ['\\n', '\\r'], trim($previousSibling->nodeValue)) . "'\n";
51
52            // 取得したノードの種類に基づいて追加情報を表示します。
53            if ($previousSibling instanceof DOMElement) {
54                echo "  これは要素ノードです (例: <p>, <div>など)。\n";
55            } elseif ($previousSibling->nodeName === '#text') {
56                echo "  これはテキストノードです。HTMLソースの改行や空白もテキストノードとして扱われることがあります。\n";
57            } elseif ($previousSibling->nodeName === '#comment') {
58                echo "  これはコメントノードです。\n";
59            }
60        } else {
61            echo "【直前の兄弟ノードは見つかりませんでした (null が返されました)】\n";
62            echo "  これは、現在のノードが親ノードの最初の子である場合に発生します。\n";
63        }
64    } else {
65        echo "HTMLコンテンツ内に <span> タグが見つかりませんでした。\n";
66    }
67
68    echo "\n--------------------------------------------------------\n\n";
69
70    // null が返されるケースの例:親ノードの最初の子の previousSibling
71    // 'container' というIDを持つ<div>要素を取得します。
72    $rootDiv = $dom->getElementById('container');
73    if ($rootDiv) {
74        // <div>の最初の子ノードを取得します。
75        // 上のHTMLでは、`<!-- これはコメントノードです -->`の前の改行とスペースが最初の子になる可能性があります。
76        $firstChildOfDiv = $rootDiv->firstChild; 
77
78        echo "--- 親ノードの最初の子の previousSibling の確認 ---\n";
79        if ($firstChildOfDiv instanceof DOMNode) {
80            echo "ターゲットノード (親ノードの最初の子): (nodeName: " . $firstChildOfDiv->nodeName . ", nodeValue: '" . str_replace(["\n", "\r"], ['\\n', '\\r'], trim($firstChildOfDiv->nodeValue)) . "')\n\n";
81
82            // 親ノードの最初の子ノードの previousSibling を取得します。
83            // 論理的には、これ以上前には兄弟ノードは存在しないはずです。
84            $prevOfFirstChild = $firstChildOfDiv->previousSibling;
85
86            if ($prevOfFirstChild instanceof DOMNode) {
87                echo "直前の兄弟ノードが見つかりました。\n";
88                echo "  ノード名: " . $prevOfFirstChild->nodeName . "\n";
89                echo "  ノード値: '" . str_replace(["\n", "\r"], ['\\n', '\\r'], trim($prevOfFirstChild->nodeValue)) . "'\n";
90            } else {
91                echo "【直前の兄弟ノードは見つかりませんでした (null が返されました)】\n";
92                echo "  これは、このノードが親ノードの最初の子ノードであるためです。\n";
93            }
94        } else {
95            echo "親ノード 'container' に子ノードが見つかりませんでした。\n";
96        }
97    } else {
98        echo "IDが 'container' の要素が見つかりませんでした。\n";
99    }
100}
101
102// 上記のサンプル関数を実行します。
103demonstrateDomPreviousSibling();

DOMNode::previousSiblingプロパティは、PHPのDOM操作において、現在のノードの直前にある兄弟ノードを取得します。これはDOMNodeクラスに属し、引数はありません。戻り値は、直前の兄弟ノードを示すDOMNodeオブジェクト、または存在しない場合はnullです。

サンプルコードでは、HTMLドキュメントを読み込み、特定の<span>要素の直前の兄弟ノードを取得する様子を示しています。HTMLソースの改行や空白は「テキストノード」、コメントは「コメントノード」として扱われるため、これらも兄弟ノードとして取得される点に注意が必要です。

取得結果がDOMNodeオブジェクトであればその情報を表示し、直前の兄弟ノードが存在せずnullが返されるケース(例:ターゲットノードが親の最初の子である場合)も確認できます。これは、DOM操作の基礎となる機能です。

DOMNode::previousSiblingプロパティは、現在のノードの直前の兄弟ノードを返しますが、直前の兄弟ノードが存在しない場合はnullを返します。そのため、プロパティの利用前には必ずnullチェックやinstanceof DOMNodeによる型チェックを行ってください。

特に、HTMLソースコード中の改行やインデント、空白文字もDOMツリー上では「テキストノード」(nodeName#text)として扱われる点に注意が必要です。これにより、HTMLタグだけを兄弟ノードとして取得したい場合に、意図せずテキストノードが返されることがあります。同様に、HTMLコメントも「コメントノード」(nodeName#comment)として認識され、兄弟ノードに含まれます。要素ノードのみを対象としたい場合は、取得したノードのnodeTypenodeNameで種類を判別する追加の処理が必要です。

また、DOMDocument::loadHTML()関数は、構文に問題があるHTMLを読み込むと警告を発する場合があります。サンプルコードでは@演算子で抑制していますが、実運用ではエラーハンドリングを適切に実装し、安全性と堅牢性を高めることを推奨します。

関連コンテンツ

関連IT用語

関連プログラミング言語