首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >XQuery FLWOR返回包含多个if语句的区段代码内容

XQuery FLWOR返回包含多个if语句的区段代码内容
EN

Stack Overflow用户
提问于 2016-01-26 15:35:23
回答 1查看 3.5K关注 0票数 2

我试图清理一些XQuery代码,并遇到了另一个问题(最后一个问题是这个问题:Error "undefined variable at noteLine" in FLWOR expression when returning multiple nodes)。我将进一步清理以下工作代码,以最大限度地减少重用:

代码语言:javascript
复制
    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移出了,我想基本上对其余的NTE做同样的操作(运行一个当且仅当,只使用所需的代码输出另一个),所以我设想了这样的解决方案:

代码语言:javascript
复制
    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 ()
    )   

这在解析器中失败,错误为“意外令牌:‘(fn:string.’”)指向第二个if语句。我得出的结论是,XQuery不喜欢重复出现的if节,除非它们位于节点中,如下所示:

代码语言:javascript
复制
    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中是否有一种类似的方法来实现所期望的输出(我通过将一些代码放入一个本地函数来解决这个问题,但是它不是那么可读的,海事组织)?作为后续,为什么XQuery对多个连续的if语句如此敏感?

解决方案(再次感谢Jens )

代码语言:javascript
复制
    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语句中)。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-01-26 17:11:52

XQuery是一种函数式编程语言。除其他外,这意味着所有事物都有一个具有单一、不同的返回值的表达式。您还可以有多个语句返回某些内容,但是始终必须将它们包装在一个序列中,这是一个将任意数量的输入表达式包装到一个返回值(序列)中的表达式。

解释表达

要用更少的样板代码来解释这个问题,请考虑下面的一个小例子

代码语言:javascript
复制
for $i in 1 to 10
return $i

这显然会将所有数字从1返回到10。如果我们只想使用if语句返回偶数怎么办?if语句的形式是if (expression) then expression else expression。记住:每个表达式都必须有一个返回值,这也适用于else子句。在本例中,我们只让它返回空序列(),它在XQuery中的意思是“无值”。

代码语言:javascript
复制
for $i in 1 to 10
return
  if ($i mod 2 eq 0)
  then $i
  else ()

具有多个if表达式

这很好,并返回所有偶数值。现在,让我们考虑一下,每当一个数字可以除以3时,我们也要打印一个字符串。我们不能简单地将其放入else子句中,例如,6既是偶数,又可以除以3。我们需要分离if条款。这也是您在第二个代码示例中尝试过的。

代码语言:javascript
复制
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编译器认为这个示例是

代码语言:javascript
复制
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 ()

这应该会让问题变得更明显。最后,它是相同的问题,在你的原始问题,但更复杂的表达。两者都是形式上的

代码语言:javascript
复制
for $i in 1 to 10
return
  expression1,
  expression2

如果它们都属于return语句,则必须用一个序列括起来:

代码语言:javascript
复制
for $i in 1 to 10
return (
  expression1,
  expression2
)

表达式是旧问题中的元素/元素构造函数,这里是if then else表达式。

多个if表达式的解决方案

同样,您必须将它们按顺序包装:

代码语言:javascript
复制
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代码的子表达式。在混合不同类型的表达式时,也需要这样做,如本例所示:

代码语言:javascript
复制
for $i in 1 to 10
return (
  if ($i mod 2 eq 0)
  then $i
  else (),
  <foo/>
)

删除序列括号将使XQuery引擎输出偶数,然后输出单个<foo/>元素,而不是10个<foo/>元素--每个$i一个。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35017665

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档