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

【PHP8.x】DOMEntityReference::DOCUMENT_POSITION_CONTAINED_BY定数の使い方

DOCUMENT_POSITION_CONTAINED_BY定数の使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

『DOCUMENT_POSITION_CONTAINED_BY定数は、DOMツリー内における2つのノードの位置関係を示すための定数です。具体的には、あるノードが別のノードに内包されている、つまり子孫である状態を表します。この定数は、主にDOMNode::compareDocumentPosition()メソッドの戻り値を評価する際に利用されます。compareDocumentPosition()メソッドは、2つのノードの位置関係を比較し、その結果をビットマスクと呼ばれる単一の数値で返します。ビットマスクは、複数の状態を同時に表現できる便利な仕組みです。例えば、$nodeA->compareDocumentPosition($nodeB) を実行した際に、$nodeA$nodeBの子孫ノードである場合、メソッドの戻り値にはDOCUMENT_POSITION_CONTAINED_BYに対応するビットが含まれています。開発者は、この戻り値とDOCUMENT_POSITION_CONTAINED_BY定数をビット単位のAND演算子(&)で比較することにより、$nodeA$nodeBに含まれているかどうかを確実に判定できます。この定数はDOCUMENT_POSITION_CONTAINSと対の関係にあり、XMLやHTMLドキュメントの複雑な階層構造をプログラムで正確に把握し、操作する上で重要な役割を果たします。

構文(syntax)

1<?php
2
3var_dump(DOMEntityReference::DOCUMENT_POSITION_CONTAINED_BY);

引数(parameters)

引数なし

引数はありません

戻り値(return)

int

DOCUMENT_POSITION_CONTAINED_BYは、あるノードが別のノードに完全に含まれている場合の相対的な位置を示す定数で、整数値の16を返します。

サンプルコード

PHP: DOMノード位置比較で先行ノードを判定する

1<?php
2
3/**
4 * DOMノード間の位置関係を比較する例を示します。
5 * 特に、指定されたノードが他のノードよりもドキュメント内で「先行している」かどうかを
6 * 判定する DOM_DOCUMENT_POSITION_PRECEDING 定数の使用方法に焦点を当てます。
7 */
8function demonstrateNodePositionComparison(): void
9{
10    // 新しい DOMDocument オブジェクトを作成します。
11    // '1.0' はXMLのバージョン、'UTF-8' はエンコーディングを指定します。
12    $dom = new DOMDocument('1.0', 'UTF-8');
13    // 出力されるXMLを整形(インデントなどを追加)するように設定します。
14    $dom->formatOutput = true;
15
16    // HTMLの <body> 要素を作成し、それをドキュメントのルート要素として追加します。
17    $body = $dom->createElement('body');
18    $dom->appendChild($body);
19
20    // 最初のノードとして <h1> 要素(見出し)を作成し、テキストを設定してから <body> の子として追加します。
21    $h1 = $dom->createElement('h1', 'DOMノードの位置');
22    $body->appendChild($h1);
23
24    // 2番目のノードとして <p> 要素(段落)を作成し、テキストを設定してから <body> の子として追加します。
25    // この <p> ノードは、DOMツリー上で <h1> ノードの「後」に位置します。
26    $p = $dom->createElement('p', 'これはDOM要素の位置関係を示す段落です。');
27    $body->appendChild($p);
28
29    // 現在のDOM構造をXML形式で表示します。
30    echo "--- 現在のDOM構造 ---\n";
31    echo $dom->saveXML();
32    echo "--------------------\n\n";
33
34    // <p> ノードから見て <h1> ノードがドキュメント内でどこに位置するかを比較します。
35    // DOMNode::compareDocumentPosition() メソッドは、呼び出し元のノード($p)と
36    // 引数のノード($h1)の相対的な位置関係を示すビットマスクの整数値を返します。
37    //
38    // この場合、<p> ノードの前に <h1> ノードが位置しているため、
39    // 返される結果には DOM_DOCUMENT_POSITION_PRECEDING 定数が含まれるはずです。
40    $positionResult = $p->compareDocumentPosition($h1);
41
42    echo "p ノードと h1 ノードの比較結果 (整数値): " . $positionResult . "\n\n";
43
44    // 返された整数値が DOM_DOCUMENT_POSITION_PRECEDING 定数を含んでいるかを確認します。
45    // ビット論理積演算子 (&) を使用して、特定の値(ビットフラグ)がセットされているかをチェックします。
46    if (($positionResult & DOM_DOCUMENT_POSITION_PRECEDING) === DOM_DOCUMENT_POSITION_PRECEDING) {
47        echo "結果: h1 ノードは p ノードよりもドキュメント内で先行しています。\n";
48        echo "  (結果には DOM_DOCUMENT_POSITION_PRECEDING 定数が含まれています。)\n";
49    } else {
50        echo "結果: h1 ノードは p ノードよりもドキュメント内で先行していません。\n";
51    }
52
53    // 参考として、リファレンス情報にあった DOM_DOCUMENT_POSITION_CONTAINED_BY 定数も確認します。
54    // この定数は、呼び出し元のノード($p)が引数のノード($h1)に「含まれている」場合にセットされます。
55    // 今回の例ではそのような関係ではないため、この条件は偽となります。
56    if (($positionResult & DOM_DOCUMENT_POSITION_CONTAINED_BY) === DOM_DOCUMENT_POSITION_CONTAINED_BY) {
57        echo "参考: p ノードは h1 ノードに含まれています。(DOM_DOCUMENT_POSITION_CONTAINED_BY)\n";
58    } else {
59        echo "参考: p ノードは h1 ノードに含まれていません。(DOM_DOCUMENT_POSITION_CONTAINED_BY)\n";
60    }
61}
62
63// 定義した関数を実行し、ノード位置比較のデモンストレーションを開始します。
64demonstrateNodePositionComparison();

PHPのDOM操作では、HTMLやXMLドキュメント内のノード(要素やテキストなど)間の位置関係を比較できます。DOMNode::compareDocumentPosition()メソッドは、呼び出し元のノードと引数のノードの相対的な位置を示す整数値を返します。この戻り値は、様々な位置関係を示す定数(ビットフラグ)の組み合わせとして表現されます。

DOM_DOCUMENT_POSITION_PRECEDING定数は、引数で指定されたノードが、呼び出し元のノードよりもドキュメント内で「先行している」(前にある)場合に、戻り値の整数値に含まれます。サンプルコードでは、<p>ノードから見て<h1>ノードが先行しているかを確認しています。<h1>はドキュメント上で<p>の前に位置するため、比較結果にこの定数が含まれ、「h1ノードはpノードよりも先行しています」と出力されます。

リファレンス情報にあったDOM_DOCUMENT_POSITION_CONTAINED_BY定数は、引数のノードが呼び出し元のノードに「含まれている」(子孫である)場合に、戻り値の整数値に含まれるものです。今回の例ではそのような包含関係がないため、この定数は結果に含まれません。これらの定数を用いることで、DOMツリー内のノードの相対的な位置を正確に判断し、条件に応じた処理を実行できます。

このコードでは、DOMノード間の位置関係を比較するcompareDocumentPositionメソッドとその結果の解釈が重要です。このメソッドは、単一の真偽値ではなく、複数の位置関係を示す「ビットフラグ」の組み合わせを整数値で返します。そのため、特定の位置関係(例えばDOM_DOCUMENT_POSITION_PRECEDING)が含まれているかを確認するには、ビット論理積演算子&を使って、結果と定数値を比較し、その結果が定数自身と一致するかを判定する必要があります。DOM_DOCUMENT_POSITION_PRECEDINGは比較対象ノードが基準ノードよりドキュメント内で先行していることを、DOM_DOCUMENT_POSITION_CONTAINED_BYは基準ノードが比較対象ノードに含まれていることをそれぞれ示します。これらの定数を正しく理解し、ビット演算を適切に用いることで、複雑なDOMツリー内でのノードの相対的な位置を正確に判断できるようになります。

DOMノードの包含関係を調べる

1<?php
2
3/**
4 * DOMノードの位置関係を比較する例。
5 *
6 * DOMNode::compareDocumentPosition() メソッドと、関連するDOMNode定数
7 * (特に DOMNode::DOCUMENT_POSITION_CONTAINED_BY と DOMNode::DOCUMENT_POSITION_CONTAINS)
8 * の使用方法を、システムエンジニアを目指す初心者向けに示します。
9 *
10 * compareDocumentPosition() メソッドは、現在のノードと引数で指定されたノードとの位置関係を
11 * ビットマスクで返します。このビットマスクを特定のDOMNode定数とビット論理積 (&) で比較することで、
12 * 特定の関係性を判別できます。
13 */
14function demonstrateDomPositionComparison(): void
15{
16    // 新しいDOMドキュメントを作成し、簡単なHTML構造をロードします。
17    // '@' を使用して、loadHTML()がHTML5解析に関する警告を出すのを抑制しています。
18    // 実際のアプリケーションでは、エラーハンドリングを適切に行うべきです。
19    $dom = new DOMDocument();
20    @$dom->loadHTML('<div id="parent"><span id="child">Hello</span> World!</div>');
21
22    // 比較対象となるノードをHTMLから取得します。
23    // getElementById() は PHP 8.0 以降で利用可能です。
24    $divNode = $dom->getElementById('parent');    // 親ノード (<div>)
25    $spanNode = $dom->getElementById('child');     // 子ノード (<span>)
26    // テキストノードは子要素として取得します。
27    // 'Hello' は <span> の最初の子ノードです。
28    $textNodeHello = $spanNode ? $spanNode->firstChild : null;
29    // ' World!' は <div> の最後の子ノードです。
30    $textNodeWorld = $divNode ? $divNode->lastChild : null;
31
32    // ノードが正しく取得できたか確認します。
33    if (!$divNode || !$spanNode || !$textNodeHello || !$textNodeWorld) {
34        echo "エラー: 必要なDOMノードの一部が取得できませんでした。\n";
35        echo "HTML構造またはgetElementById()の利用を確認してください。\n";
36        return;
37    }
38
39    echo "=== DOMノード位置比較のデモンストレーション ===\n\n";
40
41    // --- 比較例 1: 親ノードが子ノードを含んでいるか ---
42    echo "1. div (親) と span (子) の比較:\n";
43    // divNodeがspanNodeに対してどのような位置関係にあるかを比較します。
44    $position1 = $divNode->compareDocumentPosition($spanNode);
45    echo "   divNode->compareDocumentPosition(spanNode) の戻り値 (ビットマスク): " . $position1 . "\n";
46
47    // DOCUMENT_POSITION_CONTAINS は、呼び出し元のノード(divNode)が
48    // 比較対象のノード(spanNode)を含んでいる場合に設定されるビットです。
49    if (($position1 & DOMNode::DOCUMENT_POSITION_CONTAINS) > 0) {
50        echo "   -> 結果: divNode は spanNode を含んでいます。\n";
51    }
52    // DOCUMENT_POSITION_CONTAINED_BY は、呼び出し元のノード(divNode)が
53    // 比較対象のノード(spanNode)に含まれている場合に設定されるビットです。
54    if (($position1 & DOMNode::DOCUMENT_POSITION_CONTAINED_BY) > 0) {
55        echo "   -> 結果: divNode は spanNode に含まれています。(この場合は通常該当しません)\n";
56    }
57    echo "\n";
58
59    // --- 比較例 2: 子ノードが親ノードに含まれているか ---
60    echo "2. span (子) と div (親) の比較:\n";
61    // spanNodeがdivNodeに対してどのような位置関係にあるかを比較します。
62    $position2 = $spanNode->compareDocumentPosition($divNode);
63    echo "   spanNode->compareDocumentPosition(divNode) の戻り値 (ビットマスク): " . $position2 . "\n";
64
65    if (($position2 & DOMNode::DOCUMENT_POSITION_CONTAINS) > 0) {
66        echo "   -> 結果: spanNode は divNode を含んでいます。(この場合は通常該当しません)\n";
67    }
68    if (($position2 & DOMNode::DOCUMENT_POSITION_CONTAINED_BY) > 0) {
69        echo "   -> 結果: spanNode は divNode に含まれています。\n";
70    }
71    echo "\n";
72
73    // --- 比較例 3: 同じノードの比較 ---
74    echo "3. div (親) と div (親) の比較:\n";
75    // 同じノード同士を比較すると0が返されます。これはどの位置関係ビットも設定されていない状態です。
76    $position3 = $divNode->compareDocumentPosition($divNode);
77    echo "   divNode->compareDocumentPosition(divNode) の戻り値 (ビットマスク): " . $position3 . "\n";
78
79    if ($position3 === 0) {
80        echo "   -> 結果: 両方のノードは同じです。\n";
81    } else {
82        echo "   -> 結果: 両方のノードは異なります。\n";
83    }
84    echo "\n";
85
86    // --- 比較例 4: 要素ノードとテキストノードの包含関係 ---
87    echo "4. span (要素ノード) と 'Hello' (テキストノード) の比較:\n";
88    $position4 = $spanNode->compareDocumentPosition($textNodeHello);
89    echo "   spanNode->compareDocumentPosition(textNodeHello) の戻り値 (ビットマスク): " . $position4 . "\n";
90
91    if (($position4 & DOMNode::DOCUMENT_POSITION_CONTAINS) > 0) {
92        echo "   -> 結果: spanNode は 'Hello' テキストノードを含んでいます。\n";
93    }
94    if (($position4 & DOMNode::DOCUMENT_POSITION_CONTAINED_BY) > 0) {
95        echo "   -> 結果: spanNode は 'Hello' テキストノードに含まれています。(この場合は通常該当しません)\n";
96    }
97    echo "\n";
98
99    // --- 比較例 5: 異なる親を持つテキストノード間の比較 (包含関係ではない) ---
100    echo "5. 'Hello' (spanの子) と ' World!' (divの子) の比較:\n";
101    // これらは兄弟関係でも親子関係でもないため、包含関係は成立しません。
102    // 代わりに、DOMツリー上での前後関係 (PRECEDING/FOLLOWING) が示されます。
103    $position5 = $textNodeHello->compareDocumentPosition($textNodeWorld);
104    echo "   textNodeHello->compareDocumentPosition(textNodeWorld) の戻り値 (ビットマスク): " . $position5 . "\n";
105
106    if (($position5 & DOMNode::DOCUMENT_POSITION_CONTAINS) > 0) {
107        echo "   -> 結果: 'Hello' は ' World!' を含んでいます。(この場合は該当しません)\n";
108    }
109    if (($position5 & DOMNode::DOCUMENT_POSITION_CONTAINED_BY) > 0) {
110        echo "   -> 結果: 'Hello' は ' World!' に含まれています。(この場合は該当しません)\n";
111    }
112    if (($position5 & DOMNode::DOCUMENT_POSITION_PRECEDING) > 0) {
113        echo "   -> 結果: 'Hello' は ' World!' のDOMツリー上で前に位置します。\n";
114    }
115    if (($position5 & DOMNode::DOCUMENT_POSITION_FOLLOWING) > 0) {
116        echo "   -> 結果: 'Hello' は ' World!' のDOMツリー上で後に位置します。\n";
117    }
118    echo "\n";
119}
120
121// デモンストレーション関数を実行します。
122demonstrateDomPositionComparison();
123

このサンプルコードは、PHPのDOM拡張機能において、DOMツリー内のノード間の位置関係を比較する方法を示しています。具体的には、DOMNode::compareDocumentPosition()メソッドと、その結果を解釈するための定数DOMNode::DOCUMENT_POSITION_CONTAINED_BYDOMNode::DOCUMENT_POSITION_CONTAINSが利用されます。

DOMNode::DOCUMENT_POSITION_CONTAINED_BYは、比較対象のノードが基準となるノードに「含まれている」状態を示す整数値(ビット)です。同様にDOMNode::DOCUMENT_POSITION_CONTAINSは、基準となるノードが比較対象のノードを「含んでいる」状態を示すビットを表します。これらの定数自体に引数はなく、内部的に整数値を保持しています。

DOMNode::compareDocumentPosition()メソッドは、呼び出し元のノードと引数で渡されたノードとの位置関係を、複数の状態を同時に表現できるビットマスク(整数値)として返します。

サンプルコードでは、このビットマスクをDOMNode::DOCUMENT_POSITION_CONTAINSDOMNode::DOCUMENT_POSITION_CONTAINED_BYといった定数とビット論理積(&)で比較することで、ノードが他のノードに含まれているか、あるいは含んでいるかといった具体的な関係性を判別しています。親子関係にあるノードや、要素ノードとテキストノードなど、様々な組み合わせで比較が行われ、DOMツリー上でのノードの位置関係をプログラムで正確に把握し、条件に応じた処理を行うための基礎が学べます。

DOMNode::compareDocumentPosition() メソッドの戻り値は、複数の状態を示すビットマスクという数値です。特定の位置関係を確認するには、このビットマスクを目的の定数(例: DOMNode::DOCUMENT_POSITION_CONTAINED_BY)とビット論理積演算子「&」で比較し、結果が0より大きければ該当します。DOCUMENT_POSITION_CONTAINSは呼び出し元が比較対象を含み、DOCUMENT_POSITION_CONTAINED_BYは含まれる関係を表します。ノードの取得に使う getElementById() はPHP 8.0以降で利用可能です。サンプルコードの「@」によるエラー抑制はデバッグを難しくするため、本番環境では適切なエラー処理を実装しましょう。要素ノードだけでなく、テキストノードもDOMノードとして位置比較の対象となることを理解しておきましょう。

関連コンテンツ

関連IT用語

関連プログラミング言語