Search code examples
xmlxpathpredicate

XML Parsing with xPath - predicate containing relative path


Have the following XML:

<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://example.com/importer" version="1.0">
    <metadata>
        <provider>company</provider>
    </metadata>
    <assets>
        <asset type="title">
            <metadata>
                <original_spoken_locale>es-US</original_spoken_locale>
                <default_metadata_locale>en-US</default_metadata_locale>
                <country_of_origin>US</country_of_origin>
                <series>
                    <id>2845SD</id>
                    <locale_data lang="en-US">
                        <title>New Movie</title>
                        <synopsis_short>Short Description</synopsis_short>
                        <synopsis_medium>Medium Description</synopsis_medium>
                        <synopsis_long>Long Description</synopsis_long>
                    </locale_data>
                </series>
                <season>
                    <container_id>4345SD</container_id>
                    <season_display_number>2</season_display_number>
                    <locale_data lang="en-US">
                        <title>Season 2 Title</title>
                        <synopsis_short>Season 2 Short Description</synopsis_short>
                        <synopsis_medium>Season 2 Medium Description</synopsis_medium>
                        <synopsis_long>Season 2 Long Description</synopsis_long>
                    </locale_data>
                </season>
            </metadata>
        </asset>
    </assets>
</package>

Then I obtain xpath object:

$xmlDoc = new \DOMDocument();
$xmlDoc->loadXML($xml_string);
$xpath = new \DOMXpath($xmlDoc);
$xpath->registerNamespace("m", "http://example.com/importer");

Working xpath query:

$xpath->query("//m:package/m:metadata/m:provider")
=> DOMNodeList {#4696
     +length: 1,
   }

$xpath->query("//m:package/m:assets/m:asset/m:metadata/m:season/m:locale_data[@lang='en-US']/m:title")
=> DOMNodeList {#4722
     +length: 1,
   }

What I want is the lang value of locale_data node to match the value of default_metadata_locale. The following does NOT work:

$xpath->query("//m:package/m:assets/m:asset/m:metadata/m:season/m:locale_data[@lang='../../m:default_metadata_locale']/m:title")
=> DOMNodeList {#4720
     +length: 0,
   }

Have also tried:

$xpath->query("//m:package/m:assets/m:asset/m:metadata/m:season/m:locale_data[@lang='./../../m:default_metadata_locale']/m:title")

This is PHP code, but should not matter as xpath is universal query language. Any guidance would be appreciated.


Solution

  • I'm still not sure about what you are after, but try this xpath expression (based strictly on your xml above) and see if it works:

    //package/assets/asset/metadata/season/locale_data[@lang=../../default_metadata_locale]/title