I'm trying to parse this XML structure but can't find a way to parse "n"-deep nested tags using recursion. The xml structure:
<plist version="1.0">
<key>1.1.1</key>
<dict>
<key>nag</key>
<integer>1</integer>
</dict>
<key>2.2.2</key>
<dict>
<key>nag</key>
<integer>1</integer>
</dict>
<key>3.3.3</key>
<dict>
<key>show_upgrade_button</key>
<integer>0</integer>
<key>nag_startup</key>
<dict>
<key>nag_gameover</key>
<integer>3</integer>
</dict>
<key>my_stuff</key>
<string>1=cb 2=rm 3=cb+rm =leave banner ads off</string>
</dict>
<key>4.4.4</key>
<dict>
<key>nag</key>
<integer>1</integer>
</dict>
</plist>
The nodes are matched key
- dict
being the key node a version number for the data inside the dict
node but the xml structure has arbrittrary dict
nesting as you can see in the above code. I've got this recursive function which accepts a dict
node so far but I can't see the light.
<? php
function recursiveNodes($nodes, $arr){
$count=0;
if($nodes->hasChildNodes() === true ){
foreach($nodes->childNodes as $node){
$temp = array();
if($node->nodeName === 'key'){
$temp['key_name'] = $node->nodeValue;
if($node->nextSibling->nodeName !== 'dict'){
$sibling = $node->nextSibling;
$temp['type_name'] = $sibling ->nodeName;
$temp['value_name'] = $sibling ->nodeValue;
}
if($sibling->nodeName === 'dict'){
return recursiveNodes($sibling, $arr[$count++][]=$temp);
}
}
}
}
return $arr;
}
?>
The recursion in your function is broken. It might be more easy to wrap it into an object instead of a single function.
That would also allow to more easily extend it as needed.
See the following usage-example:
$parser = new PlistXMLParser();
$parser->loadXML($xml);
print_r($parser->parse());
With your exemplary input it gives the following:
Array
(
[1.1.1] => Array
(
[nag] => 1
)
[2.2.2] => Array
(
[nag] => 1
)
[3.3.3] => Array
(
[show_upgrade_button] => 0
[nag_startup] => Array
(
[nag_gameover] => 3
)
[my_stuff] => 1=cb 2=rm 3=cb+rm =leave banner ads off
)
[4.4.4] => Array
(
[nag] => 1
)
)
Internally this works basically how you already do, see here an excerpt from the sources:
...
switch ($type) {
case self::NODE_INTEGER:
$result[$keyString] = sprintf('%0.0f', trim($value));
break;
case self::NODE_STRING:
$result[$keyString] = (string)$value;
break;
case self::NODE_DICT:
$parser = new self();
$parser->loadSimpleXMLElement($value);
$result[$keyString] = $parser->parse();
break;
default:
throw new UnexpectedValueException(sprintf('Unexpected type "%s" for key "%s"', $type, $key));
}
...
The parser is using a switch
construct to better deal with the individual type-tokens that come up in the XML structure. The exception highlights you features you've not yet implemented and the recursion is triggered for NODE_DICT
which just instantiates a new parser and let it do the work. A very simple form of recursion.