Firefox 中的 XPath 排序

XPath ordering in Firefox

如何使 XPath (1) 单行优先化在 Firefox 中工作?为什么在 Firefox 中 | "fails" 而在 Chrome 中 "works"?

哪一个是正确的(如果规范中定义了这种行为)以及如何让它在所有方面发挥作用?

<a>b</a>
<a id="b"></a>

Chrome 39.0.2171.95

> $x("//a[@id='b'] | //a[text()='b']")
< [<a id=​"b">​</a>​, <a>​b​</a>​]

火狐 34.0.5

> $x("//a[@id='b'] | //a[text()='b']")
< Array [ <a>, <a#b> ]

编辑:删除了 or 选择器示例,因为问题是关于 Firefox 中的 | 行为,而不是关于两者之间的区别。

那个 |运算符不是或,它是联合,因此节点集将包含由左手 xpath(管道左侧)和右手 xpath 选择的元素子集。

选择器

"//a[@id='b' or text()='b']"

读取:按照在DOM中出现的顺序遍历所有"a"个元素并对谓词[..]求值,如果谓词求值为'true',则遍历的元素为添加到结果节点集

选择器

"//a[@id='b'] | //a[text()='b']"

读取:应用 //a[@id='b'](如上所述),然后应用 //a[text()='b'] 最后将结果连接在一起返回包含两个结果的节点集。

结果中元素的顺序与遍历相同,即它保留文档中的顺序,但是并集不包括重复项(因为节点集可能不包含重复项),即//a|/ /a 结果相同的节点集

然而,并没有定义联合 (|) 应该如何处理顺序,因此它取决于实现,因此你在 Chrome 和 FF

中看到不同的结果

我只能引用 Michael Kay 博士的话,saying:

The XPath 1.0 specification defines that a path expression (or a union expression) returns a node-set, that is, an unordered set of nodes. Some host languages, for example XSLT 1.0, specify that node-sets are always processed in document order. But you appear (as far as I can tell) to be invoking XPath from some Microsoft API, and I've no idea what that API says about the processing order: it's up to the XPath host language to define it, or it could choose to leave it undefined.

而且,如果主流浏览器应该采用 XPath 2.0:

This changes in XPath 2.0, which specifies that path expressions and union expressions return a sequence of distinct nodes in document order.

在您的情况下,这仅意味着:如果结果集和重复项的顺序对您很重要,请不要使用 |union 运算符。使用包含 or 的谓词(您现在已从问题中编辑出的路径表达式)如果这样的表达式 return Firefox 和 Chrome 的结果顺序相同。

但一般来说,无法保证节点集的文档顺序,因为无序是 属性 个集:

The second important point is that the order in which the elements of a set are listed is irrelevant (unlike for a sequence or tuple) (from: Set(mathematics)).

仍然,许多 XPath 1.0 的实现 return "items" 在节点集中按文档顺序 - 不是因为规范必须这样做,而是因为在许多情况下, return按文档顺序排列结果确实很有意义。


已经有几个非常相似的问题,例如this question or this one