【问题标题】:PHP array_walk_recursive() for SimpleXML objects?SimpleXML 对象的 PHP array_walk_recursive()?
【发布时间】:2013-06-10 08:02:56
【问题描述】:

我想对 SimpleXML 对象中的每个节点应用一个函数。

<api>
   <stuff>ABC</stuff>
   <things>
      <thing>DEF</thing>
      <thing>GHI</thing>
      <thing>JKL</thing>
   </things>
</api>

//函数 reverseText($str){};

<api>
   <stuff>CBA</stuff>
   <things>
      <thing>FED</thing>
      <thing>IHG</thing>
      <thing>LKJ</thing>
   </things>
</api>

如何将 reverseText() 应用到每个节点以获取第二个 XML sn-p?

【问题讨论】:

  • 这不能是递归的,但遍历 XML 文档顺序 中的所有元素也可以。然而,在 PHP 中,这是作为 SimpleXMLExtension 中的 RecursiveIterator 实现的,可以按照 Salathe 的 SPL 概述使用。另请参阅:en.wikipedia.org/wiki/XML_tree

标签: php simplexml spl


【解决方案1】:

Standard PHP Library 可以来救援。

一种选择是使用(鲜为人知的)SimpleXMLIterator。它是 PHP 中可用的几个 RecursiveIterators 之一,而 SPL 中的 RecursiveIteratorIterator 可用于循环和更改所有元素的文本。

$source = '
<api>
   <stuff>ABC</stuff>
   <things>
      <thing>DEF</thing>
      <thing>GHI</thing>
      <thing>JKL</thing>
   </things>
</api>
';

$xml = new SimpleXMLIterator($source);
$iterator = new RecursiveIteratorIterator($xml);
foreach ($iterator as $element) {
    // Use array-style syntax to write new text to the element
    $element[0] = strrev($element);
}
echo $xml->asXML();

上面的例子输出如下:

<?xml version="1.0"?>
<api>
   <stuff>CBA</stuff>
   <things>
      <thing>FED</thing>
      <thing>IHG</thing>
      <thing>LKJ</thing>
   </things>
</api>

【讨论】:

  • 我刚刚尝试过这个来解析 XML 文件。请注意,它会跳过仅包含其他元素的任何元素,即它仅迭代文本元素。在我的例子中,我的元素包装了其他元素,但包含解析很重要的属性,并且这种技术不提供在循环中对它们的访问。对于 OP XML,这不是问题。如果“事物”有一个需要传递给 OP 函数的属性,那么如果没有一些额外的 XML 结构遍历以找到“事物”元素,这将无法工作。
  • RecursiveIteratorIterator 默认情况下仅迭代叶节点。您可以通过设置迭代模式(例如,在构造函数的第二个参数中...new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::CHILD_FIRST))来指示它也迭代非叶(父、分支)节点。
【解决方案2】:

您可以使用SimpleXMLElement::xpath() 方法创建文档中所有节点的数组。

然后您可以在该数组上使用array_walk。但是,您不想反转 every 节点的字符串,只反转那些没有任何子元素的元素。

$source = '
<api>
   <stuff>ABC</stuff>
   <things>
      <thing>DEF</thing>
      <thing>GHI</thing>
      <thing>JKL</thing>
   </things>
</api>
';    

$xml = new SimpleXMLElement($source);

array_walk($xml->xpath('//*'), function(&$node) {
    if (count($node)) return;
    $node[0] = strrev($node);
});

echo $xml->asXML();

上面的例子输出如下:

<?xml version="1.0"?>
<api>
   <stuff>CBA</stuff>
   <things>
      <thing>FED</thing>
      <thing>IHG</thing>
      <thing>LKJ</thing>
   </things>
</api>

xpath 查询允许更多控制,例如命名空间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-23
    • 2016-06-12
    相关资源
    最近更新 更多