返回多个节点时 FLWOR 表达式中的错误 "undefined variable at noteLine"
Error "undefined variable at noteLine" in FLWOR expression when returning multiple nodes
我有一个关于 FLWOR 循环的非常奇怪的问题,它以一种方式工作,而不是另一种方式。目标是获取任意长度的字符串,并将其分成 XML 个节点,每个节点只能容纳 80 个字符。所以,首先,这很好用:
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()
解析器现在告诉我 "undefined variable at noteLine" 指向第一个 "if" 行。我在这里错过了什么? (请注意,是的,我确实有其他关于如何进一步清理它的想法,但这是第一个简单的步骤,当它惨败时,我惊慌失措)。
解决方案(感谢 Jens Erat)
return 块需要用括号括起来,以强制它在 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 :)
我有一个关于 FLWOR 循环的非常奇怪的问题,它以一种方式工作,而不是另一种方式。目标是获取任意长度的字符串,并将其分成 XML 个节点,每个节点只能容纳 80 个字符。所以,首先,这很好用:
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()
解析器现在告诉我 "undefined variable at noteLine" 指向第一个 "if" 行。我在这里错过了什么? (请注意,是的,我确实有其他关于如何进一步清理它的想法,但这是第一个简单的步骤,当它惨败时,我惊慌失措)。
解决方案(感谢 Jens Erat) return 块需要用括号括起来,以强制它在 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 :)