I have a small application that does the following:
- allows the user to upload an XML file
- parses the XML file into an array to work with $_SESSION
- displays a list of parent element names the user can choose to view
- parses the array to display children of the selected parent elements
The issue is that every item can have children who can have children who can have children… etc… and this can go on indefinitely.
How can you include every child of a child in the final output?
The XML files can look similar to this:
<thing>
<parents>
<parent>
<name>parent 1</name>
<categories>
<category>
<name>category 1</name>
<items>
<item>
<name>item 1 (gen 1)</name>
<items>
<item>
<name>sub-item 1 (gen 2)</name>
<items>
<item>
<name>sub-sub-item 1 (gen 3)</name>
...this could continue forever..
</item>
</items>
</item>
</items>
</item>
</items>
</category>
</categories>
</parent>
</parents>
</thing>
I’ve parsed the XML into an array with PHP’s SimpleXML. Every file must have a parent, category, and first generation child items. The following code parses through these 3 levels of structure, but beyond that I’m lost.
$output .= '<ul>';
foreach($xml['parents'] as $parent){
$output .= '<li>'.$parent['name'].'</li>';
foreach($parent['categories']['category'] as $category){
$output .= '<li>'.$category['name'].'</li>';
foreach($category['items']['item'] as $item){
$output .= '<li>'.$item['name'].'</li>';
// here is where the $item can have children w/ children
// who can have children who can have children... etc... forever.
// (i.e. $item['items']['item'] as $generation2_items++...)
//
// I want to add them as another <li></li>...
//
// How can you account for unknown # of children?
}
}
}
$output .= '</ul>';
echo $output;
The code $outputs a list similar to:
- parent 1
-- category 1
--- item 1 (gen 1)
---- sub item 1 (gen 2)
----- sub-sub item 1 (gen 3)
------- etc.
-------- etc.
How can you determine how many child elements deep each item goes and then how can you create enough loops to parse through accordingly… or iterate through another way?
Thanks for your help.
Solution
PHP recursion function solved it. Here’s what I used when I got to the possible infinite repeating part:
function foo($element, $indent=0){
$result .= '<li>';
if($indent > 0){
for($i=1;$i<=$indent;$i++){
$result .= ' ';
}
}
$result .= $element['name'].'</li>';
if(isset($element['children']['child'])){
$i++;
foreach($element['children']['child'] as $child){
$result .= foo($child, $i);
}
}
return $result;
}
$output .= foo($item);
You may use a recursive function for this. Every programmer should know how to use recursion; if you don’t: go ahead and learn it right away!
What you basically want to do is to create a function, let’s call it
foo(), which takes one item as it’s input.foowill do two things:Creating recursive functions is, as I said, really useful and you should both learn and exercise this tool. You may for example send a second argument to
foowith the depth of the recursion so you can output the children with different indentation.