【问题标题】:PHP - SimpleXML - AddChild with another SimpleXMLElementPHP - SimpleXML - AddChild 与另一个 SimpleXMLElement
【发布时间】:2011-06-14 07:30:19
【问题描述】:

我正在尝试构建一个相当复杂的 XML 文档。

我有一堆重复的 XML 文档部分。我想我会使用多个字符串模板作为部分的基础文档,并使用 simplexml_load_string 创建 XML 元素的实例。

所以我有一个 SimpleXMLElement 实例作为基础文档

$根= simplexml_load_string($template_root);

然后我遍历数据库中的一些项目,创建新的 SimpleXMLElement,如下所示:

对于(bla bla bla):

$item = simplexml_load_string($template_item); // 用 item 做事 // 尝试将项目添加到根文档..
// 卡在这里.. 不能做 $root->items->addChild($item)

结束;

我不能调用 addChild,因为它只需要一个标签名称和值。你不能 addChild 另一个 SimpleXMLElement。

我在这里遗漏了什么吗? addChild 不能将 SimpleXMLELement 作为参数似乎真的很愚蠢。

还有其他方法可以做到这一点吗? (除了使用不同的 xml 库)

【问题讨论】:

标签: php simplexml


【解决方案1】:

据我所知,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>

另见一些使用递归函数的用户 cmets 和 addChild,例如this one.

【讨论】:

  • 谢谢.. 我慢慢得出这个结论。您的 sxml_append 函数运行良好。
  • sxml_append() 似乎是一个很好的解决方案,但我似乎无法在文档中找到任何对它的引用。
  • @Foo_Chow sxml_append() 是用户创建的函数。这就是为什么您不会在文档中找到它。
  • @Chad 似乎我忽略了答案的顶部,这是使用 DOM-XML 的一种非常直观的方式
  • 非常好的解决方案,我创建了SimpleXMLElement 的子类来添加此支持:gist.github.com/ericmulder/1e3bf4592d7c0463127d
【解决方案2】:

您可以使用这个基于从源创建具有属性的子级的函数:

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>

【讨论】:

  • 这个效果很好,不需要安装php dom。
  • 感谢您的解决方案。但我有问题。 (string)$new 为空,结果$node 也为空。但是$new-&gt;asXML() - 返回一个有效的 xml。
【解决方案3】:

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>'

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-12
  • 2016-11-15
  • 2011-05-11
  • 2019-04-19
  • 2016-03-08
相关资源
最近更新 更多