在XQuery 3.0中选择元素范围

时间:2018-03-01 08:23:47

标签: basex xquery-3.0

我有以下xml数据结构

<journey>
<leg origin='a' dest='b' />
<leg origin='b' dest='c' />
<leg origin='c' dest='d' />
<leg origin='d' dest='e' />
<leg origin='e' dest='f' />
... and so on
</journey>

我想从legorigin='b'

选择dest='e'个元素

我尝试使用翻滚窗口,跟随兄弟,但似乎只能匹配第一个和最后一个元素,其间没有任何内容。

我在BaseX 8.6中使用XQuery 3.0

1 个答案:

答案 0 :(得分:3)

由于并非所有范围条件都在初始问题中给出,我提供了几个答案。所有这些都基于相同的查询序言和以下假设(可能还有其他一些):

  • 搜索的出发地和目的地
  • 所有起源&amp;目的地只出现一次
  • 没有周期(例如bcb

查询序言

declare variable $JOURNEY :=
  <journey>
    <leg origin='a' dest='b' />
    <leg origin='b' dest='c' />
    <leg origin='c' dest='d' />
    <leg origin='d' dest='e' />
    <leg origin='e' dest='f' />
  </journey>;
declare variable $ORIGIN := 'b';
declare variable $DEST := 'e';

使用翻滚窗口

假设:目的地发生在原点之后。

for tumbling window $legs in $JOURNEY/leg
    start $s when $s/@origin = $ORIGIN
    end   $e when $e/@dest   = $DEST
return $legs

使用follow-sibling

假设,同样在这里:目的地发生在原点之后。

let $origin := $JOURNEY/leg[@origin = $ORIGIN]
let $dest := $JOURNEY/leg[@dest = $DEST]
return (
  $origin,
  $origin/following-sibling::leg[. << $dest],
  $dest
)

使用节点比较

假设,同样在这里:目的地发生在原点之后。

let $origin := $JOURNEY/leg[@origin = $ORIGIN]
let $dest := $JOURNEY/leg[@dest = $DEST]
return $JOURNEY/leg[
  . is $origin or
  . >> $origin and . << $dest or
  . is $dest
]

递归方法

假设:订单无法保证。

declare function local:trace(
  $leg      as element(leg),
  $journey  as element(journey),
  $end      as xs:string
) as element(leg)* {
  $leg,
  for $dest in $leg/@dest[. != $end]
  return local:trace($journey/leg[@origin = $dest], $journey, $end)
};
local:trace($JOURNEY/leg[@origin = $ORIGIN], $JOURNEY, $DEST)