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

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

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

作成日: 更新日:

基本的な使い方

Dom\CharacterDataクラスのpreviousElementSiblingプロパティは、現在のノードの直前の兄弟要素ノードを返します。このプロパティは読み取り専用であり、CharacterDataノード(例えば、テキストノードやコメントノード)から、その兄弟要素にアクセスするために使用されます。

具体的には、あるテキストノードがあり、そのテキストノードの直前に要素ノードが存在する場合、このプロパティはその要素ノードを返します。もし直前の兄弟が要素ノードでない場合(例えば、別のテキストノードやコメントノードである場合)、または直前の兄弟が存在しない場合は、nullを返します。

システムエンジニアを目指す上で、DOM(Document Object Model)を操作する際に、このプロパティは非常に役立ちます。例えば、特定のテキストノードの内容に基づいて、その直前の要素ノードの属性を変更したり、コンテンツを操作したりする場合などに利用できます。DOMを理解し、適切に操作することで、動的なWebページの構築や、XMLデータの処理を効率的に行うことができるようになります。

このプロパティを使用する際は、対象のノードがCharacterDataノードであることを確認する必要があります。また、nullチェックを行い、存在しない場合に備えた処理を記述することも重要です。これにより、予期せぬエラーを防ぎ、安定したプログラムを作成することができます。

構文(syntax)

1readonly public ?DOMElement $previousElementSibling

引数(parameters)

引数なし

引数はありません

戻り値(return)

Dom\Element|null

このプロパティは、現在選択しているノードの直前の兄弟要素を返します。直前の兄弟要素が存在しない場合は、nullが返されます。

サンプルコード

Dom\CharacterData::previousElementSibling で前の兄弟要素を取得する

1<?php
2
3/**
4 * Dom\CharacterData::previousElementSibling の使用例を示します。
5 * Dom\Text ノード(Dom\CharacterData の子孫)の前の兄弟要素を取得します。
6 *
7 * このプロパティは、現在のノードの直前の兄弟要素ノードを返します。
8 * テキストノードやコメントノードなどの要素以外のノードはスキップされます。
9 *
10 * @return void
11 */
12function demonstratePreviousElementSibling(): void
13{
14    // DOMDocumentのインスタンスを作成
15    $dom = new DOMDocument();
16
17    // サンプルHTMLコンテンツをロードします。
18    // <p>要素と<span>要素の間に、コメントノードとターゲットとなるテキストノードを配置します。
19    // これにより、previousElementSiblingが要素以外のノードをスキップする挙動を確認できます。
20    // LIBXML_HTML_NOIMPLIED と LIBXML_HTML_NODEFDTD フラグは、
21    // DOMDocumentが自動的に <html> や <body> タグ、DOCTYPE宣言を追加しないようにします。
22    $html = <<<HTML
23    <div>
24        <p>最初の段落要素です。</p>
25        <!-- これはコメントノードです。previousElementSiblingによってスキップされます。 -->
26        前の兄弟要素を探すターゲットテキスト。
27        <span>次のスパン要素です。</span>
28    </div>
29    HTML;
30    $dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
31
32    echo "--- Dom\\CharacterData::previousElementSibling のデモンストレーション ---\n";
33
34    // <div>要素を見つけます。
35    $divElement = $dom->getElementsByTagName('div')->item(0);
36
37    if ($divElement === null) {
38        echo "エラー: <div> 要素が見つかりませんでした。\n";
39        return;
40    }
41
42    // <div>要素の子ノードを走査し、ターゲットとなる Dom\Text ノードを探します。
43    // ターゲットは「 前の兄弟要素を探すターゲットテキスト。 」というテキストノードです。
44    $targetTextNode = null;
45    foreach ($divElement->childNodes as $node) {
46        if ($node instanceof Dom\Text && trim($node->nodeValue) === '前の兄弟要素を探すターゲットテキスト。') {
47            $targetTextNode = $node;
48            break;
49        }
50    }
51
52    if ($targetTextNode === null) {
53        echo "エラー: ターゲットのテキストノードが見つかりませんでした。\n";
54        return;
55    }
56
57    echo "ターゲットの Dom\\Text ノードを見つけました: '" . trim($targetTextNode->nodeValue) . "'\n";
58
59    // ターゲットの Dom\Text ノード(Dom\CharacterData の子孫)の
60    // previousElementSibling プロパティにアクセスします。
61    // このテキストノードの直前の兄弟ノードはコメントノードですが、
62    // previousElementSibling は要素ノードのみを対象とするため、コメントノードをスキップし、
63    // その前の <p> 要素を返します。
64    $previousElement = $targetTextNode->previousElementSibling;
65
66    if ($previousElement !== null) {
67        echo "  前の兄弟要素 (previousElementSibling) が見つかりました:\n";
68        echo "    タイプ: " . get_class($previousElement) . "\n";
69        echo "    タグ名: " . $previousElement->tagName . "\n";
70        echo "    内容: " . trim($previousElement->nodeValue) . "\n";
71    } else {
72        echo "  前の兄弟要素 (previousElementSibling) は見つかりませんでした。\n";
73    }
74}
75
76// 関数を実行します。
77demonstratePreviousElementSibling();
78

PHP 8のDom\CharacterDataクラスに属するpreviousElementSiblingは、現在のノードの直前の兄弟要素ノードを取得するためのプロパティです。このプロパティには引数がなく、戻り値としてDom\Elementオブジェクトを返します。直前の兄弟要素が存在しない場合はnullが返されます。

previousElementSiblingの重要な特徴は、テキストノードやコメントノードなどの要素ではないノードはスキップし、要素ノードだけを対象とすることです。

提供されたサンプルコードでは、まずDOMDocumentを用いてHTMLコンテンツを読み込みます。このHTMLには、<p>要素、コメントノード、ターゲットとなるテキストノード、<span>要素が順に配置されています。コードは、「前の兄弟要素を探すターゲットテキスト。」というDom\Textノードをターゲットとして特定します。そして、このターゲットテキストノードのpreviousElementSiblingプロパティにアクセスします。ターゲットの直前の兄弟ノードはコメントノードですが、previousElementSiblingはそのコメントノードをスキップし、さらにその前の兄弟要素である<p>要素を正確に取得する様子を示しています。これにより、要素以外のノードが無視され、目的の要素ノードだけが取得される挙動を具体的に理解できます。

Dom\CharacterData::previousElementSiblingは、現在のノードの直前の兄弟「要素」ノードを返します。テキストノードやコメントノードなどの要素以外のノードはスキップされるため、意図した通りの要素が取得できるか、HTMLのDOM構造をよく確認してください。戻り値はDom\Elementオブジェクトか、対応する要素が見つからない場合はnullです。そのため、取得した結果からプロパティ(例: tagName)にアクセスする前には必ずnullチェックを行い、エラーを防ぐ必要があります。サンプルコードでDOMDocument::loadHTMLに指定されているLIBXML_HTML_NOIMPLIEDなどのフラグは、HTMLをロードする際に、PHPが自動的に<html><body>タグなどを追加するのを防ぎ、より直接的に指定したHTMLのDOM構造を扱いたい場合に便利です。このプロパティは、Dom\TextノードなどDom\CharacterDataを継承するクラスのインスタンスから利用できます。

PHP Dom\Element::previousElementSibling を使う

1<?php
2
3declare(strict_types=1);
4
5/**
6 * Dom\Element::previousElementSibling の使用例を示します。
7 * このメソッドは、指定された要素の直前にある要素の兄弟ノードを返します。
8 * テキストノードやコメントノードなど、要素以外のノードはスキップされます。
9 * これはJavaScriptのElement.previousElementSiblingと概念が同じです。
10 */
11function demonstratePreviousElementSibling(): void
12{
13    // 新しいDom\Documentインスタンスを作成します (PHP 8の名前空間を使用)。
14    $dom = new Dom\Document();
15
16    // 解析するサンプルHTML文字列を定義します。
17    // 要素間にテキストノードやコメントノードを含めることで、
18    // previousElementSibling がそれらをどのようにスキップするかを示します。
19    $html = <<<HTML
20    <div id="container">
21        <!-- これはコメントノードです -->
22        <span id="first">最初の要素</span>
23        これはテキストノード1です。
24        <p id="middle">中間要素</p>
25        これはテキストノード2です。
26        <a id="target-link" href="#">ターゲットリンク</a>
27        これはテキストノード3です。
28        <button id="last-button">最後のボタン</button>
29    </div>
30    HTML;
31
32    // HTMLをDOMドキュメントにロードします。
33    // LIBXML_NOERROR と LIBXML_NOWARNING は、HTMLのパースエラーや警告を抑制します。
34    $dom->loadHTML($html, LIBXML_NOERROR | LIBXML_NOWARNING);
35
36    // ID 'target-link' を持つ要素を検索します。この要素の直前の要素を見つけます。
37    $targetElement = $dom->getElementById('target-link');
38
39    // ターゲット要素が正常に見つかり、Dom\Elementのインスタンスであることを確認します。
40    if ($targetElement instanceof Dom\Element) {
41        echo "現在のターゲット要素: <{$targetElement->nodeName}> (ID: {$targetElement->getAttribute('id')})\n";
42        echo "  textContent: \"{$targetElement->textContent}\"\n\n";
43
44        // previousElementSibling を使用して、ターゲット要素の直前にある「要素」の兄弟ノードを取得します。
45        // "これはテキストノード2です。" をスキップし、<p id="middle"> が返されます。
46        $previousElement = $targetElement->previousElementSibling;
47
48        if ($previousElement instanceof Dom\Element) {
49            echo "--- previousElementSibling の結果 (直前の要素の兄弟) ---\n";
50            echo "  見つかった要素: <{$previousElement->nodeName}> (ID: {$previousElement->getAttribute('id')})\n";
51            echo "  textContent: \"{$previousElement->textContent}\"\n";
52        } else {
53            echo "--- previousElementSibling の結果 ---\n";
54            echo "  直前の要素の兄弟は見つかりませんでした。\n";
55        }
56
57        echo "\n--- 参考: previousSibling との比較 ---\n";
58
59        // previousSibling を使用して、ターゲット要素の直前にある「ノード」(要素、テキスト、コメントなど、何でも)を取得します。
60        // この場合、"これはテキストノード2です。" (Dom\Textノード) が返されます。
61        $previousNode = $targetElement->previousSibling;
62
63        if ($previousNode instanceof Dom\Node) {
64            echo "  見つかったノード: {$previousNode->nodeName} (タイプ: {$previousNode->nodeType})\n";
65            echo "  textContent: \"{$previousNode->textContent}\"\n";
66            // ノードタイプ3はDom\Textノード(Dom\CharacterDataのサブクラス)を示します。
67            if ($previousNode->nodeType === XML_TEXT_NODE) {
68                 echo "  (このノードはテキストノードであり、Dom\\CharacterDataのサブクラスです。)\n";
69            }
70        } else {
71            echo "  直前のノードの兄弟は見つかりませんでした。\n";
72        }
73
74    } else {
75        echo "エラー: ターゲット要素(ID: target-link)が見つかりませんでした。\n";
76    }
77}
78
79// 関数を実行してサンプルコードの動作を確認します。
80demonstratePreviousElementSibling();
81

PHP 8のDom\CharacterData::previousElementSiblingは、DOM(Document Object Model)ツリー内で、特定の要素の直前にある「要素」の兄弟ノードを取得するためのプロパティです。このプロパティは引数を取りません。

例えば、HTMLドキュメント内で <p id="middle"><a id="target-link"> の間にテキストノードやコメントノードがあったとしても、target-link要素からpreviousElementSiblingを使用すると、間の要素以外のノードをスキップし、直前の兄弟「要素」である p 要素を直接取得します。

戻り値は、条件に合致する要素が見つかれば Dom\Element クラスのインスタンスとして返されますが、直前に要素の兄弟ノードが存在しない場合は null を返します。これは、DOMノードの種類に関わらず直前の兄弟ノードを返す previousSibling プロパティとは異なり、純粋な要素のみを対象とする点で区別されます。

このプロパティの挙動は、JavaScriptのElement.previousElementSiblingと概念が同じであり、ウェブページの構造をプログラムで操作する際に、特定の要素の前後関係を簡単に特定するために非常に便利です。サンプルコードでは、IDがtarget-linkの要素からpreviousElementSiblingを使い、直前のmiddleというIDを持つp要素を正確に取得する様子が示されています。

previousElementSiblingは、指定された要素の直前にある「HTML要素」の兄弟ノードのみを取得します。テキストノードやコメントノードといった要素以外のノードはスキップされるため、その点を理解しておくことが重要です。このプロパティは、直前の要素が見つからない場合にnullを返しますので、取得した結果をinstanceof Dom\Elementで必ずチェックし、nullの可能性を考慮した処理を記述してください。兄弟ノードの種類を問わず直前のノードを取得したい場合は、previousSiblingプロパティとの違いを明確に理解しておくことが、意図しない挙動を防ぐ上で非常に大切です。また、HTMLの読み込みが正常に行われたか、目的の要素が正しく取得できたかを常に確認し、堅牢なコードを心がけましょう。

関連コンテンツ

関連IT用語

関連プログラミング言語