Поскольку не все условия охвата были даны в исходном вопросе, я предлагаю несколько ответов. Все они основаны на одном и том же прологе запроса и следующих предположениях (и, возможно, некоторых других):
- искомый пункт отправления и пункт назначения существуют
- все пункты отправления и назначения встречаются только один раз
- нет циклов (например,
b
→ c
→ b
)
Пролог запроса
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
Использование следующего брата
Предположение, то же самое здесь: место назначения происходит после источника.
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)
person
Christian Grün
schedule
01.03.2018