代码之家  ›  专栏  ›  技术社区  ›  Wilfred Knievel

使用xpath查找节点的位置

  •  81
  • Wilfred Knievel  · 技术社区  · 16 年前

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

    假设我有以下XML:

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

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

    a/b[.='tsr']
    

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

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

    (但工作要多一点!)

    有可能吗?

    编辑 :忘记提到AM使用.NET 2,所以它是xpath 1.0!


    更新 :结束使用 James Sulak excellent 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 回复  |  直到 16 年前
        1
  •  86
  •   Wayne    13 年前

    尝试:

    count(a/b[.='tsr']/preceding-sibling::*)+1.
    
        2
  •  9
  •   Steven Huwig    16 年前

    您可以使用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>
    
        3
  •  7
  •   user414661    14 年前

    我知道这个职位很古老。但是…

    用nodename替换星号会得到更好的结果

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

    而不是

    count(a/b[.='tsr']/preceding::*)+1.
    
        4
  •  3
  •   Damien    14 年前

    与前面所述的不同,“上一个同级”实际上是要使用的轴,而不是“上一个”它执行完全不同的操作,它选择文档中当前节点开始标记之前的所有内容。(见 http://www.w3schools.com/xpath/xpath_axes.asp )

        5
  •  3
  •   CroWell    9 年前

    如果升级到xpath 2.0,请注意它提供了函数 index-of ,通过以下方式解决问题:

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

    哪里:

    • 第一个参数是搜索顺序
    • 第二个是要搜索的内容
        6
  •  1
  •   Claus Jensen    10 年前

    只是对詹姆斯·苏拉克的回答的一个说明。

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

    count(a/b[.='tsr']/preceding-sibling::*)+number(boolean(a/b[.='tsr']))
    
        7
  •  0
  •   Andrew Cox    16 年前

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

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

    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;
                    }
                }
            }
        }
    }
    
        8
  •  0
  •   geoffc    16 年前

    我做了很多Novell Identity Manager的工作,在这个上下文中,xpath看起来有点不同。

    假设您要查找的值位于名为target的字符串变量中,那么xpath将是:

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

    此外,还指出,为了节省一些字符的空间,还可以使用以下方法:

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

    我还在Novell的酷解决方案上发布了一个更漂亮的版本: Using XPATH to get the position node