Я пытаюсь создать довольно сложный XML-документ.
У меня есть куча разделов XML-документа, который повторяется. Я думал, что я буду использовать несколько строковых шаблонов в качестве базового документа для разделов и создавать экземпляры XML-элементов, используя simplexml_load_string.
Поэтому у меня есть один экземпляр SimpleXMLElement в качестве базового документа
$ root = simplexml_load_string ($ template_root);
затем я просматриваю некоторые элементы в моей базе данных, создаю новый SimpleXMLElement, что-то вроде этого:
для (bla bla bla):
$ item = simplexml_load_string ($ template_item); // Делаем материал с элементом // пытаемся добавить элемент в корневой документ.
// Застрял здесь .. не могу сделать $ root-> items-> addChild ($ item)ENDFOR;
Я не могу вызвать addChild, потому что он просто ожидает имя тега и значение. Вы не можете добавитьChild другой SimpleXMLElement.
Я что-то упустил? кажется очень глупым, что addChild не может принимать SimpleXMLELement в качестве параметра.
Есть ли другой способ сделать это? (кроме использования другой xml lib)
Насколько я знаю, вы не можете сделать это с помощью 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><pa=\"aaaaaaa\">a paragraph</p><p>another <br/>p</p></content>"); xml_adopt($xml, $child); echo $xml->asXML()."\n";
Это даст:
<?xml version="1.0"?> <root><content><pa="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>'