相对于 1.0,XPath 2.0 有一些新的函数和语法,可以处理序列。其中一些集合并没有真正添加到语言在 1.0 中已经可以做的事情(使用节点集合),但它们使以更易读的方式表达所需的逻辑变得更容易。这增加了程序员获得正确代码并保持这种方式的机会。例如,
empty(s)
等价于not(s)
,但是当你想测试一个序列是否为空时,它的意图要清楚得多。- 更正:序列的有效布尔值通常比这更复杂。例如
empty((0))
!=not((0))
。这也适用于布尔上下文中的exists(s)
vs .。s
但是,有些域s
whereempty(s)
等价于not(s)
,因此两者可以在这些域中互换使用。但这表明使用empty()
可以在使代码更易于理解方面产生不小的差异。
- 更正:序列的有效布尔值通常比这更复杂。例如
- 类似地,
exists(s)
等效boolean(s)
于 XPath 1.0 中已经存在的内容(或只是s
在布尔上下文中),但其意图更加清晰。 - 量化表达式;例如,“
some $x in
表达式satisfies
测试($x)
”将等同于boolean(
表达式[
测试(.)])
(尽管新语法更灵活,因为您不必担心丢失上下文项,因为您有引用它的变量)。 - 类似地,“
every $x in
表达式satisfies
测试($x)
”将等同于not(
表达式[not(
测试(.))])
,但更具可读性。
显然,这些函数和语法的添加成本不低,只是为了实现编写更容易映射到人类思维方式的 XPath 的目标。正如经验丰富的开发人员所知,这意味着可理解的代码明显优于难以理解的代码。
鉴于所有这些......编写一个询问的 XPath 测试表达式的清晰易读的方法是什么
值 X 是否出现在序列 S 中?
一些方法:(注意:我在这里使用X
和S
符号来表示值和序列,但我并不是暗示这些子表达式是元素名称测试,也不是简单的表达式。它们可能很复杂。 )
X = S
: 这将是最难读的之一,因为它要求读者index-of(S, X)
:这个很清楚什么是值和序列(如果你记得参数的顺序index-of()
)。但它表达的超出了我们的需要:它要求索引,而我们真正想知道的只是X是否出现在 S 中。这对读者有点误导。有经验的开发人员会通过一些努力和对上下文的理解来弄清楚它的意图。但是我们越是依赖上下文来理解每一行的意图,就越能理解代码变成一个循环(螺旋)和潜在的西西弗斯任务!此外,由于index-of()
旨在返回 X 出现的所有索引的列表,它可能比必要的更昂贵:智能处理器,为了评估X = S
,不一定要找到 S 的所有内容,也不一定要按顺序枚举它们;但是对于index-of(S, X)
,必须确定正确的顺序,并且必须将 S 的所有内容与 X 进行比较。使用的另一个缺点index-of()
是它仅限于eq
用于比较;例如,您不能用它来询问一个节点是否与给定序列中的任何节点相同。- 更正:此表格用作条件测试,可能会导致运行时错误:
Effective boolean value is not defined for a sequence of two or more items starting with a numeric value
. (但至少我们不会得到错误的布尔值,因为index-of()
不能返回零。)如果 S 可以有多个 X 实例,这是另一个选择形式 3 或 6 的好理由。
- 更正:此表格用作条件测试,可能会导致运行时错误:
exists(index-of(X, S))
:使意图更清晰,如果处理器足够智能,将有助于处理器消除性能损失。some $m in S satisfies $m eq X
: 这个很清楚,完全符合我们的意图。与 1 相比,它似乎冗长,而且它本身会降低可读性。但为了清楚起见,这可能是一个可以接受的价格。请记住,X 和 S 本身可能是复杂的表达式——它们不一定只是变量引用。一个优点是,由于eq
运算符是显式的,您可以将其替换为is
或任何其他比较运算符。S[. eq X]
:比 1 更清晰,但具有 2 的语义缺陷:它计算 S 中等于 X 的所有成员。实际上,如果 X 为假,这可能会返回假阴性(不正确的有效布尔值)。例如(0, 1)[. eq 0]
,返回 0 这是虚假的,即使0
发生在(0, 1)
.exists(S[. eq X])
:比 1、2、3、5 更清晰。不如 4 清晰,但更短。避免 5 的缺点(或至少其中大部分,取决于处理器的智能)。
在这一点上,我有点倾向于最后一个:exists(S[. eq X])
那么您呢... 作为一名开发人员,他正在处理一个复杂的、不熟悉的 XSLT 或 XQuery 或其他使用 XPath 2.0 的程序,并想弄清楚该程序在做什么,您认为哪个最容易阅读?
为长长的问题道歉。感谢您阅读本文。
编辑:我在上面的讨论中尽可能地改变了,以便更容易看到“价值比较”(而不是一般比较)的意图=
。eq