Find node position using xpath

Does anyone know how to get node position using xpath?

Let's say I have the following xml:

<a> <b>zyx</b> <b>wvu</b> <b>tsr</b> <b>qpo</b> </a> 

I can use the following xpath request to select the third <b> node (<b> tsr </b>):

 a/b[.='tsr'] 

That all is well and good, but I want to return the ordinal position of this node, something like:

 a/b[.='tsr']/position() 

(but a little more work!)

Is it possible?

edit : Forgot to mention that I am using .net 2, so it is xpath 1.0!




Update : Finished with the help of James Sulak a great answer . For those interested here, my implementation in C #:

 int position = doc.SelectNodes("a/b[.='tsr']/preceding-sibling::b").Count + 1; // Check the node actually exists if (position > 1 || doc.SelectSingleNode("a/b[.='tsr']") != null) { Console.WriteLine("Found at position = {0}", position); } 
+78
xpath
Oct 22 '08 at 15:51
source share
8 answers

Try:

 count(a/b[.='tsr']/preceding-sibling::*)+1. 
+82
Oct 22 '08 at 18:46
source share

You can do this with XSLT, but I'm not sure about direct XPath.

 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes"/> <xsl:template match="a/*[text()='tsr']"> <xsl:number value-of="position()"/> </xsl:template> <xsl:template match="text()"/> </xsl:stylesheet> 
+8
Oct 22 '08 at 16:39
source share

I understand that the post is ancient .. but ..

replacing asterisk with nodename will give you better results

 count(a/b[.='tsr']/preceding::a)+1. 

instead

 count(a/b[.='tsr']/preceding::*)+1. 
+5
Aug 09 2018-10-10T00:
source share

Unlike the previous “previous marriage”, it is actually an axis, not a “previous” one, which does something completely different, it selects everything in the document that is located before the start of the current node tag. (see http://www.w3schools.com/xpath/xpath_axes.asp )

+3
Aug 04 '10 at 20:57
source share

The problem is that the position of the node does not really matter without context.

The following code will provide you with the location of the node in the parent child nodes

 using System; using System.Xml; public class XpathFinder { public static void Main(string[] args) { XmlDocument xmldoc = new XmlDocument(); xmldoc.Load(args[0]); foreach ( XmlNode xn in xmldoc.SelectNodes(args[1]) ) { for (int i = 0; i < xn.ParentNode.ChildNodes.Count; i++) { if ( xn.ParentNode.ChildNodes[i].Equals( xn ) ) { Console.Out.WriteLine( i ); break; } } } } } 
+1
Oct 23 '08 at 8:20
source share

Just a note on the answer made by James Sulak.

If you want to take into account that the node may not exist and want to keep it just XPATH, try the following, which will return 0 if the node does not exist.

 count(a/b[.='tsr']/preceding-sibling::*)+number(boolean(a/b[.='tsr'])) 
+1
Nov 27 '14 at 2:35
source share

If you are ever upgrading to XPath 2.0, note that it provides an index-of function, it solves the problem as follows:

 index-of(//b, //b[.='tsr']) 

Where:

  • 1st parameter is the search sequence
  • 2nd is what to look for
+1
Sep 21 '15 at 16:14
source share

I do a lot of Novell Identity Manager stuff, and XPATH looks a little different in this context.

Suppose the value you are looking for is in a string variable called TARGET, then XPATH will be:

 count(attr/value[.='$TARGET']/preceding-sibling::*)+1 

In addition, it was pointed out that the following would work to save multiple space characters:

 count(attr/value[.='$TARGET']/preceding::*) + 1 

I also posted a more beautiful version of this in Novell Cool Solutions: Using XPATH to get node position

0
Nov 12 '08 at 20:07
source share



All Articles