2

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
            )
    )
)

1 Answer 1

2

//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'));
Sign up to request clarification or add additional context in comments.

1 Comment

So the first result from xpath doesn't then confine me to only that node in the xml doc? I am still working with the main, original document? I thought $value[0] would then only contain and have access to that dataset element.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.