public
Created

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

  • Download Gist
simplexml-import.php
PHP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
<?php
/**
* In SimpleXML, how can I add an existing SimpleXMLElement as a child element?
*
* @link http://stackoverflow.com/q/767327/367456
* @link http://eval.in/9568
* @link http://3v4l.org/1sI05
*/
 
/**
* Insert XML into a SimpleXMLElement
*
* @param SimpleXMLElement $parent
* @param string $xml
* @param bool $before
* @return bool XML string added
*/
function simplexml_import_xml(SimpleXMLElement $parent, $xml, $before = false)
{
$xml = (string)$xml;
 
// check if there is something to add
if ($nodata = !strlen($xml) or $parent[0] == NULL) {
return $nodata;
}
 
// add the XML
$node = dom_import_simplexml($parent);
$fragment = $node->ownerDocument->createDocumentFragment();
$fragment->appendXML($xml);
 
if ($before) {
return (bool)$node->parentNode->insertBefore($fragment, $node);
}
 
return (bool)$node->appendChild($fragment);
}
 
$parent = new SimpleXMLElement('<parent/>');
 
// insert some XML
simplexml_import_xml($parent, "\n <test><this>now</this></test>\n");
 
// insert some XML before a certain element, here the first <test> element
// that was just added
simplexml_import_xml($parent->test, "<!-- leave a comment -->\n ", $before = true);
 
// you can place comments above the root element
simplexml_import_xml($parent, "<!-- this works, too -->", $before = true);
 
// but take care, you can produce invalid XML, too:
// simplexml_add_xml($parent, "<warn><but>take care!</but> you can produce invalid XML, too</warn>", $before = true);
 
echo $parent->asXML(), "\n.........................................\n\n";
 
$test = simplexml_load_string($parent->asXML()); // validate
 
/**
* Insert SimpleXMLElement into SimpleXMLElement
*
* @param SimpleXMLElement $parent
* @param SimpleXMLElement $child
* @param bool $before
* @return bool SimpleXMLElement added
*/
function simplexml_import_simplexml(SimpleXMLElement $parent, SimpleXMLElement $child, $before = false)
{
// check if there is something to add
if ($child[0] == NULL) {
return true;
}
 
// if it is a list of SimpleXMLElements default to the first one
$child = $child[0];
 
// insert attribute
if ($child->xpath('.') != array($child)) {
$parent[$child->getName()] = (string)$child;
return true;
}
 
$xml = $child->asXML();
 
// remove the XML declaration on document elements
if ($child->xpath('/*') == array($child)) {
$pos = strpos($xml, "\n");
$xml = substr($xml, $pos + 1);
}
 
return simplexml_import_xml($parent, $xml, $before);
}
 
// append the element itself to itself
simplexml_import_simplexml($parent, $parent);
 
// insert <this> before the first child element (<test>)
simplexml_import_simplexml($parent->children(), $parent->test->this, true);
 
// add an attribute to the document element
$test = new SimpleXMLElement('<test attribute="value" />');
simplexml_import_simplexml($parent, $test->attributes());
 
echo $parent->asXML();

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.