Hard worker
Hard worker

Reputation: 4046

Simplexml with multiple tags

In all the examples of simplexml I have seen the structure of the xml is like:

<examples>
<example>
</example>
<example>
</example>
<example>
</example>
</examples>

However I am dealing with xml in the form:

 <examples>
    <example>
    </example>
    <example>
    </example>
    <example>
    </example>
</examples>
<app>
<appdata>
<error>
<Details> 
 <ErrorCode>101</ErrorCode> 
 <ErrorDescription>Invalid Username and Password</ErrorDescription> 
 <ErrorSeverity>3</ErrorSeverity> 
 <ErrorSource /> 
 <ErrorDetails /> 
</Details>
</error>
<items>
<item>
</item>
<item>
</item>
</items>
</appdata>
</app>

I would like to skip the examples stuff, and go straight to the app tag and check if the error errorcode exists and if it doesn't, go to the items array and loop through it.

My current way of handling this is:

$items = new SimpleXMLElement($xml_response); 
foreach($items as $item){
        //in here I check the presence of the object properties
    }

Is there a better way? The problem is the xml structure sometimes changes order so I want to be able to go straight to particular parts of the xml.

Upvotes: 2

Views: 862

Answers (1)

i alarmed alien
i alarmed alien

Reputation: 9520

This kind of thing is very easy using XPath, and handily, SimpleXML has an xpath function built into it! XPaths allow you to select nodes in a graph based on their ancestors, descendants, attributes, values, and so on.

Here is an example of using SimpleXML's xpath function to extract data from your XML. Note that I added an extra parent element to the sample you posted so that the XML would validate.

$sxo = new SimpleXMLElement($xml);
# this selects all 'error' elements with parent 'appdata', which has parent 'app'
$error = $sxo->xpath('//app/appdata/error');

if ($error) {
    # go through the error elements...
    while(list( , $node) = each($error)) {
        # get the error details
        echo "Found an error!" . PHP_EOL;
        echo $node->Details->ErrorCode 
        . ", severity " . $node->Details->ErrorSeverity 
        . ": " . $node->Details->ErrorDescription . PHP_EOL;
    }
}

Output:

Found an error!
101, severity 3: Invalid Username and Password

Here's another example -- I edited the XML excerpt slightly to show the results better here:

// edited <items> section of the XML you posted:
<items>
    <item>Item One
    </item>
    <item>Item Two
    </item>
</items>

# this selects all 'item' elements under appdata/items:
$items = $sxo->xpath('//appdata/items/item');
foreach ($items as $i) {
    echo "Found item; value: " . $i . PHP_EOL;
}

Output:

Found item; value: Item One
Found item; value: Item Two

There's more information in the SimpleXML XPath documentation, and try the zvon.org XPath tutorials -- they give a good grounding in XPath 1.0 syntax.

Upvotes: 1

Related Questions