Search code examples
phpxmlnested-loops

Getting multiple values with specific attributes in nested xml with php


I feel like this should be easy, but for the love of it I cannot get it right. I've read and tested for hours, trying different approaches I have found on the interwebs, both with simpleXML and PHP XML DOM, but none of them works just the way I need.

I got somewhat close, after tweaking and combining a few answers (that I cannot even find the way back to cause I've been through so many of them here), but not entirely correct.

My code:

$xml = simplexml_load_file(all_objects.xml");

$image = $xml->xpath('/objects/object/images/image');
foreach($image as $node) {
    $id = (string) $node->field[0];
    $url = (string) $node->field[4];
    echo $id . " : " . $url . "<br>";
}

But instead of using the key/number they appear [4] in, I would like to target using the field name attribute, e.g. "id" and "image_url", as they are not always in this order.

Something like this:

$id = (string) $node->field["id"];

But it does not work, I tried with field->attribtues()->id too, but no luck.

The xml:

<objects>
    <object>
        <field name="id">1055</field>
        <field name="title">example object</field>
        <images>
            <image number="1">
                <field name="id">55</field>
                <field name="version">1</field>
                <field name="image_url_small">http://example.com/image-small.jpg</field>
                <field name="image_url_medium">http://example.com/image-medium.jpg</field>
                <field name="image_url_big">http://example.com/image-big.jpg</field>
                <field name="image_url_original">http://example.com/image.jpg</field>
            </image>
            <image number="2">
                <field name="id">56</field>
                <field name="version">2</field>
                <field name="image_url">http://example.com/image2.jpg</field>
            </image>
            <image number="3">...</image>
            ...
            <image number="25">...</image>
        </images>
    </object>
    <object>...</object>
    <object>...</object>
</objects>

I would really appreciate any help/guidance! I am losing my mind over this.


Solution

  • You can use XPath to get child element with certain attribute value :

    foreach($image as $node) {
        $id = (string) $node->xpath('field[@name="id"]')[0];
        $url = (string) $node->xpath('field[@name="image_url_big"]')[0];
        echo $id . " : " . $url . "<br>";
    }
    

    eval.in demo

    output :

    55 : http://example.com/image-big.jpg
    56 :
    :
    :