使用count(preceding-sibling::*)
XPath 表达式可以获得递增计数器。但是,同样也可以在两级深度序列中完成吗?
<grandfather>
<father>
<child>a</child>
</father>
<father>
<child>b</child>
<child>c</child>
</father>
</grandfather>
尝试为具有不同类型的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
我试过的三个 XPaths 中没有一个设法产生正确的序列:1,2,3。很明显,使用i
循环变量可以轻松完成,但如果可能,我想用 XPath 完成它。此外,我需要保持评估 XPath 表达式的基本框架,以获取所有要访问的节点,然后在该集合上进行迭代,因为这是我正在处理的实际应用程序的结构。基本上我访问每个节点,然后需要在其上评估一些 XPath 表达式(node
)或文档(doc
);其中一个 XPAth 表达式应该产生这个递增序列。
答案 0 :(得分:1)
使用前面的轴代替名称测试。
count(preceding::child)
使用XPath 2.0,有一种更好的方法可以做到这一点。获取所有<child/>
个节点并使用position()
函数获取索引:
//child/concat("child's index is: ", position(), ", name is: ", text())
答案 1 :(得分:1)
你没有说效率很重要,但我真的很讨厌用O(n ^ 2)代码完成这个! Jens的解决方案展示了如何以一系列(位置,名称)对的形式使用结果的方法。您还可以使用// child /(string(。),position())返回交替的字符串和数字序列:虽然您希望使用s9api API而不是JAXP,因为JAXP只能真正处理数据类型在XPath 1.0中出现。
如果您需要计算每个节点的索引作为其他处理的一部分,那么在单个初始传递中为每个节点计算索引可能仍然值得,然后在表中查找它。但是如果你这样做,最简单的方法肯定是迭代//child
的结果,并在迭代中从节点到序列号构建一个映射。