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

【PHP8.x】DOMDocument::cloneNode()メソッドの使い方

cloneNodeメソッドの使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

cloneNodeメソッドは、PHPのDOMDocumentクラスに属し、現在のDOMDocumentオブジェクトを複製するメソッドです。DOMDocumentオブジェクトはXMLやHTMLドキュメント全体を表現するためのものであり、このメソッドを使うことで、元のドキュメントの内容を保持したまま、完全に独立した新しいドキュメントオブジェクトを作成できます。これにより、元のドキュメントに影響を与えることなく、複製したドキュメントに対して様々な操作を自由に行うことが可能になります。

このメソッドには、複製方法を制御するためのオプションのブール型引数$deepがあります。$deeptrueに設定した場合、現在のDOMDocumentオブジェクトだけでなく、その配下にあるすべての要素、テキストノード、属性といった子ノードやその子孫ノードもすべて再帰的にコピーされ、元のドキュメントと全く同じ構造を持つドキュメントが生成されます。これは「深いコピー」と呼ばれます。

一方、$deepfalseに設定した場合、DOMDocumentオブジェクト自体は複製されますが、その内部に含まれる子ノードはコピーされません。結果として、空のドキュメント構造を持つ新しいDOMDocumentオブジェクトが作成されます。これは「浅いコピー」と呼ばれ、新しいドキュメント構造を一から構築する基盤として利用できます。

cloneNodeメソッドは、複製された新しいDOMDocumentオブジェクトを戻り値として返します。返されるオブジェクトは元のオブジェクトとは異なるメモリ領域に存在するため、互いに独立して操作できます。例えば、既存のXMLファイルをテンプレートとして読み込み、その構造を複数回再利用して、異なるデータを持つ複数のXMLドキュメントを効率的に生成するシナリオなどで非常に有用です。

構文(syntax)

1<?php
2
3$dom = new DOMDocument();
4$originalElement = $dom->createElement('item');
5$originalElement->appendChild($dom->createTextNode('Data'));
6$dom->appendChild($originalElement);
7
8// originalElement ノードとその子孫を深くクローンする構文
9$clonedElement = $originalElement->cloneNode(true);
10
11?>

引数(parameters)

bool $deep = false

  • bool $deep = false: trueを指定すると、ノードだけでなく、その子ノードすべてが再帰的にコピーされます。falseの場合は、ノードのみがコピーされ、子ノードはコピーされません。

戻り値(return)

DOMNode

このメソッドは、呼び出したDOMNodeオブジェクトのコピーを新しく生成し、そのコピーを返します。

サンプルコード

PHP cloneNodeでノードをコピーする

1<?php
2
3/**
4 * DOMDocument::cloneNode の使用例
5 * ノードをディープコピー(子孫ノードも含む)およびシャローコピー(ノード自身のみ)する方法を示します。
6 */
7
8// DOMDocument インスタンスを作成
9// XMLのバージョンとエンコーディングを指定します。
10$dom = new DOMDocument('1.0', 'UTF-8');
11
12// HTMLコンテンツをロード
13// 実際のWebページやXMLファイルから読み込むこともできますが、ここでは文字列からロードします。
14$html = '
15    <html>
16    <body>
17        <div id="original_container">
18            <p>これはオリジナルの段落です。</p>
19            <span>オリジナルのスパン要素</span>
20        </div>
21    </body>
22    </html>';
23$dom->loadHTML($html);
24
25// オリジナルのコンテナ要素(id="original_container")を取得
26// cloneNodeの対象となるノードを取得します。
27$originalContainer = $dom->getElementById('original_container');
28
29if ($originalContainer) {
30    echo "--- オリジナルノード ---" . PHP_EOL;
31    // saveHTML() を使用して、指定されたノードのHTML表現を取得します。
32    echo $dom->saveHTML($originalContainer) . PHP_EOL . PHP_EOL;
33
34    // --- ディープコピーの例 (子孫ノードも一緒にクローンされる) ---
35    // cloneNode(true) は、ノード自身と全ての子孫ノード(子、孫など)を再帰的にクローンします。
36    // 引数 $deep に true を渡します。
37    $deepClonedContainer = $originalContainer->cloneNode(true);
38    // クローンされたノードを識別しやすくするため、IDを変更します。
39    $deepClonedContainer->setAttribute('id', 'deep_cloned_container');
40
41    echo "--- ディープコピーされたノード (cloneNode(true)) ---" . PHP_EOL;
42    echo $dom->saveHTML($deepClonedContainer) . PHP_EOL . PHP_EOL;
43
44    // --- シャローコピーの例 (ノード自身のみがクローンされる) ---
45    // cloneNode(false) は、ノード自身はクローンしますが、その子孫ノードはクローンしません。
46    // 引数 $deep に false を渡すか、省略します。
47    $shallowClonedContainer = $originalContainer->cloneNode(false);
48    // クローンされたノードを識別しやすくするため、IDを変更します。
49    $shallowClonedContainer->setAttribute('id', 'shallow_cloned_container');
50
51    echo "--- シャローコピーされたノード (cloneNode(false)) ---" . PHP_EOL;
52    echo $dom->saveHTML($shallowClonedContainer) . PHP_EOL . PHP_EOL;
53
54} else {
55    echo "エラー: オリジナルノードが見つかりませんでした。" . PHP_EOL;
56}
57
58?>

PHPのDOMDocument::cloneNodeメソッドは、HTMLやXML文書内の特定の要素(ノード)を複製するために利用されます。これは、ウェブページの内容を動的に操作するDOM(Document Object Model)操作において非常に便利な機能です。

このメソッドはDOMNodeクラスに属し、引数にbool $deepを受け取ります。引数$deeptrueを指定すると、「ディープコピー」が行われます。これは、対象のノード自身だけでなく、そのノードが持っているすべての子孫ノード(子要素、孫要素など)も再帰的に複製します。結果として、元のノードとまったく同じ構造と内容を持つ新しいノードが生成されます。

一方、$deepfalseを指定するか、引数を省略すると、「シャローコピー」が行われます。この場合、ノード自身は複製されますが、その子孫ノードは複製されません。したがって、複製されたノードには、元の子孫ノードは含まれず、属性のみが引き継がれた空のノードが作成されます。

cloneNodeメソッドは、複製された新しいDOMNodeオブジェクトを返します。この新しいノードは、元のノードとは独立しており、DOMツリーのどこにでも追加したり操作したりできます。提示されたサンプルコードでは、original_containerという要素を元に、cloneNode(true)によるディープコピーと、cloneNode(false)によるシャローコピーの挙動が具体的に示されており、それぞれの結果の違いを明確に確認できます。

DOMDocument::cloneNodeは、指定したHTMLやXMLノードを複製し、独立した新しいノードを作成するメソッドです。引数$deeptrueを指定すると、ノードとそのすべての子孫ノードを再帰的に複製する「ディープコピー」になります。false(または省略)では、ノード自身のみを複製し、子孫ノードは含まれない「シャローコピー」となるため、この引数の違いを理解することが最も重要です。クローンされたノードは、元のドキュメントに自動で追加されません。ドキュメントに組み込む場合は、別途appendChildなどのメソッドで追加する必要があります。また、複製されたノードは元のノードと同じ属性(IDなど)を持つため、ドキュメント内でIDが一意である必要がある場合は、クローン後に必ず変更してください。

PHP DOMDocument::cloneNodeでノードをコピーする

1<?php
2
3// DOMDocument クラスを使用してXMLドキュメントを操作します。
4// システムエンジニアにとって、XMLやHTMLの構造を扱う際に非常に重要なクラスです。
5$dom = new DOMDocument('1.0', 'UTF-8');
6$dom->formatOutput = true;         // 出力時にXMLを整形し、読みやすくします。
7$dom->preserveWhiteSpace = false;  // formatOutputが意図通りに機能するように空白文字の扱いを調整します。
8
9// サンプルとなるXML文字列をロードします。
10// ここでは、クローン操作の対象となる要素を含むシンプルなXMLを作成します。
11$xmlString = <<<XML
12<root>
13    <item id="original_item">
14        <subitem>これはオリジナルのサブアイテムです。</subitem>
15        <info>追加情報</info>
16    </item>
17    <container>
18        <!-- クローンされたノードはここに追加されます -->
19    </container>
20</root>
21XML;
22
23$dom->loadXML($xmlString);
24
25// クローンしたい元のノード(XMLの要素)を取得します。
26// getElementById() メソッドは、指定されたIDを持つ要素を検索します。
27$originalItem = $dom->getElementById('original_item');
28
29if ($originalItem) {
30    echo "=== 元のノードをクローンしてドキュメントに追加します ===\n\n";
31
32    // 1. 浅いコピー (引数 $deep を false または省略):
33    // cloneNode(false) は、ノード自身だけをコピーし、子ノード(<subitem>, <info>)はコピーしません。
34    // 結果として、クローンされたノードは空の要素となります。
35    $shallowClonedItem = $originalItem->cloneNode(false);
36    $shallowClonedItem->setAttribute('id', 'shallow_cloned_item');
37    // 浅いコピーなので子ノードはありません。必要であれば新しい子ノードを追加できます。
38    $shallowClonedItem->appendChild($dom->createElement('text_content', '浅いコピーの新しいコンテンツ'));
39
40    // クローンされたノードをドキュメント内の 'container' 要素に追加します。
41    $container = $dom->getElementsByTagName('container')->item(0);
42    if ($container) {
43        $container->appendChild($dom->createTextNode("\n        ")); // 整形のための改行とインデント
44        $container->appendChild($shallowClonedItem);
45    }
46
47    // 2. 深いコピー (引数 $deep を true):
48    // cloneNode(true) は、ノード自身とすべての子ノード(<subitem>, <info>)を再帰的にコピーします。
49    // 結果として、元のノードと全く同じ構造を持つノードが作成されます。
50    $deepClonedItem = $originalItem->cloneNode(true);
51    $deepClonedItem->setAttribute('id', 'deep_cloned_item');
52    // 深いコピーなので、元のノードの子ノードも含まれています。
53    // 例えば、深いコピーのサブアイテムのテキストを変更することも可能です。
54    $deepClonedItem->getElementsByTagName('subitem')->item(0)->nodeValue = '深いコピーのサブアイテム';
55
56    // クローンされたノードをドキュメント内の 'container' 要素に追加します。
57    if ($container) {
58        $container->appendChild($dom->createTextNode("\n        ")); // 整形のための改行とインデント
59        $container->appendChild($deepClonedItem);
60        $container->appendChild($dom->createTextNode("\n    ")); // 整形のための改行とインデント
61    }
62
63    echo "=== クローン後のXMLドキュメントの出力 ===\n";
64    // ドキュメント全体のXML文字列を保存し、出力します。
65    // これにより、クローン操作がどのように反映されたかを確認できます。
66    echo $dom->saveXML();
67
68} else {
69    echo "エラー: 'original_item' IDを持つ要素が見つかりませんでした。\n";
70}
71
72?>

PHPのDOMDocument::cloneNodeメソッドは、XMLやHTMLドキュメント内で既存のノード(要素やテキストなど)を複製するために利用されます。これは、同じ構造の要素を繰り返し作成する場合や、既存の要素をテンプレートとして利用したい場合に非常に便利な機能です。

このメソッドの引数$deepには真偽値(trueまたはfalse)を指定します。$deepfalse(または省略)の場合、ノード自身だけがコピーされ、そのノードが持っている子ノードはコピーされません。この動作を「浅いコピー」と呼び、複製されたノードは空の要素として扱われます。一方、$deeptrueの場合、ノード自身とその子ノード、さらにその子ノードの子ノード…と、すべての階層の子孫ノードが再帰的にコピーされます。これを「深いコピー」と呼び、元のノードと全く同じ構造と内容を持つ複製が作成されます。

メソッドの戻り値は、複製された新しいDOMNodeオブジェクトです。この新しいノードは、元のドキュメント内の別の場所に挿入したり、内容を修正したりして使用できます。

サンプルコードでは、まず特定のIDを持つXML要素を元のノードとして取得します。次に、この元のノードに対し、cloneNode(false)で浅いコピーを作成し、子ノードが含まれないことを示しつつ、後から新しい内容を追加する例を示しています。また、cloneNode(true)で深いコピーを作成し、元のノードの子ノードも含めて完全に複製される様子が確認できます。これらの複製されたノードは、ドキュメント内のcontainer要素に追加され、最終的なXML出力でそれぞれのコピーの挙動が明確に示されています。

cloneNodeメソッドを利用する際は、引数$deepの指定が非常に重要です。false(または省略)を指定すると、ノード自身のみがコピーされる「浅いコピー」となり、子ノードは含まれません。一方、trueを指定すると、ノード自身とすべての子ノードが再帰的にコピーされる「深いコピー」となります。意図した通り子ノードを含めたい場合は、必ずtrueを指定してください。クローンされたノードは、元のドキュメントに自動的には追加されません。必ずappendChildなどのメソッドを使って、目的の場所に明示的に追加してください。また、HTMLやXMLでユニークなはずのID属性は、クローンによって重複する可能性があります。getElementByIdなどを使う際に予期せぬ動作を避けるため、クローン後にID属性を変更するなどの対応を検討してください。元のノードはクローン操作によって変更されることはありません。

関連コンテンツ

関連IT用語

関連プログラミング言語