5

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.

hakre
  • 193,403
  • 52
  • 435
  • 836
miCRoSCoPiC_eaRthLinG
  • 2,910
  • 4
  • 40
  • 56
  • Related: [Is there a way to add a PHP SimpleXMLElement to another SimpleXMLElement?](http://stackoverflow.com/q/1157104/367456) – hakre Apr 27 '13 at 10:25

2 Answers2

4

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>'
);
hakre
  • 193,403
  • 52
  • 435
  • 836
Josh Davis
  • 28,400
  • 5
  • 52
  • 67
  • I'd go for the 1st method as it doesn't involve any external libraries. Played around with the code a bit and managed to figure out the exact code sequence. Thanks. That helped bigtime :) – miCRoSCoPiC_eaRthLinG Dec 01 '09 at 09:00
  • Please contribute with the exact code sequence if you still have it...! – maralbjo May 01 '10 at 12:13
  • Hi kids, I added a code-example that shows how this works including an online demo. I dunno why this was not made available in the past three and a half years as this Q&A shows a basic and useful concept. You all might have had super secret code ;) - And yes, nowadays *SimpleDOM* is totally superfluous in my eyes. – hakre Apr 27 '13 at 07:08
4

Have a look at my code:

$doc = new DOMDocument();       
$doc->loadXML("<root/>");       

$fragment = $doc->createDocumentFragment();     
$fragment->appendXML("<foo>text</foo><bar>text2</bar>");
$doc->documentElement->appendChild($fragment);

echo $doc->saveXML();

This modifies the XML document by adding an XML fragment. Online Demo.

hakre
  • 193,403
  • 52
  • 435
  • 836
maralbjo
  • 963
  • 1
  • 10
  • 16
  • 1
    Your code is fine and working: http://eval.in/17709 - Just remove the part about saving for the moment, you just have an XML modifying, unrelated problem of saving to disk which you should place in a different question. – hakre Apr 27 '13 at 06:51
  • @hakre saveXML returns a string, it doesn't actually save it to disk. – oskarth Sep 26 '13 at 10:30