使用XPath查找节点的位置

使用XPath查找节点的位置,xpath,Xpath,有人知道如何使用XPath获取节点的位置吗 假设我有以下xml: <a> <b>zyx</b> <b>wvu</b> <b>tsr</b> <b>qpo</b> </a> 这很好,但我想返回该节点的顺序位置,类似于: a/b[.='tsr']/position() 但要更有效一点 有可能吗 编辑:忘了提到我在使用.NET2,所以它是XPath

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

假设我有以下xml:

<a>
    <b>zyx</b>
    <b>wvu</b>
    <b>tsr</b>
    <b>qpo</b>
</a>
这很好,但我想返回该节点的顺序位置,类似于:

a/b[.='tsr']/position()
但要更有效一点

有可能吗

编辑:忘了提到我在使用.NET2,所以它是XPath1.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);
}

可以使用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>
尝试:


问题是,如果没有上下文,节点的位置没有多大意义

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

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

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

假设您要查找的值位于名为TARGET的字符串变量中,则XPATH将为:

count(attr/value[.='$TARGET']/preceding-sibling::*)+1
此外,有人指出,为了节省几个字符的空间,以下内容也可以:

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

我还在Novell's Cool Solutions上发布了一个更漂亮的版本:

与前面所说的不同,“前面的兄弟姐妹”实际上是要使用的轴,而不是“前面的”,它做一些完全不同的事情,它选择文档中当前节点开始标记之前的所有内容。见

我意识到这篇文章很古老。。但是

将星号替换为节点名称将获得更好的结果

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

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

只是詹姆斯·苏拉克对答案的一个注释

如果您想考虑到该节点可能不存在,并希望将其保留为纯XPATH,那么请尝试以下操作,如果该节点不存在,则返回0

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

如果您曾经升级到XPath 2.0,请注意它提供了函数,它通过以下方式解决了问题:

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

第一个参数是用于搜索的序列 第二个是搜索什么
'因为我使用的是.net&要么是它,要么是我无法处理我使用的电源:int position=doc.SelectNodesa/b[.='tsr']/前面的兄弟姐妹::b.Count+1;如果位置>1 | |文档选择SingleNodeA/b[.='tsr']!=null//检查节点是否实际存在{//Do magic here}在零索引语言中,您不需要+1,因此现在不是XPath查找程序,而是C查找程序。不包括祖先节点。在细节上不要相信学校!但我同意。。。虽然previous::在这种情况下起作用,因为除了a祖先之外,相关b元素之前没有其他元素,所以它比前面的兄弟元素更脆弱。OTOH,OP没有告诉我们他想知道什么上下文中的位置,因此前面的::可能是正确的。应该注意的是,这只适用于XPath 2+。下面的任何内容都必须使用“怪异”计数功能。@Dan,它在原始文档的链接中被注明,添加了明确的通知,谢谢!一个小例子,在XML文档中原位获取元素France的位置:索引//country\u name/common\u name,//country\u name/common\u name[text=France]请尽量不要在问题中发布答案->最好将其作为答案发布,然后可能从问题链接到它。
count(a/b[.='tsr']/preceding-sibling::*)+number(boolean(a/b[.='tsr']))
index-of(//b, //b[.='tsr'])