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

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

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

作成日: 更新日:

基本的な使い方

Dom\ElementクラスのpreviousElementSiblingプロパティは、現在の要素の直前の兄弟要素(element)を返却するプロパティです。このプロパティは読み取り専用であり、値を設定することはできません。

具体的には、DOM(Document Object Model)ツリー構造において、ある要素のすぐ上に位置する兄弟要素、つまり同じ親要素を持つ直前の要素を取得するために使用されます。もし直前の兄弟要素が存在しない場合、previousElementSiblingプロパティはnullを返します。

このプロパティは、DOMツリーを操作し、特定の要素の前にある要素を特定する必要がある場合に非常に役立ちます。例えば、リスト構造において、現在のリストアイテムの前に表示されるアイテムを特定したり、複雑なHTML構造の中で特定の要素の配置を解析したりする際に利用できます。

previousElementSiblingプロパティは、要素間の関係性を辿る上で基本的な機能を提供し、DOM操作における柔軟性と効率性を向上させます。他の兄弟要素を取得するためのプロパティ(例えば、nextElementSiblingプロパティ)と組み合わせて使用することで、DOMツリー内の要素を様々な方法でナビゲートすることが可能です。システム開発においては、動的に生成されたHTMLコンテンツを操作したり、ユーザーの操作に応じて要素の表示を切り替えたりする際に、このプロパティが重要な役割を果たします。

構文(syntax)

1readonly public ?Dom\Element $previousElementSibling

引数(parameters)

引数なし

引数はありません

戻り値(return)

DOMElement|null

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

サンプルコード

previousElementSiblingで直前の兄弟要素を取得する

1<?php
2
3/**
4 * 指定されたHTML文字列から特定の要素を取得し、その直前の兄弟要素(Element)の情報を表示します。
5 *
6 * Dom\Element::previousElementSibling プロパティの使用例を示します。
7 * このプロパティは、現在の要素の直前にある要素ノード(コメントやテキストノードは含まない)を返します。
8 * 直前に要素ノードが存在しない場合は null を返します。
9 *
10 * @param string $html HTML文字列
11 * @param string $xpathQuery ターゲット要素を特定するためのXPathクエリ
12 */
13function demonstratePreviousElementSibling(string $html, string $xpathQuery): void
14{
15    // DOMDocumentオブジェクトを初期化し、HTMLをロードします。
16    // @ を使用してHTMLパース時の警告を抑制していますが、
17    // 実際のアプリケーションでは、エラーハンドリングを適切に行うことを推奨します。
18    $dom = new DOMDocument();
19    @$dom->loadHTML($html);
20
21    // XPathオブジェクトを作成し、指定されたクエリに合致する最初のターゲット要素を取得します。
22    // PHP 8ではDom\ElementはDOMElementのエイリアスであり、互換性があります。
23    $xpath = new DOMXPath($dom);
24    $targetElement = $xpath->query($xpathQuery)->item(0);
25
26    // ターゲット要素がDom\Elementのインスタンスであることを確認します。
27    if ($targetElement instanceof Dom\Element) {
28        echo "ターゲット要素: <" . $targetElement->tagName . "> (" . trim($targetElement->textContent) . ")\n";
29
30        // previousElementSibling プロパティにアクセスします。
31        // これは、現在の要素の直前にある要素ノードを返します。
32        $previousSibling = $targetElement->previousElementSibling;
33
34        if ($previousSibling instanceof Dom\Element) {
35            echo "-> 直前の兄弟要素 (previousElementSibling) が見つかりました。\n";
36            echo "   要素名: <" . $previousSibling->tagName . ">\n";
37            echo "   テキスト: \"" . trim($previousSibling->textContent) . "\"\n";
38            if ($previousSibling->hasAttribute('class')) {
39                echo "   クラス属性: \"" . $previousSibling->getAttribute('class') . "\"\n";
40            }
41        } else {
42            echo "-> 直前の兄弟要素 (previousElementSibling) は見つかりませんでした (null を返しました)。\n";
43        }
44    } else {
45        echo "エラー: 指定されたXPathクエリ '" . $xpathQuery . "' でターゲット要素が見つからないか、それが要素ノードではありませんでした。\n";
46    }
47    echo "\n"; // 出力間の区切り
48}
49
50// --- 使用例 ---
51
52// 例1: 直前の要素が存在する場合
53$html1 = <<<HTML
54<div id="container-1">
55    <p>最初の段落</p>
56    <!-- これはコメントなのでpreviousElementSiblingでは無視されます -->
57    <span class="highlight">ハイライトされたスパン</span>
58    <div id="target-1">ターゲットの要素A</div>
59    <p class="last">最後の段落</p>
60</div>
61HTML;
62echo "--- 例1: 直前の兄弟要素が存在する場合 ---\n";
63demonstratePreviousElementSibling($html1, '//*[@id="target-1"]');
64
65// 例2: 直前の要素が存在しない場合(親要素内の最初の要素)
66$html2 = <<<HTML
67<div id="container-2">
68    <p id="target-2">親要素内の最初の段落</p>
69    <span>別のスパン要素</span>
70    <div>別の要素</div>
71</div>
72HTML;
73echo "--- 例2: 直前の兄弟要素が存在しない場合 ---\n";
74demonstratePreviousElementSibling($html2, '//*[@id="target-2"]');
75
76// 例3: 直前にテキストノードやコメントがあるが、要素ノードのみを考慮する場合
77$html3 = <<<HTML
78<div id="container-3">
79    <p>先頭の要素</p>
80    これは要素ではないテキストノードです。
81    <!-- これも要素ではないコメントです -->
82    <span id="target-3">ターゲットのスパン</span>
83</div>
84HTML;
85echo "--- 例3: 直前にテキストノードやコメントがあっても要素ノードのみを対象とする場合 ---\n";
86demonstratePreviousElementSibling($html3, '//*[@id="target-3"]');
87
88?>

PHP 8のDom\Element::previousElementSiblingプロパティは、HTMLやXMLドキュメント内で特定の要素の直前にある兄弟要素(Element)を取得するために使用されます。このプロパティにアクセスすると、現在の要素と同じ親要素を持ち、かつ直前に位置するHTMLタグで構成された要素オブジェクトを返します。例えば、<div><p>前の要素</p><span>ターゲット</span></div>のような構造で<span>要素にこのプロパティを使うと、<p>要素のオブジェクトが戻り値となります。この際、要素の間にテキストノードやコメントノードがあっても、それらは兄弟要素とは見なされず無視される点が特徴です。

直前に要素ノードが存在しない場合、例えば親要素内の最初の要素である場合などには、戻り値としてnullを返します。サンプルコードでは、与えられたHTML文字列から特定のターゲット要素を見つけ出し、そのターゲット要素のpreviousElementSiblingプロパティにアクセスして、直前の兄弟要素を取得する一連の流れを示しています。取得した要素が存在すれば、そのタグ名やテキスト内容などの詳細を表示し、nullが返された場合は「直前の兄弟要素は見つかりませんでした」と表示することで、プロパティの挙動を確認できます。このプロパティは、ドキュメント構造を解析し、隣接する要素間の関係性を簡単にたどる際に非常に役立ちます。

Dom\Element::previousElementSiblingは、現在の要素の直前にある「要素ノード」のみを返します。テキストノードやコメントノードは無視される点に注意が必要です。直前に要素ノードが存在しない場合はnullを返すため、結果を扱う前には必ずnullチェックを行い、適切な処理を記述してください。また、HTMLのパースにはDOMDocument::loadHTML()を使用しますが、このメソッドは不正なHTMLに対して警告を出すことがあります。サンプルコードでは@で警告を抑制していますが、実際のシステム開発ではエラーハンドリングを適切に行うことが重要です。PHP 8ではDom\ElementDOMElementのエイリアスとして導入されており、既存のDOM関連コードとの互換性がありますのでご安心ください。

Dom\Element::previousElementSibling で直前の要素を取得する

1<?php
2
3/**
4 * Dom\Element::previousElementSibling の使用例を示します。
5 * これは、指定された要素の直前の要素ノードを返します。
6 * テキストノード、コメントノードなどの非要素ノードはスキップされます。
7 */
8function demonstratePreviousElementSibling(): void
9{
10    // 1. 新しい DOM Document を作成します
11    $document = new Dom\Document();
12    // 整形された出力を有効にする(必要に応じて)
13    $document->formatOutput = true;
14
15    // 2. ルート要素 (例: <body>) を作成し、ドキュメントに追加します
16    $body = $document->createElement('body');
17    $document->appendChild($body);
18
19    // 3. いくつかの異なるタグを持つ子要素を body に追加します
20    $divElement = $document->createElement('div', 'これは最初のDIV要素です。');
21    $body->appendChild($divElement);
22
23    // テキストノードを追加して、previousElementSibling がそれをスキップすることを示します
24    $body->appendChild($document->createTextNode('  これはテキストノードです。  '));
25
26    $pElement1 = $document->createElement('p', 'これは最初のP要素です。');
27    $body->appendChild($pElement1);
28
29    // コメントノードを追加して、previousElementSibling がそれをスキップすることを示します
30    $body->appendChild($document->createComment('これはコメントノードです。'));
31
32    $spanElement = $document->createElement('span', 'これはSPAN要素です。');
33    $body->appendChild($spanElement);
34
35    $pElement2 = $document->createElement('p', 'これは2番目のP要素です。');
36    $body->appendChild($pElement2);
37
38    echo "--- オリジナル DOM 構造 ---" . PHP_EOL;
39    echo $document->saveHTML() . PHP_EOL;
40
41    // 4. previousElementSibling を使用する要素を選択します
42    // 例として、$pElement2 (2番目のP要素) を選びます
43    echo "--- Dom\\Element::previousElementSibling のデモンストレーション ---" . PHP_EOL;
44    echo "現在の要素: <" . $pElement2->tagName . "> ('" . $pElement2->textContent . "')" . PHP_EOL;
45
46    // 5. previousElementSibling を呼び出して直前の要素ノードを取得します
47    $previousSiblingElement = $pElement2->previousElementSibling;
48
49    // 6. 戻り値を確認し、情報を出力します
50    if ($previousSiblingElement instanceof Dom\Element) {
51        echo "直前の要素兄弟ノードが見つかりました: <" . $previousSiblingElement->tagName . ">" . PHP_EOL;
52        echo "内容: '" . $previousSiblingElement->textContent . "'" . PHP_EOL;
53    } else {
54        echo "直前の要素兄弟ノードは見つかりませんでした。" . PHP_EOL;
55    }
56
57    echo PHP_EOL . "--- 最初の要素のデモンストレーション ---" . PHP_EOL;
58    // 最初の要素 (divElement) は要素兄弟を持たないはずです
59    echo "現在の要素: <" . $divElement->tagName . "> ('" . $divElement->textContent . "')" . PHP_EOL;
60    $previousForFirst = $divElement->previousElementSibling;
61    if ($previousForFirst instanceof Dom\Element) {
62        echo "直前の要素兄弟ノードが見つかりました: <" . $previousForFirst->tagName . ">" . PHP_EOL;
63    } else {
64        echo "直前の要素兄弟ノードは見つかりませんでした (期待通り)。" . PHP_EOL;
65    }
66}
67
68// デモンストレーション関数を実行します
69demonstratePreviousElementSibling();

PHP 8のDom\Element::previousElementSiblingは、DOM(Document Object Model)を操作する際に、特定の要素の直前にある「要素ノード」を取得するためのプロパティです。このプロパティは引数を取らず、戻り値として直前の要素が見つかればDom\Elementオブジェクトを、見つからない場合はnullを返します。

その特徴は、テキストノードやコメントノードといった「非要素ノード」をスキップし、要素ノードだけを対象とすることです。これにより、DOMツリー内で要素間の関係を簡潔にたどることができます。

サンプルコードでは、まず複数のdivpspan要素、そしてテキストノードやコメントノードを含むDOM構造を作成しています。次に、$pElement2という2番目のP要素からpreviousElementSiblingプロパティにアクセスしています。この際、$pElement2の直前にはコメントノードがありますが、プロパティはそのコメントノードをスキップし、その前のspan要素を正確に取得します。また、最初の要素である$divElementに対してこのプロパティを使用すると、直前に要素ノードが存在しないため、期待通りnullが返される様子も示されており、previousElementSiblingがDOMツリー内での要素間のナビゲーションを効率的に行うために利用されることがわかります。

Dom\Element::previousElementSiblingは、指定された要素の直前にある「要素ノード」のみを取得します。テキストノードやコメントノードなどの非要素ノードはスキップされますので、DOM構造の把握が重要です。

直前の要素ノードが存在しない場合(例えば、対象要素が親の最初の子要素である場合)は、戻り値としてnullが返されます。このため、取得した値がnullでないか(instanceof Dom\Elementなどを用いて)必ず確認し、適切な処理を行う必要があります。確認を怠ると、nullに対してプロパティアクセスを行った際にエラーが発生する可能性がありますのでご注意ください。これは、JavaScriptの同名のプロパティと挙動が共通しています。

関連コンテンツ

関連IT用語

関連プログラミング言語