Search code examples
phpxmlsimplexml

How to add SimpleXMLElement node as a child element?


I have this PHP code. The $target_xml and $source_xml variables are SimpleXMLElement objects:

$target_body = $target_xml->children($this->namespaces['main']);
$source_body = $source_xml->children($this->namespaces['main']);

foreach ($source_body as $source_child) {
    foreach ($source_child as $p) {
        $target_body->addChild('p', $p, $this->namespace['main']);
    }
}

In the $p will be something like this XML code:

<w:p w:rsidR="009F3A42" w:rsidRPr="009F3A42" w:rsidRDefault="009F3A42" w:rsidP="009F3A42">
    <w:pPr>
        <w:pStyle w:val="NormlWeb"/>
        // .... here is more xml tags
    </w:pPr>
    <w:r w:rsidRPr="009F3A42">
        <w:rPr>
            <w:rFonts w:ascii="Open Sans" w:hAnsi="Open Sans" w:cs="Open Sans"/>
            <w:b/>
            <w:color w:val="000000"/>
            <w:sz w:val="21"/>
            <w:szCs w:val="21"/>
        </w:rPr>
        <w:t>Lorem ipsum dolor sit amet...</w:t>
    </w:r>
    <w:bookmarkStart w:id="0" w:name="_GoBack"/>
    <w:bookmarkEnd w:id="0"/>
</w:p>

The PHP code I have above will be add only this XML code to the target document:

<w:p/>

So all child nodes lost.

How can I add a child node with it's own child nodes?


Solution

  • SimpleXML is good for basic things, but lacks the control (and complications) of DOMDocument.

    When copying content from one document to another, you have to do three things (for SimpleXML), first is convert it to a DOMElement, then import it into the target document using importNode() with true as the second argument to say do a deep copy. This just makes it available to the target document and doesn't actually place the content. This is done using appendChild() with the newly imported node...

    // Convert target SimpleXMLElement to DOMElement
    $targetImport = dom_import_simplexml($target_body);
    
    foreach ($source_body as $source_child) {
        foreach ($source_child as $p) {
            // Convert SimpleXMLElement to DOMElement
            $sourceImport = dom_import_simplexml($p);
            // Import the new node into the target document
            $import = $targetImport->ownerDocument->importNode($sourceImport, true);
            // Add the new node to the correct part of the target
            $targetImport->appendChild($import);
        }
    }