我正在尝试清理一些XQuery代码并遇到另一个问题(最后一个问题就是这个问题:Error "undefined variable at noteLine" in FLWOR expression when returning multiple nodes)。我正在进一步清理以下工作代码,以尽量减少重用:
for $noteLine in $noteLineArr
where $noteLine != ''
return (
<NTE>
<NoteRefCd>BOL</NoteRefCd>
<Descr>{fn:substring(fn:normalize-space($noteLine), 1, 80)}</Descr>
</NTE>,
if (fn:string-length(fn:normalize-space($noteLine)) > 80 and fn:string-length(fn:normalize-space($noteLine)) <= 160) then (
<NTE>
<NoteRefCd>BOL</NoteRefCd>
<Descr>{fn:substring(fn:normalize-space($noteLine), 81, 80)}</Descr>
</NTE>
) else if (fn:string-length(fn:normalize-space($noteLine)) > 160) then (
<NTE>
<NoteRefCd>BOL</NoteRefCd>
<Descr>{fn:substring(fn:normalize-space($noteLine), 81, 80)}</Descr>
</NTE>,
<NTE>
<NoteRefCd>BOL</NoteRefCd>
<Descr>{fn:substring(fn:normalize-space($noteLine), 161, 80)}</Descr>
</NTE>
) else ()
)
既然我已经移出了第一个NTE,我想基本上对其余部分做同样的事情(运行一个IF并且仅使用所需的代码输出另一个)所以我想象了这样的解决方案:
for $noteLine in $noteLineArr
where $noteLine != ''
return (
<NTE>
<NoteRefCd>BOL</NoteRefCd>
<Descr>{fn:substring(fn:normalize-space($noteLine), 1, 80)}</Descr>
</NTE>,
if (fn:string-length(fn:normalize-space($noteLine)) > 80) then (
<NTE>
<NoteRefCd>BOL</NoteRefCd>
<Descr>{fn:substring(fn:normalize-space($noteLine), 81, 80)}</Descr>
</NTE>
) else()
if (fn:string-length(fn:normalize-space($noteLine)) > 160) then (
<NTE>
<NoteRefCd>BOL</NoteRefCd>
<Descr>{fn:substring(fn:normalize-space($noteLine), 161, 80)}</Descr>
</NTE>
) else ()
)
这在解析器中失败,出现错误“Unexpected Token:'(fn:string-len ...'”指向第二个if语句。我得出结论,XQuery不喜欢重复,除非它们在节点,像这样:
for $noteLine in $noteLineArr
where $noteLine != ''
return (
<NTE>
<NoteRefCd>BOL</NoteRefCd>
<Descr>{fn:substring(fn:normalize-space($noteLine), 1, 80)}</Descr>
</NTE>,
<NTE>
if (fn:string-length(fn:normalize-space($noteLine)) > 80) then (
<NoteRefCd>BOL</NoteRefCd>,
<Descr>{fn:substring(fn:normalize-space($noteLine), 81, 80)}</Descr>
) else()
</NTE>,
<NTE>
if (fn:string-length(fn:normalize-space($noteLine)) > 160) then (
<NoteRefCd>BOL</NoteRefCd>,
<Descr>{fn:substring(fn:normalize-space($noteLine), 161, 80)}</Descr>
) else ()
</NTE>
)
这是行不通的,因为如果它们是空的,我不能让任何额外的节点进入输出。是否有一种方法在XQuery中以类似的方式实现所需的输出(我通过将一些代码放入本地函数但但它不是可读的imo来制定解决方案)?并且可能作为后续,为什么XQuery对多个连续的if语句如此敏感?
解决方案(再次感谢Jens Erat)
for $noteLine in $noteLineArr
where $noteLine != ''
return (
<NTE>
<NoteRefCd>BOL</NoteRefCd>
<Descr>{fn:substring(fn:normalize-space($noteLine), 1, 80)}</Descr>
</NTE>,
if (fn:string-length(fn:normalize-space($noteLine)) > 80) then (
<NTE>
<NoteRefCd>BOL</NoteRefCd>
<Descr>{fn:substring(fn:normalize-space($noteLine), 81, 80)}</Descr>
</NTE>
) else(),
if (fn:string-length(fn:normalize-space($noteLine)) > 160) then (
<NTE>
<NoteRefCd>BOL</NoteRefCd>
<Descr>{fn:substring(fn:normalize-space($noteLine), 161, 80)}</Descr>
</NTE>
) else()
)
(注意:逗号放置在返回的前两个“部分”之后,第一个NTE节点然后在if语句之后,不在if语句之内)。
答案 0 :(得分:2)
XQuery是一种函数式编程语言。除此之外,这意味着一切都有一个具有单一,不同返回值的表达式。你也可以让多个语句返回一些东西,但是你总是必须将它们包装在一个序列中,这是一个将任意数量的输入表达式包装成一个返回值(序列)的表达式。 p>
用较少的样板代码解释问题,请考虑一个小例子,如
for $i in 1 to 10
return $i
这显然会将所有数字从1返回到10。如果我们只想使用if语句返回偶数,该怎么办? if
语句的格式为if (expression) then expression else expression
。请记住:每个表达式都必须有一个返回值,这也适用于else
子句。在这种情况下,我们只返回空序列()
,在XQuery中表示“无值”。
for $i in 1 to 10
return
if ($i mod 2 eq 0)
then $i
else ()
if
表达式这很好,并返回所有偶数值。现在,让我们考虑我们还想要在数字可以除以3时打印字符串。我们不能简单地将其放入else
子句中,例如6
甚至和都可以除以3。我们需要分开if
条款。这也是您在第二个代码示例中尝试过的。
for $i in 1 to 10
return
if ($i mod 2 eq 0)
then $i
else (),
if ($i mod 3 eq 0)
then "three"
else ()
此操作失败,因为第二个$i
子句中未定义if
。但为什么?请记住:每个表达式都应该有一个返回值。也是return
语句的表达式,即if then else
表达式。与第一个问题类似,XQuery编译器将此示例视为
for $i in 1 to 10
return
if ($i mod 2 eq 0)
then $i
else (),
if ($i mod 3 eq 0)
then "three"
else ()
这会使问题更加明显。最后,它与原始问题中的问题相同,但表达式更复杂。两者都是
的形式for $i in 1 to 10
return
expression1,
expression2
如果它们都属于return语句,则必须包含在序列中:
for $i in 1 to 10
return (
expression1,
expression2
)
表达式是旧问题中的元素/元素构造函数,以及此处的if then else
表达式。
if
表达式的解决方案同样,你必须按顺序包装它们:
for $i in 1 to 10
return (
if ($i mod 2 eq 0)
then $i
else (),
if ($i mod 3 eq 0)
then "three"
else ()
)
现在,序列是return
语句的单个表达式,并且还有两个包含if then else
代码的子表达式。当您混合使用不同类型的表达式时也需要这样,例如:
for $i in 1 to 10
return (
if ($i mod 2 eq 0)
then $i
else (),
<foo/>
)
删除序列括号将使XQuery引擎输出偶数,然后输出单个<foo/>
元素,而不是10个<foo/>
元素 - 每个$i
一个。