PHP -симплексный язык программирования - Добавить дочерний элемент с другим SimpleXMLElement
Я пытаюсь создать довольно сложный XML-документ.
У меня есть куча разделов XML-документа, которые повторяются. Я думал, что буду использовать несколько шаблонов строк в качестве базового документа для разделов и создавать экземпляры XML-элементов с помощью simplexml_load_string.
Итак, у меня есть один экземпляр SimpleXMLElement в качестве базового документа
$корень= simplexml_load_string($template_root);
Затем я перебираю некоторые элементы в своей базе данных, создаю новый элемент SimpleXML, что-то вроде этого:
Для (бла-бла-бла):
$элемент = simplexml_load_string($template_item); // делать что-то с предметом //попробуйте добавить элемент в корневой документ..
//Застрял здесь.. не могу сделать $root->элементы->addChild($item)Конец;
Я не могу вызвать addChild, потому что он просто ожидает имя тега и значение.. вы не можете добавить дочерний элемент другого SimpleXMLElement.
Я что-то здесь упускаю? кажется действительно глупым этот addChild не может принимать элемент SimpleXML в качестве параметра.
Есть ли другой способ сделать это? (помимо использования другой библиотеки xml)
3 answers
Насколько я знаю, вы не можете сделать это с помощью SimpleXML, потому что addChild
не создает глубокую копию элемента (необходимость указывать имя тега может быть легко преодолена вызовом SimpleXMLElement::getName()
).
Одним из решений было бы использовать вместо этого DOM:
С помощью этой функции:
function sxml_append(SimpleXMLElement $to, SimpleXMLElement $from) {
$toDom = dom_import_simplexml($to);
$fromDom = dom_import_simplexml($from);
$toDom->appendChild($toDom->ownerDocument->importNode($fromDom, true));
}
У нас есть для
<?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();
Вывод
<?xml version="1.0"?>
<root><child>one</child><child><k>two</k></child></root>
Смотрите также некоторые комментарии пользователей, которые используют рекурсивные функции и addChild
, например этот.
Вы можете использовать эту функцию, основанную на создании дочерних элементов с атрибутами из источника:
function xml_adopt($root, $new) {
$node = $root->addChild($new->getName(), (string) $new);
foreach($new->attributes() as $attr => $value) {
$node->addAttribute($attr, $value);
}
foreach($new->children() as $ch) {
xml_adopt($node, $ch);
}
}
$xml = new SimpleXMLElement("<root/>");
$child = new SimpleXMLElement("<content><p a=\"aaaaaaa\">a paragraph</p><p>another <br/>p</p></content>");
xml_adopt($xml, $child);
echo $xml->asXML()."\n";
Это приведет к:
<?xml version="1.0"?>
<root><content><p a="aaaaaaa">a paragraph</p><p>another p<br/></p></content></root>
Пример xml_adopt() не сохраняет узлы пространства имен.
Мое редактирование было отклонено, потому что оно сильно изменилось? был ли это спам?.
Вот версия xml_adopt(), которая сохраняет пространства имен.
function xml_adopt($root, $new, $namespace = null) {
// first add the new node
// NOTE: addChild does NOT escape "&" ampersands in (string)$new !!!
// replace them or use htmlspecialchars(). see addchild docs comments.
$node = $root->addChild($new->getName(), (string) $new, $namespace);
// add any attributes for the new node
foreach($new->attributes() as $attr => $value) {
$node->addAttribute($attr, $value);
}
// get all namespaces, include a blank one
$namespaces = array_merge(array(null), $new->getNameSpaces(true));
// add any child nodes, including optional namespace
foreach($namespaces as $space) {
foreach ($new->children($space) as $child) {
xml_adopt($node, $child, $space);
}
}
}
(изменить: добавлен пример)
$xml = new SimpleXMLElement(
'<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/">
<channel></channel></rss>');
$item = new SimpleXMLElement(
'<item xmlns:media="http://search.yahoo.com/mrss/">
<title>Slide Title</title>
<description>Some description</description>
<link>http://example.com/img/image.jpg</link>
<guid isPermaLink="false">A1234</guid>
<media:content url="http://example.com/img/image.jpg" medium="image" duration="15">
</media:content>
</item>');
$channel = $xml->channel;
xml_adopt($channel, $item);
// output:
// Note that the namespace is (correctly) only preserved on the root element
'<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
<channel>
<item>
<title>Slide Title</title>
<description>Some description</description>
<link>http://example.com/img/image.jpg</link>
<guid isPermaLink="false">A1234</guid>
<media:content url="http://example.com/img/image.jpg" medium="image" duration="15">
</media:content>
</item>
</channel>
</rss>'