phpxmlsimplexmladditionsimpledom

Adding a block of XML as child of a SimpleXMLElement object


I have this SimpleXMLElement object with a XML setup similar to the following...

$xml = <<<EOX
<books>
    <book>
        <name>ABCD</name>
    </book>
</books>
EOX;

$sx = new SimpleXMLElement( $xml );

Now I have a class named Book that contains info. about each book. The same class can also spit out the book info. in XML format akin the the above (the nested block).. example,

$book = new Book( 'EFGH' );
$book->genXML();

... will generate
<book>
    <name>EFGH</name>
</book>

Now I'm trying to figure out a way by which I can use this generated XML block and append as a child of so that now it looks like... for example..

// Non-existent member method. For illustration purposes only.
$sx->addXMLChild( $book->genXML() );    

...XML tree now looks like:
<books>
    <book>
        <name>ABCD</name>
    </book>
    <book>
        <name>EFGH</name>
    </book>
</books>

From what documentation I have read on SimpleXMLElement, addChild() won't get this done for you as it doesn't support XML data as tag value.


Solution

  • Two solutions. First, you do it with the help of libxml / DOMDocument / SimpleXML: you have to import your $sx object to DOM, create a DOMDocumentFragment and use DOMDocumentFragment::appendXML():

    $doc = dom_import_simplexml($sx)->ownerDocument;
    
    $fragment = $doc->createDocumentFragment();     
    $fragment->appendXML($book->genXML());
    $doc->documentElement->appendChild($fragment);
    
    // your original $sx is now already modified.
    

    See the Online Demo.

    You can also extend from SimpleXMLElement and add a method that is providing this. Using this specialized object then would allow you to create the following easily:

    $sx = new MySimpleXMLElement($xml);
    
    $sx->addXML($book->genXML());
    

    Another solution is to use an XML library that already has this feature built-in like SimpleDOM. You grab SimpleDOM and you use insertXML(), which works like the addXMLChild() method you were describing.

    include 'SimpleDOM.php';
    
    $books = simpledom_load_string(
        '<books>
            <book>
                <name>ABCD</name>
            </book>
        </books>'
    );
    
    $books->insertXML(
        '<book>
            <name>EFGH</name>
        </book>'
    );