使用 XPath 查找节点的位置

有人知道如何使用 XPath 获取节点的位置吗?

假设我有以下 xml:

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

我可以使用以下 xpath 查询来选择第三个 < b > 节点(< b > tsr ) :

a/b[.='tsr']

这很好,但是我想要 返回这个节点的序号位置,比如:

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

(但要更努力一点!)

这有可能吗?

编辑 : 忘了提到我正在使用. net 2,因此它是 xpath 1.0!


更新 : 最终使用了 詹姆斯 · 苏拉克答得好:

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);
}
121565 次浏览

You can do this with XSLT but I'm not sure about straight 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>

Try:

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

The problem is that the position of the node doesn't mean much without a context.

The following code will give you the location of the node in its 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;
}
}
}
}
}

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

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

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

Additionally it was pointed out that to save a few characters of space, the following would work as well:

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

I also posted a prettier version of this at Novell's Cool Solutions: Using XPATH to get the position node

Unlike stated previously 'preceding-sibling' is really the axis to use, not 'preceding' which does something completely different, it selects everything in the document that is before the start tag of the current node. (see http://www.w3schools.com/xpath/xpath_axes.asp)

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

replace'ing the asterisk with the nodename would give you better results

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

instead of

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

Just a note to the answer done by James Sulak.

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

count(a/b[.='tsr']/preceding-sibling::*)+number(boolean(a/b[.='tsr']))

If you ever upgrade to XPath 2.0, note that it provides function index-of, it solves problem this way:

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

Where:

  • 1st parameter is sequence for searching
  • 2nd is what to search