Search code examples
phpcurlsimplexml

Problem with SimpleXMLElement and XML data from mobile.de


I try to fetch xml data from mobile.de to prepare my plugins data. The returned XML looks as follows:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <reference:reference xmlns:seller="http://services.mobile.de/schema   /seller"
                     xmlns:ad="http://services.mobile.de/schema/ad"
                     xmlns:financing="http://services.mobile.de/schema/common/financing-1.0"
                     xmlns:reference="http://services.mobile.de/schema/reference"
                     xmlns:resource="http://services.mobile.de/schema/resource">
    <reference:item key="Cabrio" url="https://services.mobile.de/refdata/classes/Car/categories/Cabrio">
        <resource:local-description xml-lang="en">Cabriolet / Roadster</resource:local-description>
    </reference:item>
    <reference:item key="EstateCar" url="https://services.mobile.de/refdata/classes/Car/categories/EstateCar">
        <resource:local-description xml-lang="en">Estate Car</resource:local-description>
    </reference:item>
    <reference:item key="Limousine" url="https://services.mobile.de/refdata/classes/Car/categories/Limousine">
        <resource:local-description xml-lang="en">Saloon</resource:local-description>
    </reference:item>
    <reference:item key="OffRoad" url="https://services.mobile.de/refdata/classes/Car/categories/OffRoad">
        <resource:local-description xml-lang="en">SUV/Off-road Vehicle/Pickup Truck</resource:local-description>
    </reference:item>
    <reference:item key="SmallCar" url="https://services.mobile.de/refdata/classes/Car/categories/SmallCar">
        <resource:local-description xml-lang="en">Small Car</resource:local-description>
    </reference:item>
    <reference:item key="SportsCar" url="https://services.mobile.de/refdata/classes/Car/categories/SportsCar">
        <resource:local-description xml-lang="en">Sports Car/Coupe</resource:local-description>
    </reference:item>
    <reference:item key="Van" url="https://services.mobile.de/refdata/classes/Car/categories/Van">
        <resource:local-description xml-lang="en">Van/Minibus</resource:local-description>
    </reference:item>
    <reference:item key="OtherCar" url="https://services.mobile.de/refdata/classes/Car/categories/OtherCar">
        <resource:local-description xml-lang="en">Other</resource:local-description>
    </reference:item>
</reference:reference>

I tried to iterate trough the nodes but it seems like SimpleXML can´t parse this xml.

Here is my php code:

public function getReferenceXML($url) {
        //url e.g : https://services.mobile.de/refdata/classes/Car/categories

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_FAILONERROR, 1);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_URL, $url);

        $data = htmlspecialchars_decode(curl_exec($ch));
        curl_close($ch);

        $file = EAZY_CLASSIC_CARS_ROOT_DIR . basename($url) . '.xml';

        if (file_exists($file)) {
            unlink($file);
        }

        file_put_contents($file, $data);

        $xml = simplexml_load_file($file);

        echo $xml->count();

        echo '</br>';

        print_r($xml->getNamespaces());

        die();
        //return $xml;
    }

This is the output of the echo and print_r call :

0
Array ( [reference] => http://services.mobile.de/schema/reference ) 

Do i need to set a specific namespace on the SimpleXML Object ??

I'm grateful for any answer, because I'm really getting stuck ...

i need the key value of reference:item and the resource:local-description value


Solution

  • One option could be using xpath and using the namespace in the query and loop through the results:

    /reference:reference/reference:item
    

    And for every item get the first entry for the returned array using this query

    ./resource:local-description
    

    Note that the objects are of type SimpleXMLElement and you have to use __toString() or cast them to a (string) to get the string content

    For example:

    foreach($xml->xpath("/reference:reference/reference:item") as $item) {
        $key = (string)$item->attributes()["key"];
        $description = (string)$item->xpath("./resource:local-description")[0];
        echo "Key: " . $key . PHP_EOL;
        echo "Description " . $description . PHP_EOL;
        echo PHP_EOL;
    }
    

    Output

    Key: Cabrio
    Description Cabriolet / Roadster
    
    Key: EstateCar
    Description Estate Car
    
    Key: Limousine
    Description Saloon
    
    Key: OffRoad
    Description SUV/Off-road Vehicle/Pickup Truck
    
    Key: SmallCar
    Description Small Car
    
    Key: SportsCar
    Description Sports Car/Coupe
    
    Key: Van
    Description Van/Minibus
    
    Key: OtherCar
    Description Other
    

    Php demo