문제

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