我对flwor循环有一个非常奇怪的问题,它是一种工作方式,但不是另一种。目标是获取任意长度的字符串,并将其分解为每个只能容纳80个字符的xml节点。所以,首先,这很有效:

    for $noteLine in $noteLineArr
    where $noteLine != ''

    return
    if (fn:string-length(fn:normalize-space($noteLine)) < 80) then (
    <NTE>
        <NoteRefCd>WHI</NoteRefCd>
        <Descr>{fn:substring(fn:normalize-space($noteLine), 1, 80)}</Descr>
    </NTE>
    ) else if (fn:string-length(fn:normalize-space($noteLine)) > 80 and fn:string-length(fn:normalize-space($noteLine)) <= 160) then (
    <NTE>
        <NoteRefCd>WHI</NoteRefCd>
        <Descr>{fn:substring(fn:normalize-space($noteLine), 1, 80)}</Descr>
    </NTE>,
    <NTE>
        <NoteRefCd>WHI</NoteRefCd>
        <Descr>{fn:substring(fn:normalize-space($noteLine), 81, 80)}</Descr>
    </NTE>
    ) else if (fn:string-length(fn:normalize-space($noteLine)) > 160 and fn:string-length(fn:normalize-space($noteLine)) <= 240) then (
    <NTE>
        <NoteRefCd>WHI</NoteRefCd>
        <Descr>{fn:substring(fn:normalize-space($noteLine), 1, 80)}</Descr>
    </NTE>,
    <NTE>
        <NoteRefCd>WHI</NoteRefCd>
        <Descr>{fn:substring(fn:normalize-space($noteLine), 81, 80)}</Descr>
    </NTE>,
    <NTE>
        <NoteRefCd>WHI</NoteRefCd>
        <Descr>{fn:substring(fn:normalize-space($noteLine), 161, 80)}</Descr>
    </NTE>
    ) else()

所以,我觉得这不太优雅。我试图通过将第一个元素移出if来清理它,因为它应该一直被使用,对吧?这样代码就少了?我试过的是:
for $noteLine in $noteLineArr
where $noteLine != ''

return

    <NTE>
        <NoteRefCd>WHI</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>WHI</NoteRefCd>
        <Descr>{fn:substring(fn:normalize-space($noteLine), 81, 80)}</Descr>
    </NTE>
    ) else if (fn:string-length(fn:normalize-space($noteLine)) > 160 and fn:string-length(fn:normalize-space($noteLine)) <= 240) then (
    <NTE>
        <NoteRefCd>WHI</NoteRefCd>
        <Descr>{fn:substring(fn:normalize-space($noteLine), 81, 80)}</Descr>
    </NTE>,
    <NTE>
        <NoteRefCd>WHI</NoteRefCd>
        <Descr>{fn:substring(fn:normalize-space($noteLine), 161, 80)}</Descr>
    </NTE>
    ) else()

解析器现在告诉我“noteline的未定义变量”指向第一个“if”行。我错过了什么?(请注意,是的,我确实有其他的想法,如何清理这个甚至更多,但这是第一个简单的步骤,当它失败惨痛,我惊慌失措)。
解决方案(感谢Jens Erat)
返回块需要用括号括起来,以便强制它在flwor循环的每次迭代中完全求值。因此:
for $noteLine in $noteLineArr
where $noteLine != ''

return
    (
        <NTE>
            <NoteRefCd>WHI</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>WHI</NoteRefCd>
            <Descr>{fn:substring(fn:normalize-space($noteLine), 81, 80)}</Descr>
        </NTE>
        ) else if (fn:string-length(fn:normalize-space($noteLine)) > 160 and fn:string-length(fn:normalize-space($noteLine)) <= 240) then (
        <NTE>
            <NoteRefCd>WHI</NoteRefCd>
            <Descr>{fn:substring(fn:normalize-space($noteLine), 81, 80)}</Descr>
        </NTE>,
        <NTE>
            <NoteRefCd>WHI</NoteRefCd>
            <Descr>{fn:substring(fn:normalize-space($noteLine), 161, 80)}</Descr>
        </NTE>
        ) else()
    )

最佳答案

这是一个小语法问题。必须在return子句中创建的元素周围加上括号。为了进一步解释这个问题,我提供了一个类似但简单的示例:

for $i in 1 to 3
return
    <foo />,
    <bar />

您将得到以下结果(这两个元素重复了三次):
<foo/>
<bar/>
<foo/>
<bar/>
<foo/>
<bar/>

但是相反,你得到
<foo/>
<foo/>
<foo/>
<bar/>

这是因为查询实际上被计算为
(
  for $i in 1 to 3
  return
      <foo />
),
<bar />

在代码中,不会得到意外的输出,但会收到错误消息。这是因为$noteLine没有在第一个逗号,之后定义。对于以下查询,您将收到类似的错误消息:
for $i in 1 to 3
return
    <foo>{ $i }</foo>,
    <bar>{ $i }</foo>

这里,$i没有绑定到<bar/>元素,因为查询的计算方式是
(
  for $i in 1 to 3
  return
      <foo>{ $i }</foo>
),
<bar>{ $i }</foo> (: obivously, $i is not defined here :)

07-24 16:26