netdjw
netdjw

Reputation: 6007

PHP DOMElement appendChild get DOMException Wrong Document Error

I want to copy <w:p> tags from an XML document into another one. Both XML documents follow this structure:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:document xmlns:main=""here is some namespace definitions">
  <w:body>
    <w:p>
       <somechildelementshere />
    </w:p>
  </w:body>
</w:document>

I have this PHP code:

// $targetDocument contains a <w:document> tag with their children
$target_body = $targetDocument->getElementsByTagNameNS($ns, 'body')[0];

// $sourceBody contains a <w:body> tag with their children
$paragraphs = $sourceBody->getElementsByTagNameNS($ns, 'p');

// $target_body is a DOMElement and $paragraph will be a DOMElement too
foreach ($paragraphs as $paragraph) {
  $target_body->importNode($paragraph, true);
}

And in the foreach I get DOMException Wrong Document Error message.

How can I add a DOMElement into another one as a child element?

Upvotes: 0

Views: 419

Answers (1)

Nigel Ren
Nigel Ren

Reputation: 57121

There are a few problems with the XML document and the code. It is always better while developing to ensure that you get the code to show any errors being generated as this help in debugging.

I've changed the namespace in the document to w to match the namespace actually used, I've also remove the extra quote in xmlns:main=""here and put in a dummy URL.

For the code, you must call importNode() on the document you want to add it to and not an element. Note that this also only makes the node available, it doesn't actually insert it. Here I store the newly created node temporarily and pass it to appendChild() on the node in the target document where I want to add the node.

The working code is (I only use the same document as source and target for simplicity sake)...

$source = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:document xmlns:w="http://some.url">
  <w:body>
    <w:p>
       <somechildelementshere />
    </w:p>
  </w:body>
</w:document>';

$targetDocument = new DOMDocument();
$targetDocument->loadXML($source);
$sourceBody = new DOMDocument();
$sourceBody->loadXML($source);
$ns = "http://some.url";

$target_body = $targetDocument->getElementsByTagNameNS($ns, 'body')[0];

// $sourceBody contains a <w:body> tag with their children
$paragraphs = $sourceBody->getElementsByTagNameNS($ns, 'p');

// $target_body is a DOMElement and $paragraph will be a DOMElement too
foreach ($paragraphs as $paragraph) {
    $impParagraph = $targetDocument->importNode($paragraph, true);
    $target_body->appendChild($impParagraph);
}

echo $targetDocument->saveXML();

Upvotes: 1

Related Questions