1

I have a series of arbitrary XML Documents that I need to parse and perform some string manipulation on each element within the document.

For example:

<sample>
  <example>
    <name>David</name>
    <age>21</age>
  </example>
</sample>

For the nodes name and age I might want to run it through a function such as strtoupper to change the case.

I am struggling to do this in a generic way. I have been trying to use RecursiveIteratorIterator with SimpleXMLIterator to achieve this but I am unable to get the parent key to update the xml document:

$iterator = new RecursiveIteratorIterator(new SimpleXMLIterator($xml->asXML()));
foreach ($iterator as $k=> $v) {
    $iterator->$k = strtoupper($v);
}

This fails because $k in this example is 'name' so it's trying to do:

$xml->name = strtoupper($value);

When it needs to be

$xml->example->name = strtoupper($value);

As the schema of the documents change I want to use something generic to process them all but I don't know how to get the key.

Is this possible with Spl iterators and simplexml?

1 Answer 1

1

You are most likely looking for something that I worded SimpleXML-Self-Reference once. It does work here, too.

And yes, Simplexml has support for SPL and RecursiveIteratorIterator.

So first of all, you can directly make $xml work with tree-traversal by opening the original XML that way:

$buffer = <<<BUFFER
<sample>
  <example>
    <name>David</name>
    <age>21</age>
  </example>
</sample>
BUFFER;

$xml = simplexml_load_string($buffer, 'SimpleXMLIterator');
//                                     #################

That allows you to do all the standard modifications (as SimpleXMLIterator is as well a SimpleXMLElement) but also the recursive tree-traversal to modify each leaf-node:

$iterator = new RecursiveIteratorIterator($xml);
foreach ($iterator as $node) {
    $node[0] = strtoupper($node);
    //   ###
}

This exemplary recursive iteration over all leaf-nodes shows how to set the self-reference, the key here is to assign to $node[0] as outlined in the above link.

So all left is to output:

$xml->asXML('php://output');

Which then simply gives:

<?xml version="1.0"?>
<sample>
  <example>
    <name>DAVID</name>
    <age>21</age>
  </example>
</sample>

And that's the whole example and it should also answer your question.

Sign up to request clarification or add additional context in comments.

1 Comment

I also just created a RecursiveSimpleXMLIterator so that you can simply apply the recursive iteration on any SimpleXMLElement with it instead of relying on SimpleXMLIterator.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.