Search code examples
phpxmlxpathsimplexml

SimpleXML: How to parse nodenames including dots with xpath query


I have to parse the following XML:

<BMECAT version="2005" xmlns="http://www.bmecat.org/bmecat/2005fd">
    <T_NEW_CATALOG prev_version="0">
        <PRODUCT>
            <NAME>Test</NAME>
            <USER_DEFINED_EXTENSIONS>
                <UDX.VENDOR.ATTRIBUTE lang="de">German</UDX.VENDOR.ATTRIBUTE>
                <UDX.VENDOR.ATTRIBUTE lang="en">English</UDX.VENDOR.ATTRIBUTE>
            </USER_DEFINED_EXTENSIONS>
        </PRODUCT>
    </T_NEW_CATALOG>
</BMECAT>

I need to get the value "German" via xpath. Everything I have tried so far didn't work so I need some help. I think the problem is that the tagname includes dots. I have found no way to escape the xpath expression.


Solution

  • The XML you show cannot be parsed because it is malformed (USER_DEFINED_EXTENSIONS is not closed properly). Assuming well-formed input, you could use DOMDocument instead of SimpleXML:

    <?php
    $xml = <<<'XML'
    <BMECAT version="2005" xmlns="http://www.bmecat.org/bmecat/2005fd">
        <T_NEW_CATALOG prev_version="0">
            <PRODUCT>
                <NAME>Test</NAME>
                <USER_DEFINED_EXTENSIONS>
                    <UDX.VENDOR.ATTRIBUTE lang="de">German</UDX.VENDOR.ATTRIBUTE>
                    <UDX.VENDOR.ATTRIBUTE lang="en">English</UDX.VENDOR.ATTRIBUTE>
                </USER_DEFINED_EXTENSIONS>
            </PRODUCT>
        </T_NEW_CATALOG>
    </BMECAT>
    XML;
    
    $dom = new DOMDocument();
    $dom->loadXML($xml);
    
    $xpath = new DOMXPath($dom);
    $xpath->registerNamespace("bme",
            "http://www.bmecat.org/bmecat/2005fd");
    
    $expression = 'string(
      /bme:BMECAT
      /bme:T_NEW_CATALOG
      /bme:PRODUCT
      /bme:USER_DEFINED_EXTENSIONS
      /bme:UDX.VENDOR.ATTRIBUTE[@lang = "de"]
    )';
    
    var_dump($xpath->evaluate($expression));
    

    And the result will be

    German
    

    If you need to use SimpleXML, you really need to show your current PHP code.