使用xpath查找节点的位置

时间:2008-10-22 15:51:21

标签: xpath

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

说我有以下xml:

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

我可以使用以下xpath查询来选择第三个&lt; b&gt;节点(&lt; b&gt; tsr&lt; / b&gt;):

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

8 个答案:

答案 0 :(得分:90)

尝试:

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

答案 1 :(得分:9)

您可以使用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>

答案 2 :(得分:7)

我意识到这个帖子很古老......但是......

用节点代替星号会给你带来更好的效果

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

而不是

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

答案 3 :(得分:3)

与先前描述的'previous-sibling'不同,它实际上是要使用的轴,而不是“先行”,它完全不同,它选择文档中当前节点的开始标记之前的所有内容。 (见http://www.w3schools.com/xpath/xpath_axes.asp

答案 4 :(得分:3)

如果您曾升级到XPath 2.0,请注意它提供了函数index-of,它以这种方式解决了问题:

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

其中:

  • 第一个参数是搜索序列
  • 第二个是搜索内容

答案 5 :(得分:1)

简要回答James Sulak的答案。

如果您想要考虑该节点可能不存在并且想要将其保持为纯XPATH,那么尝试以下将在节点不存在时返回0。

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

答案 6 :(得分:0)

问题是如果没有上下文,节点的位置并不重要。

以下代码将为您提供节点在其父子节点中的位置

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

答案 7 :(得分:0)

我做了很多Novell Identity Manager的事情,在这种情况下XPATH看起来有点不同。

假设您要查找的值是一个名为TARGET的字符串变量,那么XPATH将是:

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

另外有人指出,为了节省一些空间字符,以下内容也可以使用:

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

我还在Novell的Cool Solutions上发布了一个更漂亮的版本:Using XPATH to get the position node