41

There's something I don't fully understand about node cloning with the PHP's DOM api. Here's a sample file that quickly duplicates the issue I'm coming across.

$doc  = new DOMDocument( '1.0', 'UTF-8' );
$root = $doc->createElement( 'root' ); // This doesn't work either $root = new DOMElement( 'root' );
$doc->appendChild( $root );

$doc2  = new DOMDocument( '1.0', 'UTF-8' );
$root2 = $doc2->createElement( 'root2' );
$doc2->appendChild( $root2 );

// Here comes the error
$root2->appendChild( $root->cloneNode() );

When you run this little snippet an exception is thrown

Fatal error: Uncaught exception 'DOMException' with message 'Wrong Document Error'

Can I not grab a node from a document, clone it, and then append it to another document?

ThinkingStiff
  • 64,767
  • 30
  • 146
  • 239
Peter Bailey
  • 105,256
  • 31
  • 182
  • 206

2 Answers2

61

Use DOMDocument->importNode to import the node into the other document before adding it to the DOM.

Gumbo
  • 643,351
  • 109
  • 780
  • 844
  • Perfect, Thanks. I was searching through the `DOMNode` and `DOMElement` APIs looking for something that would let me do this and (foolishly) never checked the `DOMDocument` methods =/ – Peter Bailey Nov 18 '09 at 21:31
  • 1
    Where did you add importNode? I added it to my code and I'm still getting the error. – NobleUplift Jan 08 '14 at 17:54
  • @NobleUplift You need to call `importNode` to import a node from one document to another document. After that you can append it as a child where you want. – Gumbo Jan 08 '14 at 18:42
  • 2
    I was working on deeply nested tags so I needed to call `$parent->ownerDocument->importNode($child, true)` and then I was able to add it. – NobleUplift Jan 08 '14 at 19:48
3

You'll have to append the result of the importNode method to the DOM. Keep in mind that the method could return false when it cannot be imported

if ($importedNode = $doc2->importNode($root->cloneNode())) {
    $root2->appendChild($importedNode);
}

If you need to import the node, all of it's child nodes (resursively) and/or the node's attributes use the optional second parameter deep:

if ($importedNode = $doc2->importNode($root->cloneNode(), true)) {
    $root2->appendChild($importedNode);
}
halfpastfour.am
  • 5,764
  • 3
  • 44
  • 61