2016-03-14 3 views
3

У меня есть XML, который выглядит следующим образом:XQuery присоединиться результат

<?xml version="1.0"?> 
<root> 
    <flight> 
    <number>10001</number> 
    <airport>LAX</airport> 
    <dest> 
     <airport>SFO</airport> 
    </dest> 
    </flight> 
    <flight> 
    <number>10002</number> 
    <airport>LAX</airport> 
    <dest> 
     <airport>JFK</airport> 
    </dest> 
    </flight> 
    <flight> 
    <number>10003</number> 
    <airport>JFK</airport> 
    <dest> 
     <airport>LAX</airport> 
    </dest> 
    </flight> 
</root> 

Использование XQuery Мне нужно, чтобы получить что-то вроде этого:

<res> 
    <airport code="LAX"> 
     <deps>2</deps> 
     <dests>1</deps> 
    </airport> 
    <airport code="JFK"> 
     <deps>1</deps> 
     <dests>1</deps> 
    </airport> 
    <airport code="SFO"> 
     <deps>0</deps> 
     <dests>1</deps> 
    </airport> 
</res> 

Я сделал это, и может получить правильный результат, однако, мой запрос может найти только deps или dests, но не оба.

Вот как я подошел к проблеме.

let $all := doc("flights.xml")/root 
for $airports in distinct-values($all/flight//*/airport) (:here I get all airport codes:) 
order by $airports 

for $nr-dep in $all/flight/airport 

where $nr-dep = $airports 
group by $airports 

return <res> 
      <airport name="{$airports}"><deps>{count($nr-dep)}</deps></airport> 
     </res> 

Здесь я получаю счет отправления. Я могу легко получить destionations, заменив for $nr-dep in $all/flight/airport на for $nr-dep in $all/flight/dest/airport, однако я не могу найти способ показать оба с тем же результатом, что и ожидаемый XML.

ответ

3

Почему не просто:

for $airport in distinct-values($all//airport) 
order by $airport 
return <airport code="{$airport}"> 
    <deps>{count($all//flight/airport[. = $airport])}</deps> 
    <dests>{count($all//dest/airport[. = $airport])}</dests> 
</airport> 
+0

Он работает, однако, я до сих пор начал работу с XQuery и не могу понять все детали за это и что заставляет его работать. Я не понимаю '//' и '[. = $ airport] '. Большое спасибо. – Enve

+1

'//' вызывает рекурсивный поиск дерева, т. Е. * «Все потомки, а не только дети» *. Это сокращение для 'descendant-or-self :: node()', и это XPath, а не XQuery. '[. = $ value] 'тоже XPath, это означает *", если этот узел имеет текстовое значение '$ value' * *. Кажется, вам нужно сначала прочитать на XPath. :) – Tomalak

4

Вот версия с использованием group by:

<res>{ 
    for $airport in //airport 
    group by $code := $airport/text() 
    order by $code 
    return <airport code="{$code}"> 
     <deps>{ count($airport/parent::flight) }</deps> 
     <dests>{ count($airport/parent::dest) }</dests> 
    </airport> 
}</res> 
+1

Я предполагаю, что явный порядок сортировки после группировки будет хорошей вещью. От чтения спецификации я не думаю, что определенный порядок гарантирован 'group by'. – Tomalak

+0

Хороший момент, я забыл об этом в исходном запросе. Я уточню свой ответ. –

+0

Я думаю, что это более элегантно, чем мое решение. – Tomalak