用于SimpleXML对象的PHP array_walk_recursive()?

时间:2013-06-13 19:30:45

标签: php simplexml spl

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

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

// function reverseText($ str){};

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

如何将reverseText()应用于每个节点以获取第二个XML片段?

2 个答案:

答案 0 :(得分:11)

这里Standard PHP Library可以拯救。

一种选择是使用(鲜为人知的)SimpleXMLIterator。它是PHP中可用的几个RecursiveIterator之一,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>

答案 1 :(得分:0)

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

然后您可以在该阵列上使用array_walk。但是,您不希望反转每个节点的字符串,只反映那些没有任何子元素的元素。

$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查询允许更多控制,例如命名空间。