Search code examples
phpxmlsoapsimplexml

Pulling SimpleXML Attributes with Namespaces


I am attempting to display multiple records from a SOAP API. My call is working correctly and this is the XML response as expected:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Body>
        <GetDataResponse xmlns="urn:com:esi911:webeoc7:api:1.0">
            <GetDataResult>
                <data>
                    <record dataid="6" county="Fayette County" title="Title goes here" description="Description goes here." status="Inactive" />
                    <record dataid="5" county="Caldwell County" title="Title goes here" description="Description goes here." status="Inactive" />
                    <record dataid="4" county="Burnet County" title="Title goes here" description="Description goes here." status="Active" />
                    <record dataid="2" county="Blanco County" title="Title goes here" description="Description goes here." status="Active" />
                    <record dataid="1" county="Bastrop County" title="Title goes here" description="Description goes here." status="Active" />
                </data>
            </GetDataResult>
        </GetDataResponse>
    </soap:Body>
</soap:Envelope>

For now, I would just like to show the first of those records and its attributes on my webpage. I am throwing this response into SimpleXML and trying to grab those multiple attributes to display. Here is what I've attempted so far based on various other StackOverflow examples, but none really matched my exact XML response structure above either:

$xml = simplexml_load_string($response);
$response = $xml->xpath("//soap:Body/*")[0];
$result = $response->children("urn:com:esi911:webeoc7:api:1.0");
echo (string) $result->data->record[0]->attributes()->dataid;

I am not getting any specific errors ever. It's just always blank, nothing is displayed.

Eventually, I would need to loop through those records to display them all or store them into their own array for other uses later, but I cannot seem to even echo anything from the code above. I'm sure it has something to do with the multiple namespaces perhaps? Or just a basic typo somewhere?

Any advice with this XML response would be great. Thank you!


Solution

  • You could register the namespace first and get the desired results with a single xpath query:

    $xml = simplexml_load_string($response);
    $xml->registerXPathNamespace('urn', 'urn:com:esi911:webeoc7:api:1.0');
    $records = $xml->xpath('//urn:record');
    
    echo (string)$records[0]->attributes()->dataid;
    

    Demo: https://3v4l.org/f8faC

    Note: you could be more accurate and use something like //urn:GetDataResult/urn:data/urn:record (instead of the shorter //urn:record) as the XPath query, in case there can be records at another place within the XML you receive.