如何更改XQuery中递归函数输出的XML



我正试图在mondial数据库中递归地生成一个国家/地区的XML文档。文件应该说明你需要跨越多少边界才能到达这个国家,以及跨越的国家总数。

XML应该如下所示:

<from_swe_cross>
<cross num="1" sum="2">
<country>Finland</country>
<country>Norway</country>
</cross>
<cross num="2" sum="3">
<country>Russia</country>
</cross>

我知道如何生成一个你可以去的国家列表,但不知道如何正确格式化,也不知道有多少次越境或越境的国家总数。

我现在的代码是:

declare function local:crossing($stack, $seen, $level, $sum) {
if(empty($stack)) then $seen
else (
let $country := $stack[1]
let $neighbors :=
for $code in $country/border/@country[not(. = $seen/@car_code)]
return $country/../country[@car_code = $code]
return local:crossing(($neighbors, $stack[position() > 1]), ($seen, $neighbors), $level + 1, $sum + count($neighbors))
)
};
<from_swe_cross>{
local:crossing(db:open('mondial')//country[@car_code = 'S'], db:open('mondial')//country[@car_code = 'S'], 1, 0)/name
}
</from_swe_cross>

但这只列出了你可以跨越的所有国家,比如:

<from_swe_cross>
<name>Albania</name>
<name>Greece</name>
<name>Macedonia</name>
<name>Serbia</name>
<name>Montenegro</name>
...
</from_swe_cross>

如何生成正确的XML?

一种解决方案是使用一个累积参数来收集结果序列,从一个空序列开始:

declare function local:crossing($stack, $seen, $level, $sum, $out) {
if(empty($stack)) then $out
else (
let $country := $stack[1]
let $neighbors :=
for $code in $country/border/@country[not(. = $seen/@car_code)]
return $country/../country[@car_code = $code]
let $sum := $sum + count($neighbors)
return local:crossing(
($neighbors, $stack[position() > 1]),
($seen, $neighbors),
$level + 1,
$sum,
($out, <cross num="{$level}" sum="{$sum}">{$neighbors/name}</cross>)
)
)
};
<from_swe_cross>{
local:crossing(
db:open('mondial')//country[@car_code = 'S'],
db:open('mondial')//country[@car_code = 'S'],
1, 0, ()
)
}
</from_swe_cross>

结果看起来就像上面显示的一样:

<from_swe_cross>
<cross num="1" sum="2">
<name>Finland</name>
<name>Norway</name>
</cross>
<cross num="2" sum="3">
<name>Russia</name>
</cross>
<cross num="3" sum="15">
<name>Belarus</name>
<name>Latvia</name>
<name>Lithuania</name>
<name>Poland</name>
<name>Ukraine</name>
<name>Estonia</name>
<name>China</name>
...

未找到新目的地的步骤显示为空的cross元素。如果你愿意,你可以抑制这些。

...
<cross num="4" sum="15"/>
<cross num="5" sum="15"/>
<cross num="6" sum="15"/>
<cross num="7" sum="18">
<name>Czech Republic</name>
<name>Germany</name>
<name>Slovakia</name>
</cross>
...

最新更新