mmdfan
mmdfan

Reputation: 346

How to get the text value from an element based on its sibling attribute value?

Example xml:

<root>
    <ns1:agent ns2:about="a3">
        <ns2:name xml:lang="en">Helen</ns2:name>
        <ns2:age>26</ns2:age>
    </ns1:agent>
    <ns1:agent ns2:about="a1">
        <ns2:name xml:lang="en">John</ns2:name>
        <ns2:age>26</ns2:age>
    </ns1:agent>
    <ns1:agent ns2:about="a2">
        <ns2:name xml:lang="en">Mike</ns2:name>
        <ns2:age>30</ns2:age>
    </ns1:agent>
    ...
    <!-- More ns1:agent nodes -->
    ...
    <ns3:person ns2:id="a1"/>
    <ns3:person ns2:id="a2"/>
    <ns3:person ns2:id="a3"/>
    ...
    <!-- More ns3:person nodes -->
    ...
</root>

So how to get the text value of the agent/name element based on its about attribute starting from person element, using XPath?

Edit: XPath expression will be used in a loop, for each ns3:person node, so I don't know the specific id attribute value beforehand.

Upvotes: 1

Views: 156

Answers (2)

kjhughes
kjhughes

Reputation: 111491

Assuming you've properly declared namespace prefixes ns1, ns2, and ns3, this XPath,

//ns3:person[@ns2:id = "a1"]/preceding-sibling::ns1:agent[1]/ns2:name

will select the name of the agent immediately preceding the identified person.

If you need help declaring the XML namespace prefixes, see How does XPath deal with XML namespaces?


Update based on OP's comment:

In my original xml document, the agent node is not immediately preceding the person node. I will be running the expression in a loop, for each person node. Sorry for the confusion, I have edited the example and the question so it is more clear what I need.

And in the edited question:

Edit: XPath expression will be used in a loop, for each ns3:person node, so I don't know the specific id attribute value beforehand.

So in your loop simply bind a variable, say $id, to the current ns3:person/@n2:id and then test it in the XPath:

//ns1:agent[@ns2:about = $id]/ns2:name

See also How to pass variable parameter into XPath expression?

Upvotes: 1

Jack Fleeting
Jack Fleeting

Reputation: 24930

If I understand your question correctly, you are looking for an xpath expression like this:

    //ns1:agent[@ns2:about=//ns3:person/@ns2:id]/ns2:name

To test it, I would change your ns3:persons nodes in your sample xml from

<ns3:person ns2:id="a1"/>
<ns3:person ns2:id="a2"/>
<ns3:person ns2:id="a3"/>

to

<ns3:person ns2:id="a7"/>
<ns3:person ns2:id="a2"/>
<ns3:person ns2:id="a9"/>

so that only one random ns1:agent corresponds to one random ns3:person. If you do that, that xpath expression would select Mike as the target name.

Upvotes: 1

Related Questions