2008-10-22 175 views
79

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

说我有下面的XML:

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

我可以使用下面的XPath查询以选择第三<b>节点(<b> TSR </B >):

a/b[.='tsr'] 

这是一切都很好,但我想返回该节点的序号位置,如:

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

(但多一点的工作!)

它甚至有可能?

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


更新:结束了使用James Sulakexcellent answer。对于那些有兴趣,这里是我的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); 
} 

回答

84

尝试:

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

'因为我正在使用.net及其或者我无法处理我去的权力:int position = doc.SelectNodes(“a/b [。='tsr']/preceding-Sibling :: b “).Count + 1; if(position> 1 || doc.SelectSingleNode(“a/b [。='tsr']”)!= null)//检查实际存在的节点{//在这里做魔术} – 2008-10-24 09:52:59

+0

以零索引语言, t需要+1 – 2017-11-23 14:50:30

8

为此,您可以使用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> 
1

的问题是,该节点的位置没有多大的意义不利用上下文。

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

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

所以现在不是一个真正的XPath查找器,而是一个C#查找器。 – jamesh 2008-10-29 13:03:12

0

我做了很多的Novell Identity Manager已的东西,和XPath在这方面显得有些不同。

假设你正在寻找的是一个字符串变量,称为目标的价值,那么XPATH将是:

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

另外有人指出,以节省空间几个大字,下面的以及工作:

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

我还张贴这在Novell的超酷解决方案更漂亮的版本:Using XPATH to get the position node

3

不像规定上10狡猾的“兄弟姐妹”实际上是使用的轴,而不是“前面的”,它做了完全不同的事情,它选择文档中当前节点的开始标记之前的所有内容。 (见http://www.w3schools.com/xpath/xpath_axes.asp

+4

不包括祖先节点。不要相信w3schools的细节! 但我同意......尽管前面的::在这种情况下工作,因为在除了祖先之外的相关b元素之前没有元素,它比前面的兄弟姐妹更脆弱。 OTOH,OP没有告诉我们他想知道内部位置的情况,所以潜在的前面::可能是正确的。 – LarsH 2010-08-18 18:44:32

5

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

replace'ing与节点名的星号会带来更好的效果

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

,而不是

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

只是说明由詹姆斯·苏拉克做了回答。

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

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

如果你升级到XPath 2.0中,请注意,它提供的功能index-of,它解决的问题是这样的:

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

其中:

  • 第一个参数是序列搜索
  • 第二是要搜索什么