【发布时间】:2010-07-28 16:18:18
【问题描述】:
我有一个结构如下的 XML 文件:
<foo>
<bar></bar>
<bar></bar>
...
</foo>
我不知道如何抓取一系列节点。谁能给我一个 XPath 表达式的示例,它可以抓取 100-200 条节点吗?
【问题讨论】:
-
好问题 (+1)。请参阅我的答案,以获取准确选择所需节点的简短 XPath 表达式。
我有一个结构如下的 XML 文件:
<foo>
<bar></bar>
<bar></bar>
...
</foo>
我不知道如何抓取一系列节点。谁能给我一个 XPath 表达式的示例,它可以抓取 100-200 条节点吗?
【问题讨论】:
使用:
/*/bar[position() >= 100 and not(position() > 200)]
请注意:
恰好选择了位置 100 到 200(含)的 bar 元素。
此 XPath 表达式的求值可能比使用 // 缩写的表达式快很多倍,因为后者会导致对根为上下文节点的树进行完整扫描。 在可能的情况下,请始终尽量避免使用 // 缩写。
【讨论】:
// 和 /*/ 在语法上都是无效的 XPath 表达式。我猜你的意思是 //* 和 /*/* 。答案是,在这种特定情况下,所花费的时间应该大致相同。但是,如果涉及谓词,则包括// 的表达式将不得不扫描整个树(甚至是最终选择的节点的后代)并过滤每个节点——而在精确表达式的情况下,避免了这种扫描。另请注意,有一些 XPath 处理器经过高度优化,可以有效地处理//* 和类似的表达式。
//foo/bar[100 <= position() and position() < 200]
【讨论】:
fn:subsequence 不是最好的方法吗?
subsequence( /foo/bar, 100, 101 )
返回从位置 100 到 200 的所有项目,即 101 个项目(如果源序列更短,则更少)。
【讨论】:
position() 对序列中的每个项目进行评估(这可能比最终选择的100 个项目多得多),而subsequence() 只被调用一次。无论如何,这个演讲是关于“我们如何选择序列中位置 100 到 200 的所有节点”,而不是是关于“我们可以避免对每个可能的序列过滤要求使用position() 吗?”我的回答直接与——而且只是与——提出的问题有关。
subsequence() 可用,您的查询可以很容易地改写为subsequence( subsequence( /foo/bar, 2, 3)/x, 5, 5)
subsequence() 在 W3c 标准规范中定义:“函数和运算符”仅来自 (XPath) 版本。 2.0 及更高版本。 OP 可能没有使用 XPath 2.0,因此使用 position() 的解决方案更通用——也可以在 XPath 1.0 中工作,使用它们为我们提供了普遍性和普遍性,因此我们不关心我们的环境是哪个版本的 XPath支持。