Joanmacat
Joanmacat

Reputation: 1541

Xquery 3.0 group by attribute value

In my adventure to learn Xquery and Xpath I'm with a problem trying to group apples with their category.

I'm using XPath 3.0, and XML 1.0 in my document.

I have this:

<fruits>

    <fruit>
        <name>Apple</name>
        <category>Summer</category>
    </fruit>

    <fruit>
        <name>Mondarine</name>
        <category>Autumm</category>
    </fruit>

    <fruit>

        <name>Kiwi</name>
        <category>Summer</category>
    </fruit>

    <fruit>
        <name>Aguacate</name>
        <category>Winter</category>
    </fruit>

    <fruit>
        <name>Banana</name>
        <category>Winter</category>
    </fruit>

</fruits>

I need the next output:

<summary>
<category = "Summer"/>
<item list-names = "Apple, Kiwi"/>
</summary>

<summary>
<category = "Autumm"/>
<item list-names = "Mondarine"/>
</summary>

<summary>
<category = "Winter"/>
<item list-names = "Aguacate, Banana"/>
</summary>

How can I do this with a XQuery?

Probably is very easy but I don't see it yet and I'm struggling a lot to solve this. Thank you for your help!

Upvotes: 2

Views: 380

Answers (2)

wst
wst

Reputation: 11771

You can solve this in XQuery by iterating over the distinct values of category names, then querying the names of items that match the category using XPath:

for $category in distinct-values($fruits/fruit/category)
let $items := $fruits/fruit[category = $category]/name
return 
  <summary>
    <category>{ $category }</category>
    <item list-names="{ string-join($items, ', ') }"/>  
  </summary>

Note that your sample output is not valid XML:

<category = "Summer"/>

Your options for storing that value are either in an attribute:

<summary category="Summer"> ...
<category value="Summer"/> ...

Or in an element, which is what I chose for this answer:

<summary>
  <category>Summer</category>
  <item list-names="Apple, Kiwi"/>
</summary>
<summary>
  <category>Autumm</category>
  <item list-names="Mondarine"/>
</summary>
<summary>
  <category>Winter</category>
  <item list-names="Aguacate, Banana"/>
</summary>

Upvotes: 1

Martin Honnen
Martin Honnen

Reputation: 167516

As your subject line mentions XQuery 3.0 you could also use group by:

for $fruit in fruits/fruit
group by $cat := $fruit/category
return <summary>
  <category>{$cat}</category>
  <items list="{string-join($fruit/name, ', ')}"/>
</summary>

Upvotes: 1

Related Questions