Search code examples
phpxmlxpathsimplexmlxml-namespaces

PHP - Namespace Shift in Child Node in SimpleXML Troubleshooting


I'm working with SimpleXML and XPath in trying to get the value of a child node's ('IndexEntry) attribute ('indexKey'). The node's namespace, I've tested successfully on another node ('Record'). For some reason, this node's attribute ('indexKey') is not returning. I've tried accessing the node, while specifying its namespace, by using the children method.

PHP Code

<?php
$url = "test_bb.xml";


$xml = simplexml_load_file($url);

$xml->registerXPathNamespace('a','http://www.digitalmeasures.com/schema/data');
$xml->registerXPathNamespace('dmd','http://www.digitalmeasures.com/schema/data-metadata');

$xml_report_abbrev_bb = $xml->xpath('//a:Record[@username="john-smith"]');

if($xml_report_abbrev_bb){
    echo '<br>CONTYPE is...'.$xml_report_abbrev_bb[0]->INTELLCONT->CONTYPE;
    echo '<br>termId is...'.$xml_report_abbrev_bb[0]['termId'].'<br>';
    echo '<br>surveyId is...'.$xml_report_abbrev_bb[0]->attributes('dmd',true)['surveyId'].'<br>';

//below - I've tried different methods of accessing the IndexEntry node...
    $dmd_fields = $xml_report_abbrev_bb[0]->children('dmd',true);
    echo '<br>dmd:IndexEntry is...'.$dmd_fields->IndexEntry['indexKey'].'<br>';

    echo '<br>dmd:IndexEntry is...'.$xml_report_abbrev_bb[0]->children('dmd',true)->IndexEntry['indexKey'].'<br>';

    //echo '<br>dmd:IndexEntry is...'.$xml_report_abbrev_bb[0]->IndexEntry('dmd',true)['indexKey'].'<br>';

    //echo '<br>dmd:IndexEntry is...'.$xml_report_abbrev_bb[0]->xpath('/dmd:indexEntry[@indexKey]')[0].'<br>';


} else {
    echo 'XPath query failed b';  
}

?>

XML ('test_bb.xml')

<?xml version="1.0" encoding="UTF-8"?>
<Data xmlns="http://www.digitalmeasures.com/schema/data" xmlns:dmd="http://www.digitalmeasures.com/schema/data-metadata" dmd:date="2012-01-03">
    <Record userId="148" username="john-smith" termId="4" dmd:surveyId="12">
        <dmd:IndexEntry indexKey="D" entryKey="Dylan" text="Dylan"/>
        <INTELLCONT id="14" dmd:originalSource="54TEX" dmd:lastModified="2017-04-18T10:54:29" dmd:startDate="2011-01-01" dmd:endDate="2011-12-31">
            <CONTYPE>Sales Tools</CONTYPE>
            <CONTYPEOTHER>Sales History</CONTYPEOTHER>
            </INTELLCONT>
    </Record>
</Data>

Solution

  • In the line

    $dmd_fields = $xml_report_abbrev_bb[0]->children('dmd', true);
    

    This will mean that $dmd_fields will be a list of nodes, even though there is only one node in the list - so use $dmd_fields[0] to reference the <dmd:IndexEntry> element. As this is the IndexEntry element, just using this and the list off attributes for that element you can do...

    echo '<br>dmd:IndexEntry is...'.$dmd_fields[0]->attributes()['indexKey'].'<br>';