Ошибка "неопределенная переменная в noteLine" в выражении FLWOR при возврате нескольких узлов
У меня очень странная проблема с циклом 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()
И теперь синтаксический анализатор сообщает мне "неопределенная переменная в noteLine", указывающая на первую строку "если". Что мне здесь не хватает? (обратите внимание, что да, у меня есть другие идеи о том, как убрать это еще больше, но это был первый простой шаг, и когда он потерпел неудачу, я запаниковал).
Решение (спасибо Jens Erat) Блок возврата должен быть заключен в круглые скобки, чтобы заставить его выполнять полную оценку на каждой итерации цикла flwor. Thusly:
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()
)
1 ответ
Это незначительная проблема синтаксиса. Вы должны поставить круглые скобки вокруг элементов, созданных в 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 :)