ChatGPT解决这个技术问题 Extra ChatGPT

使用 XPath 查找节点的位置

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

假设我有以下 xml:

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

我可以使用以下 xpath 查询来选择第三个 节点 (tsr):

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);
}
请尽量不要在问题中发布答案->最好将其发布为答案,然后可能从问题中链接到它。

W
Wayne

尝试:

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

'因为我正在使用 .net & 或者我无法处理我使用的功能:int position = doc.SelectNodes("a/b[.='tsr']/preceding-Sibling::b") .计数+1; if (position > 1 || doc.SelectSingleNode("a/b[.='tsr']") != null) // 检查节点是否存在 { // 在这里变魔术 }
在零索引语言中,您不需要 +1
如果没有匹配,则 count 返回 0,但 +1 意味着这将始终等于 1。因此,无论您使用什么字符串,无论它是否匹配,都将始终返回 1 - 这个答案解决了这个问题问题stackoverflow.com/a/27173072/1798234
S
Steven Huwig

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

u
user414661

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

用节点名替换星号会给你更好的结果

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

代替

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

C
CroWell

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

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

在哪里:

第一个参数是搜索顺序

第二是搜索什么


应该注意的是,这只适用于 XPath 2+。低于此值的任何内容都必须使用“奇怪的”计数功能。
@Dan,在原始文档的链接中注明,添加了明确的通知,谢谢!
一个现场小例子(获取元素 France 在 XML 文档中的位置): index-of(//country_name/common_name, //country_name/common_name[text()="France"])
D
Damien

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


不包括祖先节点。不要相信 w3schools 的细节!但我同意......虽然 before:: 在这种情况下有效,因为除了 a 祖先之外,相关 b 元素之前没有任何元素,它比前兄弟更脆弱。 OTOH,OP没有告诉我们他想知道其中的位置的上下文,所以可能在前面:: 可能是正确的。
C
Claus Jensen

只是对 James Sulak 所做答案的注释。

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

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

A
Andrew Cox

问题是节点的位置在没有上下文的情况下意义不大。

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

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

所以现在不是真正的 XPath finder,而是 C# finder。
g
geoffc

我做了很多 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


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅