非常出色地找到了与您的问题相关的 XQuery 规范部分!这样就成功了一半。开关表达式确实与条件表达式有一些共同点,但也存在一些差异。
主要区别在于条件表达式评估测试表达式查看结果是 true 还是 false,而 switch 表达式将一个表达式与一个或多个其他表达式进行比较找到第一对相等的。使用伪代码,我们可以说明其中的差异。条件表达式中的所有逻辑都发生在一行上:
if ($EXPRESSION)
相反,switch 表达式的逻辑分布在许多行中:
switch ($EXPRESSION_A)
case ($EXPRESSION_B) ...
case ($EXPRESSION_C) ...
case ($EXPRESSION_D) ...
default ...
switch 表达式实际上执行一系列比较,我们可以将其表示为更多行条件表达式:
if (deep-equal($EXPRESSION_A, $EXPRESSION_B))
then ...
else
if (deep-equal($EXPRESSION_A, $EXPRESSION_C))
then ...
else ...
if (deep-equal($EXPRESSION_A, $EXPRESSION_D))
then ...
else ... (: "default" :)
规范中描述了这两个表达式之间的本质区别,从它们描述处理每个表达式的“第一步”开始。而处理条件表达式的第一步是:
找到测试表达式的有效布尔值。
...处理 switch 表达式的第一步是:
将原子化应用于 switch 操作数表达式的值。
让我们回到具体的示例,看一下条件的测试表达式和开关的 switch 操作数表达式:
-
您的条件测试表达式:
if (local:is-img-only($p))
-
您的开关的操作数表达式:
switch ($p)
条件的测试表达式返回一个布尔值 -true()
or false()
,因此这个条件清楚地标出了其余代码的路径。
相反,switch 表达式的逻辑才刚刚从这个操作数表达式开始。首先,它找到操作数表达式的原子化值——<p>
元素绑定到$p
FLWOR 表达式中的变量。由于该值取决于哪个<p>
我们正在考虑,原子化值将是一个空字符串(""
)、空格或"hello"
(或其某种组合,具体取决于源中的空白和边界空间声明)。然后,对 switch 的第一个 case 操作数进行求值和原子化。您的第一个 case 操作数如下:
case (local:is-img-only($p))
我们记得,这个表达式的计算结果是一个布尔值。 switch 表达式执行的下一步是使用以下命令将 switch 操作数表达式的原子化值与 switch case 操作数的原子化值进行比较:fn:deep-equal
功能。那么,我们实际上要求 XQuery 处理器执行以下比较:
deep-equal("", true())
deep-equal("hello", false())
在这两种情况下,比较都会返回false()
。因此,我们的案例操作数中的比较always失败,所以 switch 表达式又回到了default
FLWOR 表达式的每次迭代中的子句。
模仿原始条件表达式结果的 switch 表达式如下:
for $p in $in-xml/p
return switch(local:is-img-only($p))
case (true()) return $p/@id/fn:data() || ' has only an img child'
default return $p/@id/fn:data() || ' has not strictly an img child'
这将执行以下检查:
deep-equal(true(), true())
deep-equal(true(), false())
并返回与条件表达式相同的结果。
对于 switch 表达式来说,这并不是特别引人注目的用途 - 因为我们正在有效地评估单个测试表达式。当您有许多值需要比较时,switch 表达式确实会发挥作用。该规范为我们提供了一个值得考虑的很好的 switch 表达式示例:
switch ($animal)
case "Cow" return "Moo"
case "Cat" return "Meow"
case "Duck" return "Quack"
default return "What's that odd noise?"
这比等效的条件表达式更具可读性和紧凑性:
if (deep-equal($animal, "Cow"))
then "Moo"
else
if (deep-equal($animal, "Cat"))
then "Meow"
else
if (deep-equal($animal, "Duck"))
then "Quack"
else "What's that odd noise?"
或者更直接的解释:
if ($animal eq "Cow")
then "Moo"
else
if ($animal eq "Cat")
then "Meow"
else
if ($animal eq "Duck")
then "Quack"
else "What's that odd noise?"
结果:如果您发现自己编写了一系列条件语句,并且比较的左侧始终相同,请考虑进行切换.