使用xpath查找节点的位置

任何人都知道如何获得使用xpath节点的位置?

说我有以下的XML:

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

我可以使用下面的xpath查询来select第三个<b>节点(<b> tsr </ b>):

 a/b[.='tsr'] 

哪一个都好,但我想返回该节点的序号位置,如下所示:

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

(但多一点工作!)

这甚至有可能吗?

编辑 :忘了提及我使用.net 2,所以它的xpath 1.0!


更新 :结束了使用詹姆斯苏拉克的优秀答案 。 对于那些感兴趣的是我在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); } 

尝试:

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

你可以用XSLT来做到这一点,但我不确定直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> 

我意识到,这个职位是古老的..但..

用nodenamereplace星号会给你更好的结果

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

代替

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

不同于前面说过的“先兄弟”实际上是使用的轴,而不是完全不同的“之前”,它select文档中当前节点的开始标签之前的所有内容。 (见http://www.w3schools.com/xpath/xpath_axes.asp

问题在于,没有上下文,节点的位置并不意味着太多。

下面的代码将给你在其父节点的父节点的位置

 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; } } } } } 

请注意James Sulak所做的答案。

如果要考虑节点可能不存在并且希望保持纯粹的XPATH,则尝试以下操作,如果该节点不存在,则返回0。

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

如果你升级到XPath 2.0,注意它提供了函数索引 ,它解决了这个问题:

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

哪里:

  • 第一个参数是search的顺序
  • 第二是什么search

我做了很多Novell Identity Manager的工作,XPATH在这方面看起来有些不同。

假设你正在查找的值是一个名为TARGET的stringvariables,那么XPATH将是:

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

此外,有人指出,为了节省一些空间的字符,下面的工作也是如此:

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

我还在Novell的Cool Solutions上发布了一个更漂亮的版本: 使用XPATH获取位置节点