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

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

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

作成日: 更新日:

基本的な使い方

previousElementSiblingプロパティは、DOMツリーにおける現在の処理命令ノード(ProcessingInstruction)の、直前に出現する兄弟要素ノード(Element)を保持するプロパティです。DOMツリーとは、XMLやHTML文書の構造を階層的な木構造で表現したものです。このプロパティは、同じ親ノードを持つ兄弟ノードの中から、現在のノードより前に位置する最も近い「要素ノード」、つまりHTMLの<div>タグや<p>タグのようなものだけを検索して返します。もし、すぐ前の兄弟ノードがテキストやコメントなど要素以外のものであった場合でも、このプロパティはそれを無視し、さらに前方を遡って最初の要素ノードを見つけ出します。この点は、テキストノードなどを含むあらゆる種類のノードを返すpreviousSiblingプロパティとの大きな違いです。先行する兄弟ノードに要素が一つも存在しない場合、このプロパティの値はnullになります。なお、このプロパティは読み取り専用のため、直接値を代入して変更することはできません。

構文(syntax)

1<?php
2
3$doc = new \Dom\Document();
4$doc->loadXML(
5    <<<XML
6    <root>
7      <p>Paragraph 1</p>
8      <!-- comment -->
9      <?php-pi data?>
10      <span>Span Element</span>
11    </root>
12    XML
13);
14
15// ProcessingInstruction ノード (<?php-pi data?>) を取得
16$pi = $doc->documentElement->childNodes->item(2);
17
18// 直前にある兄弟「要素」を取得します (コメントノードは無視されます)
19$previousElement = $pi->previousElementSibling;
20
21// 取得した要素のタグ名を出力します
22if ($previousElement !== null) {
23    // "p" が出力されます
24    echo $previousElement->tagName;
25}
26
27?>

引数(parameters)

引数なし

引数はありません

戻り値(return)

Dom\Element|null

このプロパティは、現在のXML/HTML文書内において、この要素の直前に位置する兄弟要素を返します。もし直前に兄弟要素が存在しない場合は、nullが返されます。

サンプルコード

Dom\ProcessingInstructionのpreviousElementSiblingを取得する

1<?php
2
3/**
4 * Dom\ProcessingInstruction::previousElementSibling の使用例を示します。
5 * このプロパティは、現在のノードの直前の兄弟要素ノードを返します。
6 * 要素ノード(Dom\Element)以外の兄弟ノード(テキストノード、コメントノードなど)はスキップされます。
7 * 直前の兄弟要素ノードがない場合は null を返します。
8 */
9function demonstrateProcessingInstructionPreviousElementSibling(): void
10{
11    // 1. 新しいDOMドキュメントを作成します。
12    $document = new Dom\Document();
13
14    // 2. ルート要素(div)を作成し、ドキュメントに追加します。
15    // このルート要素が他のノードの親になります。
16    $rootElement = new Dom\Element('div');
17    $document->appendChild($rootElement);
18
19    // 3. 最初の兄弟要素(p)を作成し、ルート要素に追加します。
20    // これが処理命令ノードの「前の要素」になることを期待します。
21    $paragraphElement = new Dom\Element('p');
22    $paragraphElement->textContent = 'これは最初の段落要素です。';
23    $rootElement->appendChild($paragraphElement);
24
25    // 4. 処理命令ノード(Dom\ProcessingInstruction)を作成し、ルート要素に追加します。
26    // このノードに対して previousElementSibling プロパティにアクセスします。
27    $processingInstruction = new Dom\ProcessingInstruction('php', 'echo "Hello from PI!";');
28    $rootElement->appendChild($processingInstruction);
29
30    // 5. 最後の兄弟要素(span)を作成し、ルート要素に追加します。
31    $spanElement = new Dom\Element('span');
32    $spanElement->textContent = 'これは最後のスパン要素です。';
33    $rootElement->appendChild($spanElement);
34
35    // ドキュメントの構造を出力して確認します。
36    echo "--- ドキュメント構造の概観 ---\n";
37    // saveHTML()は完全なHTMLを生成するため、ここでは分かりやすいように簡易的に表示
38    // 実際には $document->saveHTML() で確認可能
39    echo $rootElement->nodeName . "\n";
40    foreach ($rootElement->childNodes as $node) {
41        echo "  - " . $node->nodeName;
42        if ($node instanceof Dom\Element) {
43            echo " (Element: <{$node->tagName}>)";
44        } elseif ($node instanceof Dom\ProcessingInstruction) {
45            echo " (ProcessingInstruction: <?{$node->target} ...?>)";
46        }
47        echo "\n";
48    }
49    echo "-----------------------------\n\n";
50
51    echo "ターゲットの処理命令ノード: <?{$processingInstruction->target} {$processingInstruction->data}?>\n\n";
52
53    // 6. 処理命令ノードの直前の兄弟要素ノードを取得します。
54    $previousElement = $processingInstruction->previousElementSibling;
55
56    echo "--- previousElementSibling の結果 ---\n";
57    if ($previousElement instanceof Dom\Element) {
58        // 直前の兄弟要素が Dom\Element のインスタンスである場合
59        echo "直前の兄弟要素ノードが見つかりました。\n";
60        echo "タグ名: " . $previousElement->tagName . "\n";
61        echo "テキストコンテンツ: " . $previousElement->textContent . "\n";
62    } elseif ($previousElement === null) {
63        // 直前の兄弟要素が見つからない(または要素ノードではない)場合
64        echo "直前の兄弟要素ノードは見つかりませんでした。\n";
65    } else {
66        // 通常は発生しないが、型安全のために含める
67        echo "予期せぬタイプのノードが返されました。\n";
68    }
69    echo "-------------------------------------\n";
70}
71
72// 関数を実行して動作を確認します。
73demonstrateProcessingInstructionPreviousElementSibling();
74
75?>

PHP 8のDom拡張機能に属するDom\ProcessingInstructionクラスのpreviousElementSiblingプロパティは、現在の処理命令ノードの直前にある「兄弟要素ノード」を取得するために使用されます。このプロパティは、引数を必要とせず、テキストノードやコメントノードのような要素以外の兄弟ノードをスキップし、要素ノード(Dom\Element)のみを探します。

サンプルコードでは、Dom\Document内にdivp要素、処理命令ノード、span要素が順に配置されたDOM構造を作成しています。この中で、対象となる処理命令ノードからpreviousElementSiblingプロパティにアクセスすると、その直前の兄弟ノードであるp要素がDom\Element型のオブジェクトとして返されます。

もし直前の兄弟ノードが要素ノードでなかった場合や、そもそも直前の兄弟ノードが存在しない場合は、このプロパティはnullを返します。この機能により、DOMツリー内の特定の処理命令ノードを基準として、その直前の要素だけを効率的に特定し、関連する操作を行うことが可能になります。取得された要素ノードからは、タグ名やテキストコンテンツなどの情報にアクセスできます。

このプロパティは、現在のノードの直前の兄弟ノードのうち、要素ノード(Dom\Element)のみを返します。テキストノードやコメントノードなど、要素以外のノードはスキップされる点に特に注意し、ノード構成を理解してください。直前の兄弟要素がない場合はnullが返されます。必ずnullチェックを行い、安全にDom\Elementとして扱いましょう。nullチェックを怠ると、存在しないプロパティにアクセスしてエラーになる可能性があります。このサンプルはDom\ProcessingInstructionノードでの利用例ですが、他のDOMノードにも同様のプロパティが存在する場合があり、DOM操作の理解を深める上で役立ちます。

PHP: Dom\ProcessingInstructionのpreviousElementSiblingを取得する

1<?php
2
3/**
4 * Dom\ProcessingInstruction クラスの previousElementSibling プロパティの動作を実演する関数。
5 *
6 * この関数は、HTMLドキュメント内で特定の処理命令 (Processing Instruction) を探し、
7 * その直前にある要素ノード (Element) を previousElementSibling プロパティを使って取得し、表示します。
8 * JavaScriptの同名プロパティと同様の機能を提供します。
9 */
10function demonstrateProcessingInstructionPreviousElementSibling(): void
11{
12    // 1. サンプルとなるHTML文字列を作成します。
13    // PHPの処理命令 `<?php ... ?>` は、DomDocument::loadHTML でパースされる際に
14    // Dom\ProcessingInstruction ノードとして扱われます。
15    // 意図的に処理命令の直前に div 要素を配置し、後続にも div 要素を配置します。
16    $html = <<<HTML
17<!DOCTYPE html>
18<html>
19<body>
20    <div id="preceding-element">これは、処理命令の直前の要素です。</div>
21    <?php target_instruction_data ?>
22    <div id="following-element">これは、処理命令の直後の要素です。</div>
23</body>
24</html>
25HTML;
26
27    // 2. Dom\Document オブジェクトを作成し、HTML文字列を読み込みます。
28    // PHP 8では、DOM拡張のクラスは Dom\ 名前空間下にあります。
29    $dom = new Dom\Document();
30    // HTMLのパースエラーが発生する可能性があるため、@ を使用してエラー出力を抑制しています。
31    // 実際のアプリケーションでは、より堅牢なエラーハンドリングを推奨します。
32    @$dom->loadHTML($html);
33
34    $targetInstruction = null;
35
36    // 3. ドキュメントツリー内から目的の Dom\ProcessingInstruction ノードを探します。
37    // この例では、<body> 要素の子ノードを走査して見つけます。
38    $body = $dom->getElementsByTagName('body')->item(0);
39
40    if ($body) {
41        foreach ($body->childNodes as $node) {
42            // ノードが Dom\ProcessingInstruction のインスタンスであり、
43            // そのデータ内容に特定の文字列が含まれているかを確認してターゲットを特定します。
44            // loadHTML でパースされた PHP 処理命令は、target が 'php' となり、
45            // data プロパティには `<?php ... ?>` の中の文字列が入ります。
46            if ($node instanceof Dom\ProcessingInstruction && strpos($node->data, 'target_instruction_data') !== false) {
47                $targetInstruction = $node;
48                break; // 目的のノードが見つかったらループを終了します。
49            }
50        }
51    }
52
53    // 4. ターゲットの処理命令ノードが見つかった場合、previousElementSibling を使用します。
54    if ($targetInstruction) {
55        echo "Dom\ProcessingInstruction ノードが見つかりました。\n";
56        echo "  ターゲット名: " . $targetInstruction->target . "\n";
57        echo "  データ内容: " . $targetInstruction->data . "\n\n";
58
59        // previousElementSibling プロパティは、直前の兄弟ノードが要素ノードであればそれを返し、
60        // そうでなければ null を返します。
61        $previousElement = $targetInstruction->previousElementSibling;
62
63        // 5. 取得した結果を評価し、表示します。
64        if ($previousElement instanceof Dom\Element) {
65            echo "previousElementSibling によって直前の兄弟要素ノードが見つかりました。\n";
66            echo "  タグ名: " . $previousElement->tagName . "\n";
67            echo "  ID属性: " . ($previousElement->hasAttribute('id') ? $previousElement->getAttribute('id') : 'なし') . "\n";
68            echo "  テキストコンテンツ: " . trim($previousElement->textContent) . "\n";
69        } else {
70            echo "previousElementSibling は null を返しました。直前に要素ノードが存在しません。\n";
71        }
72    } else {
73        echo "ターゲットの Dom\ProcessingInstruction ノードが見つかりませんでした。\n";
74        echo "HTML内の '<?php target_instruction_data ?>' が正しく処理命令としてパースされているか確認してください。\n";
75    }
76}
77
78// 関数を実行して、previousElementSibling の動作を確認します。
79demonstrateProcessingInstructionPreviousElementSibling();
80

PHP 8のDom\ProcessingInstructionクラスのpreviousElementSiblingプロパティは、DOMツリー内で処理命令ノードの直前にある要素ノードを取得するものです。引数はなく、直前の兄弟ノードが要素ノードであればDom\Elementオブジェクトを、そうでなければnullを返します。この機能はJavaScriptの同名プロパティと同様に動作します。

提供されたサンプルコードは、このプロパティの具体的な利用例です。まず、処理命令と直前のdiv要素を含むHTML文字列を用意し、Dom\Documentでパースします。次に、ドキュメントツリーから特定の処理命令ノードを検索します。目的のノードが見つかると、previousElementSiblingプロパティを使用して直前の要素ノードを取得し、その情報(タグ名、ID、テキストコンテンツ)を表示します。直前に要素ノードがない場合はnullが返されるため、取得の可否によって処理を分岐させ、DOM構造を安全に操作できることを確認できます。

previousElementSibling プロパティは、現在のノードの直前にある兄弟ノードの中から、要素ノードのみを探して返します。改行や空白などのテキストノード、コメントノードは無視されスキップされます。もし直前に要素ノードが存在しない場合は null が返されるため、戻り値が Dom\Element のインスタンスであるか、null でないかを必ず確認してから、そのプロパティへアクセスするようにしてください。Dom\Document::loadHTML メソッドは、PHPの処理命令 <?php ... ?>Dom\ProcessingInstruction ノードとして扱います。サンプルコードでの @ によるエラー抑制は開発時の便宜的なものであり、実際のシステムではエラーログの確認など、より堅牢なエラーハンドリングを導入することが重要です。

関連コンテンツ

関連IT用語

関連プログラミング言語