Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add SimpleXMLElement node as a child element?

Tags:

php

xml

simplexml

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?

like image 540
netdjw Avatar asked Dec 13 '25 13:12

netdjw


2 Answers

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);
    }
}
like image 95
Nigel Ren Avatar answered Dec 16 '25 04:12

Nigel Ren


The SimpleXMLElement::addChild method only accepts simple values. But in this case, you are trying to add another SimpleXMLElement object.

You can check out this link that suggest the use of DOM https://stackoverflow.com/a/2356245/6824629

This is the official function documentation https://www.php.net/manual/en/function.dom-import-simplexml.php for dom_import_simplexml

Your code should look something like this:

<?php
$target_xml = new DOMDocument('1.0');

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

foreach ($source_body as $source_child) {
    foreach ($source_child as $p) {
        $dom_sxe = dom_import_simplexml($p);
        // don't forget to handle your errors
        $target_xml->appendChild($dom_sxe);
    }
}

//you get back your target xml here
echo $target_xml->saveXML();

like image 40
jasonwubz Avatar answered Dec 16 '25 04:12

jasonwubz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!