0

使用count(preceding-sibling::*) XPath表达式可以获得递增的计数器。但是,同样可以在两级深度序列中完成吗?

示例 XML 实例

<grandfather>
    <father>
        <child>a</child>
    </father>
    <father>
        <child>b</child>
        <child>c</child>
    </father>
</grandfather>

代码(在 XPath 2.0 功能的 CLASSPATH 上使用 Saxon HE 9.4 jar)

尝试为具有不同类型 XPath 表达式的三个子节点获取 1,2 和 3 的计数器序列:

    XPathExpression expr = xpath.compile("/grandfather/father/child");
    NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
    for (int i = 0 ; i < nodes.getLength() ; i++) {
        Node node = nodes.item(i);
        System.out.printf("child's index is: %s %s %s, name is: %s\n"
                          ,xpath.compile("count(preceding-sibling::*)").evaluate(node)
                          ,xpath.compile("count(preceding-sibling::child)").evaluate(node)
                          ,xpath.compile("//child/position()").evaluate(doc)
                          ,xpath.compile(".").evaluate(node));
    }

上面的代码打印:

child's index is: 0 0 1, name is: a
child's index is: 0 0 1, name is: b
child's index is: 1 1 1, name is: c

我尝试的三个XPath中没有一个能够生成正确的序列:1、2、3。显然它可以使用循环变量轻松完成,但如果可能的话i,我想用XPath完成它。此外,我需要保留评估XPath表达式的基本框架,以访问所有节点,然后在该集合上进行迭代,因为这是我处理的实际应用程序的结构方式。基本上我访问每个节点,然后需要在它( )或文档()上评估许多XPath表达式;这些XPATH表达式之一应该产生这个递增序列。nodedoc

4

2 回答 2

1

你没有说效率很重要,但我真的很讨厌看到这用 O(n^2) 代码完成!Jens 的解决方案展示了如何以(位置、名称)对序列的形式使用结果。您还可以使用 //child/(string(.), position()): 返回字符串和数字的交替序列:尽管您可能希望使用 s9api API 而不是 JAXP,因为 JAXP 只能真正处理数据类型出现在 XPath 1.0 中。

如果您需要计算每个节点的索引作为其他处理的一部分,则可能仍然值得在单个初始通道中计算每个节点的索引,然后在表中查找它。但如果你这样做,最简单的方法肯定是迭代结果//child并构建从节点到迭代中序列号的映射。

于 2013-07-03T14:27:14.277 回答
1

请改用名称为 test 的前面的轴。

count(preceding::child)

使用 XPath 2.0,有一个更好的方法来做到这一点。获取所有<child/>节点并使用position()函数获取索引:

//child/concat("child's index is: ", position(), ", name is: ", text())
于 2013-07-02T21:57:52.463 回答