【PHP8.x】Dom\HTMLDocument::importNode()メソッドの使い方
importNodeメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
importNodeメソッドは、指定されたノードを別のドキュメントから現在のドキュメントへインポートするメソッドです。
このメソッドは、XMLやHTMLのドキュメントオブジェクトモデル(DOM)を操作する際に非常に重要で、異なるドキュメントに属するノードを、現在作業しているドキュメントのコンテキストで利用できるようにするために使用されます。具体的には、引数として渡されたノード(要素、テキスト、コメントなど)のクローンを作成し、そのクローンを現在のドキュメントに属するものとして返します。元のドキュメント内の元のノードは、変更されることなくそのまま残ります。
importNodeメソッドには、第二引数として$deepというブール値を指定できます。この$deepにtrueを設定した場合、インポート対象のノードだけでなく、そのノードのすべての子孫ノード(子要素やそのさらに子要素など)も再帰的にインポートされ、新しいドキュメントのコンテキストに適合するようクローンされます。一方、$deepにfalseを設定すると、インポート対象のノードのみがインポートされ、その子孫ノードは含まれません。
この機能は、例えば、テンプレートとして作成された別のHTMLドキュメントから特定のセクションや要素を取り出し、現在のHTMLドキュメントに組み込む際などに非常に役立ちます。これにより、異なるドキュメント構造を持つデータを効率的に統合・利用することが可能になります。
構文(syntax)
1<?php 2 3$targetDocument = new Dom\HTMLDocument(); // ノードをインポートする先のHTMLドキュメント 4$sourceDocument = new Dom\HTMLDocument(); // インポート元となるノードを含むHTMLドキュメント 5$sourceDocument->loadHTML('<div><p>インポートするノード</p></div>'); 6 7$nodeToImport = $sourceDocument->getElementsByTagName('p')->item(0); // インポートしたいDom\Nodeオブジェクト 8$deep = true; // ノードの子孫も再帰的にインポートするか (true:する, false:しない) 9 10// Dom\HTMLDocument::importNode メソッドの構文 11$importedNode = $targetDocument->importNode($nodeToImport, $deep); 12 13?>
引数(parameters)
Dom\Node $node, bool $deep = false
- Dom\Node $node: インポートしたいDOMノード
- bool $deep = false: trueの場合、指定したノードの子孫ノードもすべてインポートします。デフォルトはfalseで、ノード自身のみをインポートします。
戻り値(return)
Dom\Node
指定されたDOM (Document Object Model) のノードを、現在のHTMLドキュメントのコンテキストでインポートした新しいノードを返します。この新しいノードは、元のノードの構造と内容を保持していますが、DOMツリー内での配置は異なります。
サンプルコード
PHP DomDocument importNodeでノードをインポートする
1<?php 2 3/** 4 * Dom\HTMLDocument::importNode メソッドの使用例を示します。 5 * この関数は、あるHTMLドキュメントからノードをインポートし、別のHTMLドキュメントに追加する方法をデモンストレーションします。 6 * システムエンジニアを目指す初心者の方にも分かりやすいように、コメントで各ステップを説明しています。 7 */ 8function demonstrateImportNode(): void 9{ 10 // 1. インポート先の新しいHTMLドキュメントを作成します。 11 // Dom\HTMLDocumentはPHP 8で導入された、HTML専用のDOM操作クラスです。 12 $targetDoc = new Dom\HTMLDocument(); 13 // 基本的なHTML構造を読み込みます。 14 $targetDoc->loadHTML('<!DOCTYPE html><html><head><title>ターゲットドキュメント</title></head><body><h1>元のコンテンツ</h1></body></html>'); 15 16 // 2. インポート元のHTMLコンテンツを準備します。 17 // この文字列から、特定のノードをインポートします。 18 $sourceHtml = '<div id="sourceContent"> 19 <p>これはインポート元のドキュメントからの段落です。</p> 20 <ul> 21 <li>リストアイテム1</li> 22 <li>リストアイテム2</li> 23 </ul> 24 </div>'; 25 26 // 3. インポート元となるドキュメントオブジェクトを作成し、コンテンツを読み込みます。 27 $sourceDoc = new Dom\HTMLDocument(); 28 $sourceDoc->loadHTML($sourceHtml); 29 30 // 4. インポートしたいノードをインポート元ドキュメントから選択します。 31 // ここでは、IDが "sourceContent" のdiv要素を選択しています。 32 $nodeToImport = $sourceDoc->getElementById('sourceContent'); 33 34 if ($nodeToImport) { 35 // 5. 選択したノードをターゲットドキュメントにインポートします。 36 // importNodeメソッドの第二引数 `$deep` を `true` にすると、 37 // ノード自体だけでなく、その子ノード(子孫すべて)も再帰的にインポートされます。 38 $importedNode = $targetDoc->importNode($nodeToImport, true); 39 40 // 6. インポートされたノードをターゲットドキュメントの特定の位置(ここでは<body>要素内)に追加します。 41 // まず、ターゲットドキュメントの<body>要素を取得します。 42 $body = $targetDoc->getElementsByTagName('body')->item(0); 43 44 if ($body) { 45 // <body>要素にインポートしたノードを追加します。 46 $body->appendChild($importedNode); 47 } else { 48 echo "エラー: ターゲットドキュメントの<body>要素が見つかりませんでした。\n"; 49 } 50 51 // 7. 変更後のターゲットドキュメントのHTMLコンテンツを出力して確認します。 52 echo "--- ターゲットドキュメント(インポート後)---\n"; 53 // saveHTML() はドキュメント全体のHTMLを文字列として返します。 54 // HTMLエンティティに変換して<pre>タグで囲むことで、ブラウザで整形されて表示されにくく、 55 // ソースコードのように見やすく出力できます。 56 echo '<pre>' . htmlentities($targetDoc->saveHTML()) . '</pre>'; 57 } else { 58 echo "エラー: インポート元ドキュメントから 'sourceContent' ノードが見つかりませんでした。\n"; 59 } 60} 61 62// 関数を実行してデモンストレーションを開始します。 63demonstrateImportNode(); 64 65?>
PHP 8で導入されたDom\HTMLDocument::importNodeメソッドは、あるHTMLドキュメントから特定のHTML要素(ノード)をコピーして、別のHTMLドキュメントに追加するために使用されます。Dom\HTMLDocumentはHTML専用のDOM操作クラスです。
このメソッドは、所属クラスであるDom\HTMLDocumentのインスタンスから呼び出されます。引数として、インポートしたい元のDom\Nodeオブジェクトを一つ目に指定します。二つ目の引数$deepはオプションの真偽値で、trueを設定すると、ノード自体だけでなくその子ノード(子孫要素すべて)もまとめて再帰的にインポートされます。このメソッドの戻り値は、インポート先のドキュメントに属する新しいDom\Nodeオブジェクトです。元のドキュメントのノードは削除されず、新しいコピーが作成されます。
サンプルコードでは、まずインポート先の「ターゲットドキュメント」と、インポート元のHTMLコンテンツを持つ「ソースドキュメント」の二つのDom\HTMLDocumentインスタンスを用意しています。ソースドキュメントからgetElementByIdで特定のdiv要素を選択し、これをインポート対象とします。
次に、$targetDoc->importNode($nodeToImport, true)を呼び出します。ここでtrueを指定しているため、div要素とその内部にある<p>や<ul>、<li>といったすべての子孫要素が、ターゲットドキュメントにコピーされます。この操作によって得られた新しいノードはimportedNodeとして受け取られます。
最後に、ターゲットドキュメントの<body>要素を取得し、appendChildメソッドを使ってimportedNodeをその末尾に追加します。これにより、ソースドキュメントの特定のコンテンツがターゲットドキュメントに統合されます。最終的なHTML内容はsaveHTML()で出力され、インポートが成功したことを確認できます。この機能は、複数のHTMLコンテンツを動的に組み合わせるシナリオで大変有用です。
PHP 8で導入されたDom\HTMLDocumentクラスは、HTML専用のDOM操作をより扱いやすくします。importNodeメソッドを使用する際は、第二引数の$deepにtrueを指定しないと、インポート元ノードの内部コンテンツ(子ノードやテキスト)はコピーされません。そのため、通常はtrueを指定することが多いでしょう。また、importNodeでノードをインポートしただけではターゲットドキュメントには追加されませんので、appendChildなどのメソッドで適切な位置に配置してください。getElementByIdなどで取得したノードは、存在しない場合にnullを返すことがありますので、必ず操作前にnullチェックを行いエラーを防ぐことが大切です。
PHP Dom\HTMLDocument::importNode でノードをインポートする
1<?php 2 3/** 4 * Dom\HTMLDocument::importNode の使用例を示します。 5 * あるHTMLドキュメントから別のドキュメントへ、特定の要素(ノード)をコピーします。 6 */ 7function domImportNodeExample(): void 8{ 9 // 1. コピー元となるソースHTMLを定義します。 10 $sourceHtml = <<<HTML 11<!DOCTYPE html> 12<html> 13<body> 14 <div id="source-content"> 15 <p>これはコピー元の段落です。<strong>太字</strong>の部分も含まれます。</p> 16 </div> 17</body> 18</html> 19HTML; 20 21 // 2. コピー先となるターゲットHTMLを定義します。 22 $targetHtml = <<<HTML 23<!DOCTYPE html> 24<html> 25<body> 26 <h1>ターゲット文書</h1> 27 <div id="target-container"> 28 <!-- ここにソースの要素が追加されます --> 29 </div> 30</body> 31</html> 32HTML; 33 34 // libxmlのエラーを内部で処理するように設定し、HTML5の解釈エラーが画面に出るのを防ぎます。 35 libxml_use_internal_errors(true); 36 37 // 3. ソースとターゲットのドキュメントオブジェクトを作成します。 38 $sourceDoc = new Dom\HTMLDocument(); 39 $sourceDoc->loadHTML($sourceHtml); 40 41 $targetDoc = new Dom\HTMLDocument(); 42 $targetDoc->loadHTML($targetHtml); 43 44 // 4. ソースドキュメントからコピーしたいノード(<p>要素)を取得します。 45 $nodeToCopy = $sourceDoc->getElementsByTagName('p')->item(0); 46 47 // 5. ターゲットドキュメントにソースのノードをインポートします。 48 // 第2引数に `true` を指定すると、子ノード(この場合は<strong>要素)も再帰的にコピーされます(ディープコピー)。 49 // これを行わないと、別のドキュメントのノードを追加しようとしてエラーになります。 50 $importedNode = $targetDoc->importNode($nodeToCopy, true); 51 52 // 6. ターゲットドキュメントの特定の場所(id="target-container"のdiv)にインポートしたノードを追加します。 53 $container = $targetDoc->getElementById('target-container'); 54 if ($container) { 55 $container->appendChild($importedNode); 56 } 57 58 // 7. 結果として得られたターゲットドキュメントのHTMLを出力します。 59 echo $targetDoc->saveHTML(); 60} 61 62// 関数を実行します。 63domImportNodeExample(); 64
PHPのDom\HTMLDocument::importNodeメソッドは、あるHTMLドキュメントから別のHTMLドキュメントへ、特定の要素(ノード)をコピーするために使用します。異なるドキュメントに属するノードを直接追加することはできないため、このメソッドを使って、追加先ドキュメントに所属するノードとして安全に複製する必要があります。
このメソッドの第1引数には、コピーしたい元のノードを指定します。第2引数はオプションで、trueを指定すると、そのノードが持つ子要素や孫要素もすべて再帰的にコピーします(ディープコピー)。falseを指定したり省略したりした場合は、ノード自身のみがコピーされ、その中身は含まれません。メソッドの戻り値として、コピー先ドキュメントに所属する新しいノードの複製が返されます。
サンプルコードでは、まず2つのHTMLドキュメント(コピー元とコピー先)を準備します。次に、コピー元の<p>要素を取得し、importNodeメソッドでコピー先のドキュメント用に複製しています。このとき、第2引数にtrueを指定しているため、<p>要素の中にある<strong>要素も一緒にコピーされます。最後に、importNodeから返された新しいノードを、コピー先ドキュメントの特定の<div>要素に追加しています。
importNodeメソッドは、異なるHTMLドキュメント間で要素を移動させる際に必須の手順です。あるドキュメントから取得した要素(ノード)を、直接別のドキュメントにappendChildなどで追加しようとするとエラーが発生します。このため、まずimportNodeを使って、移動させたい要素をターゲットのドキュメントに所属する新しい要素としてコピーする必要があります。第2引数にtrueを指定することで、要素の中のテキストや子要素も一緒にコピーできます。コピー後は、改めてappendChildなどを用いて、ドキュメント内の任意の位置に追加する、という2段階の操作が必要になる点に注意してください。