2016-04-05 3 views
3

Немного трудно объяснить проблему в названии, так вот конкретный пример XML-файл и что код должен возвращать:XQUERY - подсчитать количество конкретных элементов с определенными атрибутами

<objects> 
    <object type='Brick' to='Up' /> 
    <object type='Cross' to='Down' /> 
    <object type='Brick' to='Left' /> 
    <object type='Brick' to='Up' /> 
    <object type='Circle' to='Right' /> 
    <object type='Circle' to='Right' /> 
</objects> 

Так что я 3 типа объектов: Brich, Circle и Cross, а также от 3 до, вверх, вниз, влево и вправо. Я хочу использовать XQuery, чтобы получить что-то вроде:

<objects> 
    <object type="Brick"> 
     <where to="Up" count="2" /> 
     <where to="Down" count="0" /> 
     <where to="Left" count="1" /> 
     <where to="Right" count="2" /> 
    </object> 
    <object type="Cross"> 
    . 
    . 
    . 
</objects> 

в основном, для каждого типа, я хочу, чтобы получить вложенные элементы вправо, вниз, влево и вверх, сколько раз они появляются для этого типа объекта. Я знаю, что, поскольку есть ограничения, я могу просто запрограммировать каждый подсчет и иметь кучу утверждений let, но я надеюсь, что кто-то может предложить лучший способ сделать это.

+0

Можете ли вы использовать XQuery 3 для группировки ваших элементов? –

+0

Я пытаюсь сделать это в Xquery 1.0 –

ответ

2

Вот полностью динамическая версия (нет жестко кодирования), distinct-values(...) является ваш друг в XQuery 1.0:

<objects>{ 
    let $directions := distinct-values(//@to) 
    for $type in distinct-values(//object/@type) 
    return <object type="{$type}">{ 
    for $to in $directions 
    return <where to="{$to}" count="{count(//object[@type = $type and @to = $to])}"/> 
    }</object> 
}</objects> 
0

Если типы объектов и направления довольно статичны, и у вас много объектов, то вам, вероятно, лучше не перечислять известные значения, а не использовать distinct-values, что может быть медленным на больших последовательностях.

let $object-types := ('Brick', 'Circle', 'Cross') 
let $directions := ('Up', 'Down', 'Left', 'Right') 
for $t in $object-types 
return element object { 
    attribute type { $t }, 
    for $d in $directions 
    let $count := count($objects/object[@type = $t][@to = $d]) 
    return element where { 
    attribute to { $d }, 
    attribute count { $count } 
    } 
} 

Но если вы не могли знать значения входных загодя вы могли бы построить эти значения динамически, как:

let $object-types := distinct-values($objects/object/@type) 
... 
Смежные вопросы