Search code examples
recursionxml-parsingtagssimplexml

Parse simpleXML data recursively using PHP


I want to read nested elements and each element's attribute values from an XML file. I am using simpleXML and here is my code so far:

$path = Mage::getBaseUrl('media').'Banners/data.xml' ;
$doc = new DOMDocument();
$doc->load( $path );

$items = $doc->getElementsByTagName( "imgitem" );
$xml=simplexml_load_file($path);

foreach($xml->children() as $child)
{
  foreach( $child as $item )
    {
        $attr = $xml->imgitem->attributes();
        echo $attr['image'].'<br>';
        echo $attr['link'].'<br>';
        echo $attr['target'].'<br>';            

    }
}

Can anyone point me in the right direction in order to get all the child nodes and their attributes recursively?

Here is the source XML file structure

<Banner> 
<imgitem image="img/source/path" link="" target="_blank" delay="" textBlend="yes"> <![CDATA[Autumn Leaves]]> </imgitem> 
<imgitem image="img/source/path" link="" target="_blank" delay="" textBlend="yes"> <![CDATA[Creek]]> </imgitem> 
<imgitem image="img/source/path" link="" target="_blank" delay="" textBlend="yes"> <![CDATA[Dock]]> </imgitem> 
</Banner>

Now what I want is the values of all the attributes of each of the three items of the parent tag. So need to loop through the main tag to get all three (or any number of) items and then take another loop and fetch all the attribute values of each item.


Solution

  • Thanks for clarifying the question. I think you're over-complicating things here - there is no recursion needed here, and you may not even need more than one loop.

    You already have foreach($xml->children() as $child) - this will give you each <imgitem> in turn as $child, since they are the children of the top-level item. You could equivalently say foreach($xml->imgitem as $child), which would skip any children which are not <imgitem> tags.

    To echo attributes of those elements, you just need to say $child['someAttributeName'] - so your code as you have in the example would just look like this:

    $path = Mage::getBaseUrl('media').'Banners/data.xml' ;
    $xml = simplexml_load_file($path);
    
    foreach($xml->children() as $child)
    {
        echo $child['image'].'<br>';
        echo $child['link'].'<br>';
        echo $child['target'].'<br>';           
    }
    

    If instead of referencing particular attributes, you for some reason want to loop over every attribute in turn, you just need one more loop inside:

    foreach($xml->children() as $child)
    {
        foreach($child->attributes() as $attr_name => $attr_value)
        {
            echo "Attribute '$attr_name' has value '$attr_value'";
        }
    }