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?
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.