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

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

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

作成日: 更新日:

基本的な使い方

previousSiblingプロパティは、PHPのDOM拡張機能の一部として、HTMLドキュメント内の特定のノードから見て、その直前の兄弟ノードを保持するプロパティです。このプロパティは、Dom\HTMLDocumentクラスを介してアクセスされるHTMLドキュメント内の任意のノード(要素、テキストなど)に適用されます。

WebページなどのHTMLドキュメントは、要素が階層的に配置されたツリー構造(DOMツリー)で構成されています。previousSiblingプロパティを使用すると、現在注目しているノードと同じ階層にあり、かつそのノードのすぐ前に位置するノードを取得できます。例えば、あるHTML要素からその直前の兄弟要素やテキストコンテンツを取得するといった操作が可能です。

このプロパティによって取得されるノードは、HTMLタグで囲まれた要素ノードだけでなく、要素間の空白や改行を含むテキストノード、さらにはコメントノードなども含まれます。もし、現在のノードの直前に兄弟ノードが存在しない場合(例えば、現在のノードが親要素の最初の子ノードである場合)、このプロパティはnullを返します。

previousSiblingプロパティは、DOMツリーを効率的に走査し、HTMLドキュメントの構造を解析したり、特定の要素の前後にあるコンテンツを動的に操作したりする際に非常に便利です。PHP 8環境下でWebコンテンツを扱うシステム開発において、ドキュメントのナビゲーションや情報の抽出に広く活用されます。

構文(syntax)

1<?php
2$document = new DOM\HTMLDocument();
3$previousNode = $document->previousSibling;
4?>

引数(parameters)

引数なし

引数はありません

戻り値(return)

Dom\Node|null

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

サンプルコード

PHP DomPreviousSiblingで前の兄弟ノードを取得する

1<?php
2
3/**
4 * Dom\HTMLDocument::previousSibling プロパティの使用例
5 *
6 * この関数は、PHP 8のDom拡張におけるDom\HTMLDocumentオブジェクトから取得したHTML要素の
7 * previousSibling プロパティがどのように動作するかを示します。
8 * previousSibling は、ノードの直前にある兄弟ノード(Dom\Node型)を返します。
9 * 直前の兄弟ノードが存在しない場合は null を返します。
10 * (Dom\HTMLDocument クラスは Dom\Node を継承しているためこのプロパティを持ちますが、
11 * 通常、ドキュメント自体はDOMツリーのルートであるため、ドキュメントのpreviousSiblingは
12 * ほとんどの場合 null になります。このプロパティは、ドキュメント内の要素に対して
13 * その前の兄弟要素を取得する目的で一般的に使用されます。)
14 */
15function demonstrateDomPreviousSibling(): void
16{
17    // 1. 新しい Dom\HTMLDocument インスタンスを作成します。
18    //    これはPHP 8の新しいDom拡張に含まれるクラスです。
19    $document = new Dom\HTMLDocument();
20
21    // 2. サンプルHTMLコンテンツを読み込みます。
22    //    要素間に余計な空白ノードが生成されないよう、簡潔なHTMLを使用しています。
23    $htmlContent = <<<HTML
24<!DOCTYPE html>
25<html>
26<body>
27    <div id="item1">最初のアイテム</div><p id="item2">二番目のアイテム(ターゲットの前の兄弟ノード)</p><span id="target">三番目のアイテム(ターゲットノード)</span><div id="item4">四番目のアイテム</div>
28</body>
29</html>
30HTML;
31    $document->loadHTML($htmlContent);
32
33    // 3. ID 'target' を持つ<span>要素をターゲットノードとして見つけます。
34    //    Dom\HTMLDocument オブジェクトは、ドキュメント内の要素にアクセスするための
35    //    エントリーポイントとなります。
36    $targetNode = $document->getElementById('target');
37
38    if ($targetNode instanceof Dom\Node) {
39        echo "見つかったターゲットノード: " . $targetNode->nodeName . " ('" . $targetNode->textContent . "')\n";
40
41        // 4. ターゲットノードの 'previousSibling' プロパティにアクセスします。
42        //    このプロパティは、ターゲットノードの直前にある兄弟ノードを返します。
43        $previousSibling = $targetNode->previousSibling;
44
45        if ($previousSibling instanceof Dom\Node) {
46            echo "  => 直前の兄弟ノードが見つかりました:\n";
47            echo "     ノード名: " . $previousSibling->nodeName . "\n";
48            echo "     ノードタイプ: " . $previousSibling->nodeType;
49
50            // ノードタイプに応じて詳細情報を表示します。
51            switch ($previousSibling->nodeType) {
52                case Dom\Node::ELEMENT_NODE: // 要素ノード (例: <p>, <div>, <span>)
53                    echo " (要素ノード)\n";
54                    echo "     テキストコンテンツ: '" . $previousSibling->textContent . "'\n";
55                    echo "     ID属性: " . $previousSibling->getAttribute('id') . "\n";
56                    break;
57                case Dom\Node::TEXT_NODE: // テキストノード
58                    echo " (テキストノード)\n";
59                    echo "     コンテンツ: '" . $previousSibling->nodeValue . "'\n";
60                    break;
61                case Dom\Node::COMMENT_NODE: // コメントノード
62                    echo " (コメントノード)\n";
63                    echo "     コンテンツ: '" . $previousSibling->nodeValue . "'\n";
64                    break;
65                default: // その他のノードタイプ
66                    echo " (その他のノードタイプ)\n";
67                    echo "     ノード値: '" . $previousSibling->nodeValue . "'\n";
68                    break;
69            }
70        } else {
71            echo "  => ターゲットノードに直前の兄弟ノードはありません。\n";
72        }
73    } else {
74        echo "ID 'target' を持つターゲットノードが見つかりませんでした。\n";
75    }
76}
77
78// サンプル関数を実行します。
79demonstrateDomPreviousSibling();

PHP 8のDom拡張で提供されるDom\HTMLDocument::previousSiblingプロパティは、HTMLドキュメント内の特定の要素(ノード)の直前にある兄弟ノードを取得するために使用されます。このプロパティは引数を取らず、もし直前の兄弟ノードが存在すればDom\Nodeオブジェクトを返し、存在しない場合はnullを返します。

このサンプルコードでは、まずDom\HTMLDocumentオブジェクトを作成し、サンプルHTMLを読み込んでいます。次に、IDがtarget<span>要素をドキュメントから見つけ出します。この<span>要素が操作対象となる「ターゲットノード」です。

そして、ターゲットノードに対してpreviousSiblingプロパティにアクセスすることで、その直前にある兄弟ノード(この例ではIDがitem2<p>要素)を取得しています。取得された兄弟ノードがDom\Nodeのインスタンスであれば、そのノード名、ノードタイプ、そして要素であればテキストコンテンツやID属性などの詳細情報を表示します。もし直前の兄弟ノードが存在しない場合は、「ターゲットノードに直前の兄弟ノードはありません」と表示されます。これにより、DOMツリー構造の中で、要素の相対的な位置をプログラムで特定する方法を理解できます。

previousSiblingプロパティは、対象ノードの直前にある兄弟ノードを返しますが、直前の兄弟ノードが存在しない場合はnullが返されます。そのため、常に返り値がDom\Node型であるかnullであるかを確認し、nullチェックを必ず行ってください。また、HTMLのソースコード中の改行や空白もテキストノードとして扱われるため、意図せずこれらのテキストノードが直前の兄弟として取得される場合があります。取得したノードが要素なのか、テキストなのかといった種類はnodeTypeプロパティで確認し、適切な処理を行うことが重要です。この機能はPHP 8から提供されている新しいDom拡張のものです。

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

1<?php
2
3function demonstratePreviousSibling(): void
4{
5    // Dom\HTMLDocumentを生成し、HTMLコンテンツを読み込みます。
6    // previousSiblingプロパティを明確に示せるよう、兄弟要素を持つHTML構造を作成します。
7    $document = new Dom\HTMLDocument();
8    $htmlContent = '
9        <div>
10            <h1>最初の見出し</h1>
11            <p>この段落がターゲット要素の前の兄弟です。</p>
12            <span>これがターゲット要素です。</span>
13            <p>この段落はターゲット要素の次の兄弟です。</p>
14        </div>
15    ';
16    $document->parseHTML($htmlContent);
17
18    // querySelectorAllを使用して、ターゲットとなる<span>要素を検索します。
19    $spanElements = $document->querySelectorAll('span');
20
21    if ($spanElements->count() > 0) {
22        // 見つかった最初の<span>要素をターゲットとします。
23        $targetNode = $spanElements->item(0);
24
25        echo "ターゲットノード: '{$targetNode->nodeName}' (内容: '" . trim($targetNode->textContent) . "')\n";
26
27        // previousSiblingプロパティを使用して、ターゲットノードの前の兄弟ノードを取得します。
28        // このプロパティはDom\Nodeクラスから継承されており、Dom\HTMLDocument内で取得した
29        // 全てのノードで利用可能です。
30        $previousSibling = $targetNode->previousSibling;
31
32        if ($previousSibling instanceof Dom\Node) {
33            // 前の兄弟ノードが存在する場合、そのノード名とテキストコンテンツを表示します。
34            echo "前の兄弟ノード: '{$previousSibling->nodeName}'\n";
35            echo "前の兄弟ノードの内容: '" . trim($previousSibling->textContent) . "'\n";
36        } else {
37            echo "前の兄弟ノードは見つかりませんでした。\n";
38        }
39    } else {
40        echo "指定された<span>要素が見つかりませんでした。\n";
41    }
42}
43
44// 関数を実行して、previousSiblingの動作を確認します。
45demonstratePreviousSibling();

PHP 8のDom\Nodeクラスに属するpreviousSiblingプロパティは、現在のノードの直前にある兄弟ノードを取得するために使用されます。このプロパティは引数を取らず、現在のノードと同じ親要素を持つ直前の兄弟ノードをDom\Nodeオブジェクトとして返します。もし直前の兄弟ノードが存在しない場合はnullが戻り値として返されます。このプロパティは、Dom\HTMLDocumentを通じてHTMLコンテンツから取得した要素など、全てのDom\Nodeオブジェクトで利用可能です。

サンプルコードでは、まずDom\HTMLDocumentを生成し、兄弟要素を持つHTMLコンテンツを読み込んでいます。次に、querySelectorAllメソッドを使用してターゲットとなる特定の<span>要素を検索し、そのpreviousSiblingプロパティにアクセスしています。これにより、<span>要素の直前にある<p>要素が兄弟ノードとして取得されます。取得された兄弟ノードが存在する場合、そのノードのnodeName(タグ名)とtextContent(内容)を表示することで、previousSiblingプロパティが正しく機能し、直前の兄弟ノードを取得できたことを確認しています。戻り値がnullである可能性を考慮し、ノードが実際に取得されたかをinstanceof Dom\Nodeでチェックする処理も含まれており、HTMLドキュメントの構造をプログラムで操作する際に非常に役立つ機能です。

previousSiblingプロパティは、ターゲットノードの直前の兄弟ノードを取得します。HTMLの改行やインデントによって生成されるテキストノードも兄弟ノードとして認識するため、想定外のテキストノードが取得される可能性がある点にご注意ください。要素ノードのみを対象としたい場合は、previousElementSiblingプロパティの利用も検討すると良いでしょう。また、前の兄弟ノードが存在しない場合はnullが返されます。取得したノードを安全に利用するためには、必ずif ($previousSibling instanceof Dom\Node)のように、nullではないこととDom\Node型であることのチェックを行ってからアクセスするようにしてください。これにより、実行時エラーを防ぎ、堅牢なコードを記述できます。

関連コンテンツ

関連IT用語

関連プログラミング言語