How to Add a PHP Simplexmlelement to Another Simplexmlelement

PHP - SimpleXML - AddChild with another SimpleXMLElement

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.

Is there a way to add a PHP SimpleXMLElement to another SimpleXMLElement?

Hey unknown. You have to use the DOMElement interface to your SimpleXML objects to achieve this.

<?php

$s = new SimpleXMLElement('<root/>');
$t = new DOMElement('child');

$dom = dom_import_simplexml($s);
$dom->appendChild($t);

echo $s->asXML();
// <root><child/></root>

If you need more specific details, let me know. There are several examples in the documentation and comments for the dom_import_simplexml() method too: http://php.net/dom_import_simplexml

In SimpleXML, how can I add an existing SimpleXMLElement as a child element?

I know this isn't the most helpful answer, but especially since you're creating/modifying XML, I'd switch over to using the DOM functions. SimpleXML's good for accessing simple documents, but pretty poor at changing them.

If SimpleXML is treating you kindly in all other places and you want to stick with it, you still have the option of jumping over to the DOM functions temporarily to perform what you need to and then jump back again, using dom_import_simplexml() and simplexml_import_dom(). I'm not sure how efficient this is, but it might help you out.

SimpleXML: append one tree to another

You can't add a "tree" directly using SimpleXML, as you have seen. However, you can use some DOM methods to do the heavy lifting for you whilst still working on the same underlying XML.

$xmldict = new SimpleXMLElement('<dictionary><a/><b/><c/></dictionary>');
$kitty = new SimpleXMLElement('<cat><sound>meow</sound><texture>fuzzy</texture></cat>');

// Create new DOMElements from the two SimpleXMLElements
$domdict = dom_import_simplexml($xmldict->c);
$domcat = dom_import_simplexml($kitty);

// Import the <cat> into the dictionary document
$domcat = $domdict->ownerDocument->importNode($domcat, TRUE);

// Append the <cat> to <c> in the dictionary
$domdict->appendChild($domcat);

// We can still use SimpleXML! (meow)
echo $xmldict->c->cat->sound;

How to add SimpleXMLElement node as a child element?

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);
}
}

SimpleXML: append one tree to another

You can't add a "tree" directly using SimpleXML, as you have seen. However, you can use some DOM methods to do the heavy lifting for you whilst still working on the same underlying XML.

$xmldict = new SimpleXMLElement('<dictionary><a/><b/><c/></dictionary>');
$kitty = new SimpleXMLElement('<cat><sound>meow</sound><texture>fuzzy</texture></cat>');

// Create new DOMElements from the two SimpleXMLElements
$domdict = dom_import_simplexml($xmldict->c);
$domcat = dom_import_simplexml($kitty);

// Import the <cat> into the dictionary document
$domcat = $domdict->ownerDocument->importNode($domcat, TRUE);

// Append the <cat> to <c> in the dictionary
$domdict->appendChild($domcat);

// We can still use SimpleXML! (meow)
echo $xmldict->c->cat->sound;

Copy SimpleXMLElement children to a different object

SimpleXML's editing functionality is rather limited, and in this case, both the assignment you're doing and ->addChild can only set the text content of the new element, not its attributes and children.

This may be one case where you need the power of the more complex DOM API. Luckily, you can mix the two in PHP with almost no penalty, using dom_import_simplexml and simplexml_import_dom to switch to the other wrapper.

Once you have a DOM representation, you can use the appendChild method of DOMNode to add a full node, but there's a catch - you can only add nodes "owned by" the same document. So you have to first call the importNode method on the document you're trying to edit.

Putting it all together, you get something like this:

// Set up the objects you're copying from and to
// These don't need to be complete documents, they could be any element
$obj1 = simplexml_load_string('<foo><event url="example.com" /></foo>');
$obj2 = simplexml_load_string('<foo><event url="another.example.com" /></foo>');

// Get a DOM representation of the root element we want to add things to
// Note that $obj1_dom will always be a DOMElement not a DOMDocument,
// because SimpleXML has no "document" object
$obj1_dom = dom_import_simplexml($obj1);

// Loop over the SimpleXML version of the source elements
foreach ($obj2->event as $event) {
// Get the DOM representation of the element we want to copy
$event_dom = dom_import_simplexml($event);
// Copy the element into the "owner document" of our target node
$event_dom_copy = $obj1_dom->ownerDocument->importNode($event_dom, true);
// Add the node as a new child
$obj1_dom->appendChild($event_dom_adopted);
}

// Check that we have the right output, not trusting var_dump or print_r
// Note that we don't need to convert back to SimpleXML
// - $obj1 and $obj1_dom refer to the same data internally
echo $obj1->asXML();

Insert XML structure as a child of another XML Element using PHP

You can't with SimpleXML, but if you really need manipulate your DOM or create it from scratch consider DOMDocument.

$xmlObject   = new \DOMDocument();
$xml = $xmlObject->createElement('root');
$xml_a = $xmlObject->createElement('parent');
$xml_b = $xmlObject->createElement('child');
$xml_b->setAttribute('attribute','value');
$xml_b->appendChild(new \DOMElement('item', 'itemValue'));
$xml_a->appendChild($xml_b);
$xml->appendChild($xml_a);
$xmlObject->appendChild($xml);
echo $xmlObject->saveXML();


Related Topics



Leave a reply



Submit