XQuery:除最后一个元素外,如何在序列后添加逗号
XQuery: How to add a comma after sequence except for the last element
我有以下 xml:
<form>
<bibl>
<biblScope>1</biblScope>
<biblScope>a</biblScope>
</bibl>
<bibl>
<biblScope>2</biblScope>
<biblScope>b</biblScope>
</bibl>
<bibl>
<biblScope>38</biblScope>
<biblScope>c</biblScope>
</bibl>
</form>
使用这个 XQuery
for $bibl in form/bibl
return
<div>
{
for $biblScope in $bibl/biblScope/text()
return
$biblScope
}
{if ($bibl[position()] ne $bibl[last()]) then ',' else '@'}
</div>
<biblScope>
内容陆续打印出来。在每个 bibl
元素之后,除了最后一个,我想添加一个分隔符(逗号/“,”),但是使用上面的代码,我得到的只是
<div>
1a
@
</div>
<div>
2b
@
</div>
<div>
38c
@
</div>
这绝对是错误的,因为我想要的是
<div>1a,</div>
<div>2b,</div>
<div>38c@</div>
(在每个 bibl
元素内容后添加一个逗号;最后一个应该跟在 @
而不是逗号。)
我已经尝试了一段时间不同的东西,可能需要一些帮助。执行此操作的正确方法是什么?
首先注意这个:
for $biblScope in $bibl/biblScope/text()
return
$biblScope
可以这样代替:
$bibl/biblScope/text()
(这一点冗长是一个令人惊讶的常见错误。它表明您是在按程序思考 - 一次处理一个项目,而不是处理集合。)
然后这个:
<div>
{$bibl/biblScope/text()}
{if ($bibl[position()] ne $bibl[last()]) then ',' else '@'}
</div>
应替换为:
<div>{string-join($bibl/biblScope, ',')}@</div>
请注意,我还摆脱了对 /text()
的不必要(并且可以说是不正确的)使用,这是另一个 XQuery anti-pattern.
问题是 position()
和 last()
作用于当前上下文,它不是由 flwor 表达式设置的。如果你想使用类似的语义,使用 at $position
语法得到一个位置计数器,并定义 $last
作为结果的数量:
let $last := count(form/bibl)
for $bibl at $position in form/bibl
return
<div>
{
for $biblScope in $bibl/biblScope/text()
return
$biblScope
}
{if ($position ne $last) then ',' else '@'}
</div>
如果您能够使用 XQuery 3.0,应用程序运算符 !
可能会在这里派上用场。用轴步骤和元素构造函数替换不必要的循环,您可以依赖位置谓词,因为上下文设置为 <bibl/>
elements:
form/bibl ! <div>
{
biblScope/text(),
if (position() ne last()) then ',' else '@'
}
</div>
我有以下 xml:
<form>
<bibl>
<biblScope>1</biblScope>
<biblScope>a</biblScope>
</bibl>
<bibl>
<biblScope>2</biblScope>
<biblScope>b</biblScope>
</bibl>
<bibl>
<biblScope>38</biblScope>
<biblScope>c</biblScope>
</bibl>
</form>
使用这个 XQuery
for $bibl in form/bibl
return
<div>
{
for $biblScope in $bibl/biblScope/text()
return
$biblScope
}
{if ($bibl[position()] ne $bibl[last()]) then ',' else '@'}
</div>
<biblScope>
内容陆续打印出来。在每个 bibl
元素之后,除了最后一个,我想添加一个分隔符(逗号/“,”),但是使用上面的代码,我得到的只是
<div>
1a
@
</div>
<div>
2b
@
</div>
<div>
38c
@
</div>
这绝对是错误的,因为我想要的是
<div>1a,</div>
<div>2b,</div>
<div>38c@</div>
(在每个 bibl
元素内容后添加一个逗号;最后一个应该跟在 @
而不是逗号。)
我已经尝试了一段时间不同的东西,可能需要一些帮助。执行此操作的正确方法是什么?
首先注意这个:
for $biblScope in $bibl/biblScope/text()
return
$biblScope
可以这样代替:
$bibl/biblScope/text()
(这一点冗长是一个令人惊讶的常见错误。它表明您是在按程序思考 - 一次处理一个项目,而不是处理集合。)
然后这个:
<div>
{$bibl/biblScope/text()}
{if ($bibl[position()] ne $bibl[last()]) then ',' else '@'}
</div>
应替换为:
<div>{string-join($bibl/biblScope, ',')}@</div>
请注意,我还摆脱了对 /text()
的不必要(并且可以说是不正确的)使用,这是另一个 XQuery anti-pattern.
问题是 position()
和 last()
作用于当前上下文,它不是由 flwor 表达式设置的。如果你想使用类似的语义,使用 at $position
语法得到一个位置计数器,并定义 $last
作为结果的数量:
let $last := count(form/bibl)
for $bibl at $position in form/bibl
return
<div>
{
for $biblScope in $bibl/biblScope/text()
return
$biblScope
}
{if ($position ne $last) then ',' else '@'}
</div>
如果您能够使用 XQuery 3.0,应用程序运算符 !
可能会在这里派上用场。用轴步骤和元素构造函数替换不必要的循环,您可以依赖位置谓词,因为上下文设置为 <bibl/>
elements:
form/bibl ! <div>
{
biblScope/text(),
if (position() ne last()) then ',' else '@'
}
</div>