I would like to apply a function to every node in a SimpleXML object.

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

How would I apply reverseText() to every node to get the second XML snippet?

有帮助吗?

解决方案

Here the Standard PHP Library can come to the rescue.

One option is to use the (little known) SimpleXMLIterator. It is one of several RecursiveIterators available in PHP and a RecursiveIteratorIterator from the SPL can be used to loop over and change all of the elements' text.

$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();

The above example outputs the following:

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

其他提示

You can create an array of all nodes in the document with the SimpleXMLElement::xpath() method.

Then you can use array_walk on that array. However you don't want to reverse the string of every node, only of those elements which don't have any child elements.

$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();

The above example outputs the following:

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

The xpath query allows more control for example with namespaces.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top