问题描述
我无法找到以下解释。我已经制作了这个测试脚本以解决。
I can't find an explanation on the following. I've made this test script in order to solve my previous question.
xquery version "3.0" ;
declare default function namespace 'local' ;
declare function local:is-img-only( $element as element() ) as xs:boolean {
($element/child::*[1] instance of element(img))
and (fn:not($element/child::*[2]))
and (fn:normalize-space($element) = '')
} ;
let $in-xml := <myxml>
<p id="1">
<img id="1"/>
</p>
<p id="2">
<img id="1"/>
hello
</p>
<p id="3">
<img id="1"/>
</p>
<p id="4">
<blockquote>hello</blockquote>
<img id="1"/>
</p>
<p id="5">
<img id="1"/>
<img id="2"/>
</p>
</myxml>
然后,以下使用 if if else else
:
for $p in $in-xml/p
return if (local:is-img-only($p))
then $p/@id/fn:data() || ' has only an img child'
else $p/@id/fn:data() || ' has not strictly an img child'
按预期返回:
1 has only an img child
2 has not strictly an img child
3 has only an img child
4 has not strictly an img child
5 has not strictly an img child
以下使用切换案例
for $p in $in-xml/p
return switch ($p)
case (local:is-img-only($p)) return $p/@id/fn:data() || ' has only an img child'
default return $p/@id/fn:data() || ' has not strictly an img child'
返回预期:
1 has not strictly an img child
2 has not strictly an img child
3 has not strictly an img child
4 has not strictly an img child
5 has not strictly an img child
有什么解释吗?为什么的行为方式与?
Any explanation ? Why Conditional Expressions would not behave the same way than Switch Expressions ?
推荐答案
很好地为您的问题找到XQuery规范的相关部分!这是一半的战斗。切换表达式确实与条件表达式共享一些共同点,但存在一些差异。
Great job in locating the relevant sections of the XQuery specification for your question! That's half the battle. Switch expressions do share some things in common with conditional expressions, but there are some differences.
关键区别在于条件表达式评估测试表达式以查看结果是true还是false,而切换表达式将一个表达式与一个或多个其他表达式进行比较,以找到相等的第一对。使用伪代码,我们可以说明差异。条件表达式中的所有逻辑都在这一行上发生:
The key difference is that a conditional expression evaluates a test expression to see if the result is true or false, while a switch expression compares one expression against one or more other expressions to find the first pair that are equal. Using pseudo code, we can illustrate the difference. All of the logic in a conditional expression takes place here on one line:
if ($EXPRESSION)
相比之下,开关表达式的逻辑分布在多行上:
In contrast, the logic of a switch expression is spread over many lines:
switch ($EXPRESSION_A)
case ($EXPRESSION_B) ...
case ($EXPRESSION_C) ...
case ($EXPRESSION_D) ...
default ...
切换表达式实际上是执行一系列比较,我们可以表达更多的条件表达式:
The switch expression is actually performing a chain of comparisons, which we could express as even more lines of conditional expressions:
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" :)
这两个表达式之间的细节差异在规范中有描述,从他们描述处理每个表达式的第一步开始。而处理条件表达式的第一步是:
The nitty gritty differences between these two expressions are described in the spec, starting with where they describe "the first step" in processing each expression. Whereas the first step in processing a conditional expression is:
...处理开关表达式的第一步是:
... the first step in processing a switch expression is:
让我们回到你的具体例子,看看你的条件测试表达式和开关的开关操作数表达式:
Let's return to your concrete example and take a look at your conditional's test expression and your switch's switch operand expression:
-
条件的测试表达式:
Your conditional's test expression:
if (local:is-img-only($p))
你的开关的操作数表达式:
Your switch's operand expression:
switch ($p)
条件的测试表达式返回一个布尔值 - true( )
或 false()
,所以这个条件清楚地列出了其余鳕鱼的路径即
The conditional's test expression returns a boolean - true()
or false()
, so this condition clearly charts out the path of the rest of the code.
相比之下,switch表达式的逻辑才刚刚开始使用此操作数表达式。首先,它找到操作数表达式的雾化值 - < p>
元素绑定到 $ p
变量在你的FLWOR表达式中。由于此值取决于我们正在查看的< p>
,因此雾化值将为空字符串(),空格或
hello
(或其某些组合,具体取决于源中的空格和边界空间声明)。然后,评估并初始化交换机的第一个案例操作数。你的第一个案例操作数如下:
In contrast, the logic of the switch expression has only just begun with this operand expression. First, it finds the atomized value of the operand expression—the <p>
element bound to the $p
variable in your FLWOR expression. Since this value depends on which <p>
we're looking at, the atomized value will either be an empty string (""
), whitespace, or "hello"
(or some combination thereof, depending on whitespace in your source and your boundary space declaration). Then, the switch's first case operand is evaluated and atomized. Your first case operand is as follows:
case (local:is-img-only($p))
我们记得,这个表达式的计算结果为布尔值。 switch表达式执行的下一步是使用 fn:deep-equal
函数将switch操作数表达式的雾化值与switch case操作数的雾化值进行比较。实际上,我们要求XQuery处理器执行以下比较:
This expression, as we'll recall, evaluates to a boolean. The next step the switch expression performs is to compare the atomized value of the switch operand expression with the atomized value of the switch case operand using the fn:deep-equal
function. Effectively, then, we're asking the XQuery processor to perform the following comparisons:
deep-equal("", true())
deep-equal("hello", false())
在这两种情况下比较返回 false()
。因此,在我们的操作数总是中的这种比较失败,因此在FLWOR表达式的每次迭代中,switch表达式都会回退到 default
子句。
In both cases the comparison returns false()
. Thus, this comparison in our case operand always fails, so the switch expression is falling back on the default
clause in every iteration of your FLWOR expression.
模仿原始条件表达式结果的开关表达式如下:
A switch expression that mimics the results of your original conditional expression would be the following:
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())
并返回与条件表达式相同的结果。
And returns the identical results as your conditional expression.
这对于switch表达式来说,这不是一个特别引人注目的用法 - 因为我们正在有效地评估单个测试表达式。当你有许多要比较的值时,开关表达式真的很闪亮。该规范为我们提供了一个很好的示例切换表达式:
This isn't a particularly compelling use for the switch expression - since we're effectively evaluating a single test expression. The switch expression really shines when you have many values to compare. The spec offers us a good example switch expression to consider:
switch ($animal)
case "Cow" return "Moo"
case "Cat" return "Meow"
case "Duck" return "Quack"
default return "What's that odd noise?"
这比同等的条件表达式更具可读性和紧凑性:
This is far more readable and compact than the equivalent conditional expression:
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?"
结果:如果你发现自己编写了一系列条件,并且比较的左侧总是一样的,考虑进行转换。
The upshot: if you ever find yourself writing a chain of conditionals, and the left side of the comparison is always the same, consider making a switch.
这篇关于Xquery:无论是在switch / case还是if / then / else中使用,相同的测试都有不同的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!