Reputation: 35
I have searched for this and the answers I find seem to say what I thought I understand. Obviously I am missing something. I am confused at the results from the xPath query. I have simplified my problem for a test case to post here.
My real xml has several dataset nodes at different depths. Ultimately, I want to get every dataset element with a given label and then loop over that and get the field values (at different locations (or depths) so I think I need xpath). I can use xpath to get the dataset elements that I want successfully. However, when I then run xpath on that result object, it gets me the fields I want and all the other fields too. I can't figure out why it isn't only returning field1, field2, and field3. When I print_r($value[0]), it shows only the fields I want. But, when I run xpath on $value[0], it returns all fields in the xml doc.
Sample XML
<myxml>
<dataset label="wanteddata" label2="anotherlabel">
<dataitem>
<textdata>
<field label="label1">field1</field>
<field label="label2">field2</field>
<field label="label3">field3</field>
</textdata>
</dataitem>
</dataset>
<dataset label="unwanteddata" label2="unwantedanotherlabel">
<dataitem>
<textdata>
<field label="label4">field4</field>
<field label="label5">field5</field>
<field label="label6">field6</field>
</textdata>
</dataitem>
</dataset>
</myxml>
Here is the test code.
$xmlstring = file_get_contents('simplexml_test.xml');
$xml = simplexml_load_string($xmlstring);
if ($xml === false) {
throw new Exception("Failed to load");
}
$value = $xml->xpath('//dataset[@label="wanteddata"]');
print_r($value[0]->xpath('//field'));
Code Output:
Array
(
[0] => SimpleXMLElement Object
(
[@attributes] => Array
(
[label] => label1
)
)
[1] => SimpleXMLElement Object
(
[@attributes] => Array
(
[label] => label2
)
)
[2] => SimpleXMLElement Object
(
[@attributes] => Array
(
[label] => label3
)
)
[3] => SimpleXMLElement Object
(
[@attributes] => Array
(
[label] => label4
)
)
[4] => SimpleXMLElement Object
(
[@attributes] => Array
(
[label] => label5
)
)
[5] => SimpleXMLElement Object
(
[@attributes] => Array
(
[label] => label6
)
)
)
Upvotes: 2
Views: 1751
Reputation: 89285
//field
selects all <field>
elements within the entire XML document regardless of the context node from which you call that XPath. To make the XPath heed the context node, you need to add a dot (.
) at the beginning of the XPath. In XPath, (.
) references current context node :
print_r($value[0]->xpath('.//field'));
Upvotes: 2