Search code examples
phpxmlsimplexml

SimpleXML namespaced attributes and value is empty?


I have the following type of XML structure:

<catalog xmlns="http://www.namespace.com">
    <product product-id="test-product">
        <page-attributes>
            <page-title xml:lang="en">test</page-title>
            <page-title xml:lang="de">test2</page-title>
        </page-attributes>
    </product>
</catalog>

I used the following to fetch the product and it's page-title elements:

$xml->registerXPathNamespace('ns', $xml->getNamespaces()[""]);
$xpath = '//ns:product[@product-id="test-product"]';
$product = $xml->xpath($xpath)[0];

foreach ($product->{'page-attributes'}->{'page-title'} as $title) {
    var_dump($title);
    var_dump($title->{"@attributes"});
    var_dump($title->attributes());
}

But I just get:

object(SimpleXMLElement)#4 (0) {
}
object(SimpleXMLElement)#6 (0) {
}
object(SimpleXMLElement)#6 (0) {
}
object(SimpleXMLElement)#6 (0) {
}
object(SimpleXMLElement)#4 (0) {
}
object(SimpleXMLElement)#4 (0) {
}

How do I get the values of the page-title elements (test,test2)? Also how do I get the attributes? The attributes have xml: in front of them. Does that mean just the attributes are in their own namespace?


Solution

  • Two things are wrong with your code:

    • As @MichaelBerkowski mentioned, you need to convert an SimpleXMLElement to string if you attempt to retrieve it's value.

    • You need to specify the namespace xml: if you attempt to retrieve the values of the lang attributes.

    Your code should look like this:

    $xml->registerXPathNamespace('ns', $xml->getNamespaces()[""]);
    
    $xpath = '//ns:product[@product-id="test-product"]';
    $product = $xml->xpath($xpath)[0];
    
    foreach ($product->{'page-attributes'}->{'page-title'} as $title) {
        var_dump((string) $title);
        var_dump((string) $title->attributes('xml', TRUE)['lang']);
    }
    

    Output:

    string(4) "test"
    string(2) "en"
    string(5) "test2"
    string(2) "de"
    

    About the string conversion. Note that if you would attempt to do the following:

    echo "Title: $title";
    

    you won't have to explicitly convert to string since a SimpleXMLElement supports the __toString() method and PHP will convert it automatically to a string - in a such a string context.

    var_dump() cannot assume a string context and therefore it outputs the "real" type of the variable: SimpleXMLElement.