Imagine the following XML document:
<root>
<person_data>
<person>
<name>John</name>
<age>35</age>
</person>
<person>
<name>Jim</name>
<age>50</age>
</person>
</person_data>
<locations>
<location>
<name>John</name>
<country>USA</country>
</location>
<location>
<name>Jim</name>
<country>Japan</country>
</location>
</locations>
</root>
I then select the person node for Jim:
XmlNode personNode = doc.SelectSingleNode("//person[name = 'Jim']");
And now from this node with a single XPath select I would like to retrieve Jim's location node. Something like:
XmlNode locationNode = personNode.SelectSingleNode("//location[name = {reference to personNode}/name]");
Since I am selecting based on the personNode it would be handy if I could reference it in the select. Is this possible?.. is the connection there?
Sure I could put in a few extra lines of code and put the name into a variable and use this in the XPath string but that is not what I am asking.
I am not very sure why you want refer location from
personNode
. Since, the name already exists inlocation
node you can very well use the same to get the location node corresponding to 'Jim'.You are not selecting the
location
node based on theperson
node, rather you are selecting it based on the value of the node. The value is just a string and in this case, it can be used to formulate a predicate condition that selects thelocation
node based on the value within ("Jim").Should do it.
I appreciate that your real XML document is more complex than your example, but one thing does strike me about it. It resembles a relational data store containing the following:
person
table with two columns -name
andage
.location
table with two columns -name
andcountry
.name
columns.With that in mind, the XPath becomes obvious. You just select on the primary key value of the table whose data you want.
I know that aJ already proposed that solution, and it was rejected, but if you generalise the idea to the real XML schema, you get this:
In other words:
This is not very efficient, but it should work. The larger the file gets, the slower will this be.
Here is why this is inefficient:
//
" shorthand causes a document-wide scan of all nodes.[]
" predicate runs in a loop, once for each<person>
matched by "//person
".//
" causes a causes a document-wide scan again, this time once for each<person>
.This means you get quadratic O(n²) worst-case performance, which is bad. If there are n
<person>
s and n<location>
s in your document, n x n document wide scans happen. All out of one innocent looking XPath expression.I'd recommend against that approach. A two-step selection (first, find the person, then the location) will perform better.