К сожалению SimpleXMLElement
не предлагает ничего, чтобы объединить два элемента. Как писал @ nickf , это больше подходит для чтения, чем для манипуляции. Тем не менее, дочернее расширение DOMDocument
предназначено для редактирования, и вы можете объединить оба с помощью dom_import_simplexml()
. И @ salathe показывает в связанном ответе , как это работает для конкретных SimpleXMLElements.
Ниже показано, как это работает с проверкой ввода и некоторыми другими опциями. Я делаю это с двумя примерами. Первый пример - это функция для вставки строки XML:
/**
* 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);
}
Эта примерная функция позволяет добавлять XML или вставлять его перед определенным элементом, включая корневой элемент. После выяснения, есть ли что-то, что нужно добавить, он использует функции и методы DOMDocument для вставки XML в качестве фрагмента документа, а также в Как импортировать строку XML в PHP DOMDocument . Пример использования:
$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();
Это дает следующий вывод:
<?xml version="1.0"?>
<!-- this works, too -->
<parent>
<!-- leave a comment -->
<test><this>now</this></test>
</parent>
Второй пример - вставка SimpleXMLElement
. Он использует первую функцию, если это необходимо. Он в основном проверяет, есть ли что-то, что нужно сделать, и какой тип элемента нужно импортировать. Если это атрибут, он просто добавит его, если это элемент, он будет сериализован в XML, а затем добавлен к родительскому элементу как XML:
/**
* 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);
}
Эта примерная функция нормализует список элементов и атрибутов, как это принято в Simplexml. Возможно, вы захотите изменить его, чтобы вставить несколько простых элементов SimpleXMLE одновременно, но, как показано в примере использования ниже, мой пример не поддерживает это (см. Пример атрибутов):
// 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();
Это продолжение первого примера использования. Таким образом, теперь вывод:
<?xml version="1.0"?>
<!-- this works, too -->
<parent attribute="value">
<!-- leave a comment -->
<this>now</this><test><this>now</this></test>
<!-- this works, too -->
<parent>
<!-- leave a comment -->
<test><this>now</this></test>
</parent>
</parent>
Надеюсь, это полезно. Вы можете найти код в гисте и как онлайн-демонстрацию / Обзор версии PHP .