1

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.

mmdfan
  • 346
  • 2
  • 12
  • 1
    Your question isn't clear: what exactly do you mean by "based on its about attribute starting from person element"? – Jack Fleeting May 30 '20 at 15:02
  • @JackFleeting I meant I need an XPath expression that starts from person element and gets 'John'. – mmdfan May 30 '20 at 15:17
  • In the original xml I have multiple "person" nodes and multiple corresponding "agent" nodes containing some data about the person. – mmdfan May 30 '20 at 15:19

2 Answers2

1

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?

kjhughes
  • 106,133
  • 27
  • 181
  • 240
  • 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. Thanks sir! – mmdfan Jun 01 '20 at 07:48
1

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.

Jack Fleeting
  • 24,385
  • 6
  • 23
  • 45