我想在xquery中创建一个计数器。我最初的尝试如下所示:
let $count := 0
for $prod in $collection
let $count := $count + 1
return
<counter>{$count }</counter>
预期结果:
<counter>1</counter>
<counter>2</counter>
<counter>3</counter>
实际结果:
<counter>1</counter>
<counter>1</counter>
<counter>1</counter>
$count
变量无法更新或被重置。为什么我不能重新赋值现有的变量?什么是获得预期结果的更好方法?
发布于 2012-04-24 09:29:28
尝试使用‘at’中的
for $d at $p in $collection
return
element counter { $p }
这将为您提供每个“$d”的位置。如果您想将它与order by
子句一起使用,这将不起作用,因为位置是基于初始顺序的,而不是基于排序结果的。要解决这个问题,只需将FLWOR表达式的排序结果保存在一个变量中,并在第二个FLWOR中使用at
子句,该子句只迭代第一个排序结果。
let $sortResult := for $item in $collection
order by $item/id
return $item
for $sortItem at $position in $sortResult
return <item position="{$position}"> ... </item>
发布于 2012-04-24 10:01:27
正如@Ranon所说,所有的XQuery值都是不可变的,所以你不能更新一个变量。但是如果你真的需要一个可更新的数字(不应该太频繁),你可以使用递归:
declare function local:loop($seq, $count) {
if(empty($seq)) then ()
else
let $prod := $seq[1],
$count := $count + 1
return (
<count>{ $count }</count>,
local:loop($seq[position() > 1], $count)
)
};
local:loop($collection, 0)
这完全符合您对示例的预期。
在XQuery 3.0中,该函数的一个更通用的版本甚至在标准库中定义:fn:fold-right($f, $zero, $seq)
也就是说,在您的示例中,您绝对应该使用at $count
,如@tohuwawohu所示。
发布于 2012-04-24 09:16:49
不可变变量
XQuery是一个functional programming language,它涉及不可变变量,因此您的不能更改变量的值。另一方面,您可以使用强大的函数集合,这解决了许多日常编程问题。
let $count := 0
for $prod in $collection]
let $count := $count + 1
return
<counter>{$count }</counter>
第1行中的let $count
在所有作用域中定义了这个变量,在本例中,所有作用域都在后面。第3行中的let $count
定义了一个新的$count
,它是0+1
,在此代码块中的所有后续行中都有效-这是没有定义的。因此,您确实将$count
递增了三次,但是立即丢弃了结果。
BaseX的查询信息显示了该查询的优化版本
for $prod in $collection
return element { "counter" } { 1 }
解决方案
要获得$collection
中的元素总数,您可以使用
return count($collection)
有关XQuery函数的列表,您可以查看XQuery part of functx,其中既包含XQuery函数的列表,也包含一些可以作为模块包含的其他有用的函数。
https://stackoverflow.com/questions/10294677
复制