Search code examples
phpsimplexml

PHP - SimpleXML - AddChild with another SimpleXMLElement


I'm trying to build a rather complex XML document.

I have a bunch of sections of the XML document that repeats. I thought I'd use multiple string templates as base document for the sections and create instances of XML elements using simplexml_load_string.

So I have one instance of SimpleXMLElement as the base document

$root = simplexml_load_string($template_root);

then I loop through some items in my database, create new SimpleXMLElement, something like this:

for (bla bla bla):

$item = simplexml_load_string($template_item); // do stuff with item // try to add item to the root document..
// Stuck here.. can't do $root->items->addChild($item)

endfor;

I can't call addChild because it just expects a tag name and value.. you can't addChild another SimpleXMLElement.

Am I missing something here? seems really dumb that addChild can't take a SimpleXMLELement as a parameter.

Is there any other way to do this? (apart from using a different xml lib)


Solution

  • As far as I know, you can't do it with SimpleXML because addChild doesn't make a deep copy of the element (being necessary to specify the tag name can easily be overcome by calling SimpleXMLElement::getName()).

    One solution would be to use DOM instead:

    With this function:

    function sxml_append(SimpleXMLElement $to, SimpleXMLElement $from) {
        $toDom = dom_import_simplexml($to);
        $fromDom = dom_import_simplexml($from);
        $toDom->appendChild($toDom->ownerDocument->importNode($fromDom, true));
    }
    

    We have for

    <?php
    header("Content-type: text/plain");
    $sxml = simplexml_load_string("<root></root>");
    
    $n1 = simplexml_load_string("<child>one</child>");
    $n2 = simplexml_load_string("<child><k>two</k></child>");
    
    sxml_append($sxml, $n1);
    sxml_append($sxml, $n2);
    
    echo $sxml->asXML();
    

    the output

    <?xml version="1.0"?>
    <root><child>one</child><child><k>two</k></child></root>
    

    See also some user comments that use recursive functions and addChild, e.g. this one.