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

时间:2018-11-15 16:30:59

标签: xml recursion xquery

我试图递归地生成一个在星期一数据库中彼此相邻的国家的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?

1 个答案:

答案 0 :(得分:0)

一种解决方案是使用一个累加参数,在该参数中您从空序列开始收集结果序列:

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>
  ...