【PHP8.x】DOMDocument::isEqualNode()メソッドの使い方
isEqualNodeメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
isEqualNodeメソッドは、現在のDOMノードと、指定された別のDOMノードが同じであるかどうかを比較し、その結果を判定するメソッドです。このメソッドは、2つのノードが同じ種類(例えば、両方とも要素ノードやテキストノードなど)であり、かつ、それらの名前、値、属性、そして子ノードの構造と内容がすべて等しい場合にtrueを返します。
重要な点として、これらのノードがDOM文書ツリー内でどこに位置しているか、つまり親ノードや兄弟ノードとの関係は比較の対象外となります。そのため、たとえ異なる場所に存在しても、構造と内容が同一であれば等しいと判断されます。
本メソッドは、DOMDocumentクラスのインスタンスを含む、DOMNodeクラスを継承するすべてのノードオブジェクトで利用可能です。例えば、DOM文書内で特定の構造を持つノードを検索したり、XMLやHTMLの断片が内容的に同じであるかを検証したりする際に特に役立ちます。
比較の結果、両ノードが等しいと判断された場合は論理値trueを、そうでない場合はfalseを返します。これにより、プログラムでDOM構造を扱う際に、ノードの同一性を効率的に確認し、複雑な条件分岐やロジックの実装を簡素化することができます。
構文(syntax)
1<?php 2 3$domDocument1 = new DOMDocument(); 4$domDocument1->loadXML('<root><element id="1">Text1</element></root>'); 5 6$domDocument2 = new DOMDocument(); 7$domDocument2->loadXML('<root><element id="2">Text2</element></root>'); 8 9// 構文: DOMDocument インスタンス -> isEqualNode(DOMNode のインスタンス) 10$areNodesEqual = $domDocument1->isEqualNode($domDocument2); 11 12?>
引数(parameters)
?DOMNode $otherNode
- ?DOMNode $otherNode: 比較対象のDOMNodeオブジェクト
戻り値(return)
bool
このメソッドは、指定されたノードと現在のノードが等しいかどうかを示す真偽値(bool)を返します。trueであれば等しく、falseであれば等しくありません。
サンプルコード
PHP DOMノード比較 isEqualNode で一致を判定する
1<?php 2 3declare(strict_types=1); 4 5/** 6 * 2つのHTML文字列からDOMノードを構築し、それらを比較して一致しない場合に「エラー」として報告します。 7 * DOMNode::isEqualNode メソッド(DOMDocumentクラスのインスタンスからも呼び出し可能)の基本的な使用方法を示します。 8 * システムエンジニアを目指す初心者向けに、ノードの比較とその結果の解釈を簡潔に示します。 9 * 10 * @param string $htmlA 比較する最初のHTML文字列 11 * @param string $htmlB 比較する2番目のHTML文字列 12 * @return void 13 */ 14function compareHtmlNodesForEquality(string $htmlA, string $htmlB): void 15{ 16 echo "--- DOM ノード比較 ---" . PHP_EOL; 17 // 比較対象のHTMLの一部を表示し、分かりやすくします。 18 echo "HTML A (開始): " . substr($htmlA, 0, 40) . "..." . PHP_EOL; 19 echo "HTML B (開始): " . substr($htmlB, 0, 40) . "..." . PHP_EOL; 20 21 // 最初のDOMDocumentオブジェクトを作成 22 $domA = new DOMDocument(); 23 // HTML文字列をDOMDocumentにロードします。 24 // loadHTMLはHTMLのパースエラーを発生させることがあるため、@で抑制していますが、 25 // 実際のアプリケーションではtry-catchブロックなど適切なエラーハンドリングを推奨します。 26 @$domA->loadHTML($htmlA); 27 // DOMツリーを正規化し、空白文字などの違いによる厳密な比較を可能にします(オプション)。 28 $domA->normalizeDocument(); 29 30 // 2番目のDOMDocumentオブジェクトを作成し、同様に処理します。 31 $domB = new DOMDocument(); 32 @$domB->loadHTML($htmlB); 33 $domB->normalizeDocument(); 34 35 // 比較対象のノードを選択します。 36 // ここではHTMLドキュメントのルート要素(通常は <html> タグ)を取得しています。 37 $nodeA = $domA->documentElement; 38 $nodeB = $domB->documentElement; 39 40 // ルート要素が取得できなかった場合のチェック。不完全なHTMLの場合に発生することがあります。 41 if ($nodeA === null || $nodeB === null) { 42 echo "比較エラー: どちらかのHTMLからルート要素(<html>)が見つかりませんでした。比較できません。" . PHP_EOL; 43 echo PHP_EOL; 44 return; 45 } 46 47 // DOMNode::isEqualNode() メソッドを使って2つのノードを比較します。 48 // このメソッドは、ノードの型、名前、値、属性、および子ノードが同じであるかを再帰的に判断します。 49 if ($nodeA->isEqualNode($nodeB)) { 50 echo "結果: 2つのHTMLノードは完全に一致します。" . PHP_EOL; 51 } else { 52 // ノードが一致しない場合、これを「期待と異なる状態」、つまり広義の「エラー」として扱います。 53 echo "結果: 2つのHTMLノードは一致しません。これは予期せぬ不一致(広義のエラー)です。" . PHP_EOL; 54 } 55 echo PHP_EOL; 56} 57 58// --- サンプルコードの使用例 --- 59 60// ケース1: 完全に一致するHTMLノードの比較 61$html1 = '<html><head><title>Page</title></head><body><h1>Hello</h1><p>World</p></body></html>'; 62$html2 = '<html><head><title>Page</title></head><body><h1>Hello</h1><p>World</p></body></html>'; 63compareHtmlNodesForEquality($html1, $html2); 64 65// ケース2: コンテンツが異なるHTMLノードの比較(一致しない例) 66$html3 = '<html><body><p>PHP is great!</p></body></html>'; 67$html4 = '<html><body><p>PHP is good!</p></body></html>'; // pタグの内容が異なる 68compareHtmlNodesForEquality($html3, $html4); 69 70// ケース3: 属性が異なるHTMLノードの比較(一致しない例) 71$html5 = '<html><body><div id="main">Content</div></body></html>'; 72$html6 = '<html><body><div>Content</div></body></html>'; // divタグにid属性がない 73compareHtmlNodesForEquality($html5, $html6); 74 75// ケース4: タグ名が異なるHTMLノードの比較(一致しない例) 76$html7 = '<html><body><section>Area</section></body></html>'; 77$html8 = '<html><body><div>Area</div></body></html>'; // sectionタグとdivタグで異なる 78compareHtmlNodesForEquality($html7, $html8); 79 80// ケース5: 不完全なHTMLでルート要素が取得できない場合 81// この場合、比較するノードが取得できないため、エラーとして報告されます。 82$html9 = '<h1>Only a header</h1>'; // <html>要素がない 83$html10 = '<h1>Another header</h1>'; 84compareHtmlNodesForEquality($html9, $html10);
PHPのDOMNode::isEqualNodeメソッドは、二つのDOMノードが構造的に完全に等しいかどうかを比較するために利用されます。このメソッドは、DOMDocumentオブジェクトのdocumentElementプロパティなどで取得したDOMNodeインスタンスから呼び出すことが可能です。引数として比較対象となる別のDOMNodeオブジェクトを受け取り、ノードの型、名前、値、属性、そして子ノードまでが再帰的にすべて一致した場合にtrueを、一つでも異なる場合はfalseを戻り値として返します。
サンプルコードでは、まず二つのHTML文字列をDOMDocumentクラスに読み込み、それぞれをDOMツリーとして構築しています。次にnormalizeDocumentメソッドでノードを正規化し、HTMLドキュメントのルートノード(<html>タグ)をdocumentElementプロパティから取得します。これらの取得した二つのノードをisEqualNodeメソッドで比較し、その結果を出力しています。メソッドがfalseを返した場合、ノードが一致しないことを意味し、このサンプルではこれを「予期せぬ不一致」、つまり広義の「エラー」として扱って報告しています。ノードの属性値やテキストコンテンツ、含まれるタグなどがわずかでも異なれば不一致と判断されるため、期待通りのDOM構造が維持されているか確認する際に非常に有用な機能です。
このサンプルコードでは、HTMLのパースエラーを@で抑制していますが、実際のシステム開発ではtry-catchなどを用いた適切なエラーハンドリングが必須です。isEqualNodeメソッドはノードの型、名前、値、属性、子ノードまで再帰的に厳密な構造的同一性を比較します。そのため、結果がfalseの場合、それは「期待される構造と異なる」状態であり、広義の「エラー」として扱えることを理解してください。比較前にnormalizeDocument()を呼び出すことで、空白文字などの違いを吸収し、比較の精度を高めることができますが、この振る舞いを考慮して利用してください。また、比較対象のノードがnullでないことを事前に確認することも重要です。
PHP DOMDocument::isEqualNodeでノード比較とisset
1<?php 2 3/** 4 * DOMDocument::isEqualNode の使用例を示します。 5 * このメソッドは、2つのDOMノードが内容、構造、属性において等しいかどうかを比較します。 6 * PHPの isset を利用して、比較対象のノードが存在するかどうかを安全にチェックする方法も示します。 7 */ 8function demonstrateIsEqualNode(): void 9{ 10 // 比較対象となるDOMDocumentオブジェクトを複数作成 11 // DOMDocumentはHTML文字列をパースしてDOMツリーを構築します。 12 $dom1 = new DOMDocument(); 13 $dom1->loadHTML('<div><p>Hello</p></div>'); 14 15 $dom2 = new DOMDocument(); 16 $dom2->loadHTML('<div><p>Hello</p></div>'); // dom1 と同じ内容 17 18 $dom3 = new DOMDocument(); 19 $dom3->loadHTML('<div><p>World</p></div>'); // dom1 と内容が異なる 20 21 $dom4 = new DOMDocument(); 22 $dom4->loadHTML('<span><p>Hello</p></span>'); // dom1 とルート要素のタグが異なる 23 24 // DOMDocument オブジェクト自体の比較 25 echo "--- DOMDocument オブジェクト自体の比較 ---" . PHP_EOL; 26 27 // $dom1 と $dom2 は、ドキュメントツリー全体の内容が同じであるため、isEqualNode は true を返します。 28 if ($dom1->isEqualNode($dom2)) { 29 echo "\$dom1 と \$dom2 は等しいです (true)." . PHP_EOL; 30 } else { 31 echo "\$dom1 と \$dom2 は等しくありません (false)." . PHP_EOL; 32 } 33 34 // $dom1 と $dom3 は、ドキュメントツリー全体の内容が異なるため、isEqualNode は false を返します。 35 if ($dom1->isEqualNode($dom3)) { 36 echo "\$dom1 と \$dom3 は等しいです (true)." . PHP_EOL; 37 } else { 38 echo "\$dom1 と \$dom3 は等しくありません (false)." . PHP_EOL; 39 } 40 41 echo PHP_EOL . "--- HTML要素ノードの比較 (DOMDocument::getElementsByTagName と isset の併用) ---" . PHP_EOL; 42 43 // DOMDocument::getElementsByTagName は DOMNodeList を返し、 44 // item(0) でリストの最初の要素を取得します。 45 // item(0) は該当する要素がない場合、null を返す可能性があるため、isset で存在チェックするのが安全です。 46 $node1 = $dom1->getElementsByTagName('div')->item(0); // <div><p>Hello</p></div> 47 $node2 = $dom2->getElementsByTagName('div')->item(0); // <div><p>Hello</p></div> 48 $node3 = $dom3->getElementsByTagName('div')->item(0); // <div><p>World</p></div> 49 $node4 = $dom4->getElementsByTagName('span')->item(0); // <span><p>Hello</p></span> 50 51 // 存在しないノードの例 (getElementsByTagName('img') は null を返す) 52 $nonExistentNode = $dom1->getElementsByTagName('img')->item(0); 53 54 // case 1: 内容も構造も同じノードの比較 55 // isset($node1) と isset($node2) は両方 true なので、isEqualNode が呼び出されます。 56 if (isset($node1) && isset($node2) && $node1->isEqualNode($node2)) { 57 echo "node1 と node2 (同じ 'div<p>Hello</p>') は等しいです (true)." . PHP_EOL; 58 } else { 59 echo "node1 と node2 (同じ 'div<p>Hello</p>') は等しくありません (false)." . PHP_EOL; 60 } 61 62 // case 2: 内容が異なるノードの比較 63 if (isset($node1) && isset($node3) && $node1->isEqualNode($node3)) { 64 echo "node1 と node3 (異なる内容 'div<p>World</p>') は等しいです (true)." . PHP_EOL; 65 } else { 66 echo "node1 と node3 (異なる内容 'div<p>World</p>') は等しくありません (false)." . PHP_EOL; 67 } 68 69 // case 3: タグ名(構造)が異なるノードの比較 70 if (isset($node1) && isset($node4) && $node1->isEqualNode($node4)) { 71 echo "node1 と node4 (異なるタグ 'span<p>Hello</p>') は等しいです (true)." . PHP_EOL; 72 } else { 73 echo "node1 と node4 (異なるタグ 'span<p>Hello</p>') は等しくありません (false)." . PHP_EOL; 74 } 75 76 echo PHP_EOL . "--- null または存在しないノードとの比較 (isset の重要性) ---" . PHP_EOL; 77 78 // case 4: 存在するノードと存在しないノード (null) の比較 79 // isEqualNode の引数は ?DOMNode であり null を許容しますが、null とは等しいと見なされません。 80 // isset($nonExistentNode) が false となるため、最初の条件式は false となります。 81 if (isset($node1) && isset($nonExistentNode) && $node1->isEqualNode($nonExistentNode)) { 82 echo "node1 と nonExistentNode (null) は等しいです (true)." . PHP_EOL; 83 } else { 84 echo "node1 と nonExistentNode (null) は等しくありません (false)." . PHP_EOL; 85 } 86 87 // isset を使わずに直接比較した場合 88 // $nonExistentNode が null の場合、isEqualNode は false を返します。 89 // $node1 は存在するため、$node1->isEqualNode($nonExistentNode) は実行され false を返します。 90 if (isset($node1) && $node1->isEqualNode($nonExistentNode)) { 91 echo "node1 と nonExistentNode (null) は等しいです (true) (isset 無し)." . PHP_EOL; 92 } else { 93 echo "node1 と nonExistentNode (null) は等しくありません (false) (isset 無し)." . PHP_EOL; 94 } 95 96 echo PHP_EOL . "--- isset の役割 (まとめ) ---" . PHP_EOL; 97 // 変数がセットされており、かつ null ではない場合に true を返します。 98 echo "isset(\$node1): " . (isset($node1) ? 'true' : 'false') . PHP_EOL; // true 99 echo "isset(\$nonExistentNode): " . (isset($nonExistentNode) ? 'true' : 'false') . PHP_EOL; // false 100 101 echo PHP_EOL . "DOM操作において、getElementsByTagName()->item(0) のようにノード取得メソッドが" . PHP_EOL; 102 echo "null を返す可能性があるため、isset を使った存在チェックは予期せぬエラーを防ぎ、" . PHP_EOL; 103 echo "堅牢なコードを書く上で非常に重要です。" . PHP_EOL; 104} 105 106// 関数の実行 107demonstrateIsEqualNode();
PHP 8 の DOMDocument::isEqualNode メソッドは、2つのDOMノードが内容、構造、属性において等しいかどうかを比較するために使用されます。このメソッドは、比較対象となる別の DOMNode オブジェクトを引数 ?DOMNode $otherNode に受け取り、両者が等しければ true、等しくなければ false を真偽値として返します。引数が示す通り null も許容しますが、null ノードは他のノードとは等しいとは見なされません。
サンプルコードでは、HTML文字列から生成された DOMDocument オブジェクト全体や、その中から取得した特定のHTML要素ノードの比較例を示しています。例えば、ルート要素から子要素まですべて同じ構造と内容を持つドキュメントやノードの場合、isEqualNode は true を返しますが、テキスト内容やタグ名が異なる場合は false となります。
特に重要なのは、DOMDocument::getElementsByTagName()->item(0) のようにノードを取得する際に、対象の要素が存在しない場合に null が返される可能性がある点です。このような状況で安全にコードを実行するため、PHPの isset() 関数を用いた事前のチェックが不可欠です。isset() は、変数がセットされており、かつ null でないことを確認し、ノードが確実に存在する場合にのみ isEqualNode メソッドを呼び出すことで、実行時エラーを防ぎます。これは、DOM操作における堅牢なプログラミングの基礎となります。
DOMDocument::isEqualNodeメソッドは、二つのDOMノードの内容、構造、属性が完全に等しいかを比較します。getElementsByTagName()->item(0)のようにDOM要素を取得する際、該当する要素が存在しない場合はnullが返されることがあります。isEqualNodeの引数はnullを許容する型ですが、nullのノードは他のノードと等しいとは見なされません。そのため、比較を行う前に、isset()関数を使用して比較対象のノードが実際に存在し、かつnullではないことを確認することが非常に重要です。この事前チェックを行うことで、予期せぬエラーを防ぎ、より堅牢で安全なコードを作成することができます。