[xquery-talk] How to invert the hierarchy of an xml?

Joe Wicentowski joewiz at gmail.com
Wed Nov 2 19:38:00 PST 2011


Hi Peng,

Welcome to the XQuery talk mailing list.

> Suppose that I have an xml where each Article has it is own Journals.
> But since the Journals may be the same. I'd like to group the articles
> by Journals. I'm still learning XQuery. Could anybody show me how to
> do the conversion using XQuery?

I suggest making use of XQuery 3.0's "group by" clause.  A nice
example of "group by" happens to be on the eXist-db blog, describing
exist-db's support for this clause
(http://atomic.exist-db.org/HowTo/XQuery3/GroupByClause) and providing
an example that is quite similar to yours, sans the need to filter out
the Journal child of the Article element in the results.  Chances are
folks will suggest more elegant approaches to that portion of the
code, but this query does the trick.  Below is the code for your case.

Cheers,
Joe


xquery version "3.0";

let $library := <Library>
 <Article>
   <Title>title1</Title>
   <Author>author1</Author>
   <Journal>journal1</Journal>
 </Article>
 <Article>
   <Title>title2</Title>
   <Author>author2</Author>
   <Journal>journal1</Journal>
 </Article>
 <Article>
   <Title>title3</Title>
   <Author>author3</Author>
   <Journal>journal2</Journal>
 </Article>
 <Article>
   <Title>title4</Title>
   <Author>author4</Author>
   <Journal>journal2</Journal>
 </Article>
</Library>

let $reordered :=
    <Library>{
        for $article in $library/Article
        group $article as $journal-articles by $article/Journal as $journal
        order by $journal
        return
            <journal title="{$journal}">{
                for $article in $journal-articles
                return
                    <Article>{
                        $article/*[not(name(.) eq 'Journal')]
                    }</Article>
            }</journal>
    }</Library>

return
    $reordered


More information about the talk mailing list