1

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>
buck1112
  • 504
  • 8
  • 24

2 Answers2

1

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>';
Nigel Ren
  • 56,122
  • 11
  • 43
  • 55
  • Referencing an item from a list of nodes by name should work just fine; SimpleXML is designed to be very forgiving about that. – IMSoP Jan 29 '18 at 09:35
  • Thanks - I just tend to not like relying on when things 'should' happen. One of my biggest problems with PHP and some frameworks is that a lot of things tend to happen by 'magic'. – Nigel Ren Jan 29 '18 at 10:03
1

Although the IndexEntry element is in the http://www.digitalmeasures.com/schema/data-metadata namespace, as denoted by the local prefix dmd:, its attributes have no prefix:

<dmd:IndexEntry indexKey="D" entryKey="Dylan" text="Dylan"/>

Unprefixed elements in this document are in the http://www.digitalmeasures.com/schema/data namespace, as specified in the xmlns= attribute on the root node.

But as discussed on this question, the XML namespace spec says that attributes are never in the default namespace. This puts them, peculiarly, in no namespace at all, so to access them with SimpleXML, you have to select the namespace whose URI is the empty string:

$dmd_fields->IndexEntry->attributes('')->indexKey;
IMSoP
  • 89,526
  • 13
  • 117
  • 169