views:

3562

answers:

4

I'm trying to work out how to iterate though a returned SimpleXML object.

I'm using a toolkit called Tarzan AWS, which connects to Amazon Web Services (SimpleDB, S3, EC2, etc). I'm specifically using SimpleDB.

I can put data into the Amazon SimpleDB service, and I can get it back. I just don't know how to handle the SimpleXML object that is returned.

The Tarzan AWS documentation says this:

Look at the response to navigate through the headers and body of the response. Note that this is an object, not an array, and that the body is a SimpleXML object.

Here's a sample of the returned SimpleXML object:

 [body] => SimpleXMLElement Object
        (
            [QueryWithAttributesResult] => SimpleXMLElement Object
                (
                    [Item] => Array
                        (
                            [0] => SimpleXMLElement Object
                                (
                                    [Name] => message12413344443260
                                    [Attribute] => Array
                                        (
                                            [0] => SimpleXMLElement Object
                                                (
                                                    [Name] => active
                                                    [Value] => 1
                                                )

                                            [1] => SimpleXMLElement Object
                                                (
                                                    [Name] => user
                                                    [Value] => john
                                                )

                                            [2] => SimpleXMLElement Object
                                                (
                                                    [Name] => message
                                                    [Value] => This is a message.
                                                )

                                            [3] => SimpleXMLElement Object
                                                (
                                                    [Name] => time
                                                    [Value] => 1241334444
                                                )

                                            [4] => SimpleXMLElement Object
                                                (
                                                    [Name] => id
                                                    [Value] => 12413344443260
                                                )

                                            [5] => SimpleXMLElement Object
                                                (
                                                    [Name] => ip
                                                    [Value] => 10.10.10.1
                                                )

                                        )

                                )

                            [1] => SimpleXMLElement Object
                                (
                                    [Name] => message12413346907303
                                    [Attribute] => Array
                                        (
                                            [0] => SimpleXMLElement Object
                                                (
                                                    [Name] => active
                                                    [Value] => 1
                                                )

                                            [1] => SimpleXMLElement Object
                                                (
                                                    [Name] => user
                                                    [Value] => fred
                                                )

                                            [2] => SimpleXMLElement Object
                                                (
                                                    [Name] => message
                                                    [Value] => This is another message
                                                )

                                            [3] => SimpleXMLElement Object
                                                (
                                                    [Name] => time
                                                    [Value] => 1241334690
                                                )

                                            [4] => SimpleXMLElement Object
                                                (
                                                    [Name] => id
                                                    [Value] => 12413346907303
                                                )

                                            [5] => SimpleXMLElement Object
                                                (
                                                    [Name] => ip
                                                    [Value] => 10.10.10.2
                                                )

                                        )

                                )

                        )

So what code do I need to get through each of the object items? I'd like to loop through each of them and handle it like a returned mySQL query. For example, I can query SimpleDB and then loop though the SimpleXML so I can display the results on the page.

Alternatively, how do you turn the whole shebang into an array?

I'm new to SimpleXML, so I apologise if my questions aren't specific enough.

+3  A: 

You can used the SimpleXMP object (or its properties) in a foreach loop. If you want to loop through all the 'records' something like this can be used to access and display the data:

//Loop through all the members of the Item array 
//(essentially your two database rows).
foreach($SimpleXML->body->QueryWithAttributesResult->Item as $Item){
    //Now you can access the 'row' data using $Item in this case 
    //two elements, a name and an array of key/value pairs
    echo $Item->Name;
    //Loop through the attribute array to access the 'fields'.
    foreach($Item->Attribute as $Attribute){
        //Each attribute has two elements, name and value.
        echo $Attribute->Name . ": " . $Attribute->Value;
    }
}

Note that $Item will be a SimpleXML object, as is $Attribute, so they need to be referenced as objects, not arrays.

While the example code above is looping through the arrays in the SimpleXML object ($SimpleXML->body->QueryWithAttributesResult->Item), you can also loop through a SimpleXML object (say $SimpleXML->body->QueryWithAttributesResult->Item[0]), and that would give you each of the object's properties.

Each child element of a SimpleXML object is an XML entity. If the XML entity (tag) is not unique, then the element is simply an array of SimpleXML objects representing each entity.

If you want, this should create a more common row/fields array from your SimpleXML object (or get you close):

foreach($SimpleXML->body->QueryWithAttributesResult->Item as $Item){
    foreach($Item->Attribute as $Attribute){
        $rows[$Item->Name][$Attribute->Name] = $Attribute->Value;
    }
}

//Now you have an array that looks like:
$rows['message12413344443260']['active'] = 1;
$rows['message12413344443260']['user'] = 'john';
//etc.
Tim Lytle
Thanks very much for that. It's working very well.One simple question though. Using the first example, how do I echo just one of the $Attribute->Value, rather than the whole lot. I've tried all sorts of things from echo $Attribute->Name['xx'], loops in loops, etc. I've confused myself somewhat. Is it even possible? Or do I just have to if($Attribute->Value == "xx") statements?
Coffee Cup
I don't know of SimpleXML providing a shortcut to what you're doing (testing the value while looping).
Tim Lytle
+2  A: 

In the case of XML responses that DON'T contain CDATA sections (like Amazon's/Tarzan's), you can use the following assuming you have PHP 5.2 or newer.

// Get a SimpleXML response back from Tarzan
$s3 = new AmazonS3();
$response = $s3->list_buckets();

// Convert SimpleXML to Array in PHP 5.2.
$response_array = json_decode(json_encode($response));

This will be a standard utility available to all objects in the next major version of Tarzan (CloudFusion 2.5).

Ryan Parman
+1  A: 

one slight addition for for the PHP 5.2 fix.

$response_array = json_decode(json_encode($response),true);
cruzanmo
A: 

I have a simpleXMLobject name container character '-' so when I'm using foreach to loop through its made an error. Anyone have an experienced of it help me pls, tks!!

gacon