1
votes

I'm looking to iterate a sample bookstore returning each book as a result. How is this accomplished with XQuery and FLOWR?

My best attempt so far:

thufir@dur:~/basex/w3schools$ 
thufir@dur:~/basex/w3schools$ basex each.xq 
<book category="cooking">
  <title lang="en">Everyday Italian</title>
  <author>Giada De Laurentiis</author>
  <year>2005</year>
  <price>30.00</price>
</book>
<book category="children">
  <title lang="en">Harry Potter</title>
  <author>J K. Rowling</author>
  <year>2005</year>
  <price>29.99</price>
</book>
<book category="web">
  <title lang="en">XQuery Kick Start</title>
  <author>James McGovern</author>
  <author>Per Bothner</author>
  <author>Kurt Cagle</author>
  <author>James Linn</author>
  <author>Vaidyanathan Nagarajan</author>
  <year>2003</year>
  <price>49.99</price>
</book>
<book category="web" cover="paperback">
  <title lang="en">Learning XML</title>
  <author>Erik T. Ray</author>
  <year>2003</year>
  <price>39.95</price>
</book>thufir@dur:~/basex/w3schools$ 
thufir@dur:~/basex/w3schools$ 
thufir@dur:~/basex/w3schools$ cat each.xq 
let $db := db:open("com.w3schools.books")
for $item in $db
return $item/bookstore/book
thufir@dur:~/basex/w3schools$ 

Only I'd "kinda" like each result differentiated a bit more. Can I chain or pipe results from one Xquery to another perhaps? The output I would want would be more like serializing each book to an xml file.

the data:

thufir@dur:~/basex/w3schools$ 
thufir@dur:~/basex/w3schools$ basex all.xq 
<bookstore>
  <book category="cooking">
    <title lang="en">Everyday Italian</title>
    <author>Giada De Laurentiis</author>
    <year>2005</year>
    <price>30.00</price>
  </book>
  <book category="children">
    <title lang="en">Harry Potter</title>
    <author>J K. Rowling</author>
    <year>2005</year>
    <price>29.99</price>
  </book>
  <book category="web">
    <title lang="en">XQuery Kick Start</title>
    <author>James McGovern</author>
    <author>Per Bothner</author>
    <author>Kurt Cagle</author>
    <author>James Linn</author>
    <author>Vaidyanathan Nagarajan</author>
    <year>2003</year>
    <price>49.99</price>
  </book>
  <book category="web" cover="paperback">
    <title lang="en">Learning XML</title>
    <author>Erik T. Ray</author>
    <year>2003</year>
    <price>39.95</price>
  </book>
</bookstore>thufir@dur:~/basex/w3schools$ 
thufir@dur:~/basex/w3schools$ 
thufir@dur:~/basex/w3schools$ cat all.xq 
let $db := db:open("com.w3schools.books")
return $db
thufir@dur:~/basex/w3schools$ 

Certainly, possible to return a single result:

thufir@dur:~/basex/w3schools$ 
thufir@dur:~/basex/w3schools$ basex singleBook.xq 
<book category="cooking">
  <title lang="en">Everyday Italian</title>
  <author>Giada De Laurentiis</author>
  <year>2005</year>
  <price>30.00</price>
</book>thufir@dur:~/basex/w3schools$ 
thufir@dur:~/basex/w3schools$ cat singleBook.xq 
let $db := db:open("com.w3schools.books")
for $x in $db
return $x/bookstore/book[1]
thufir@dur:~/basex/w3schools$ 

However, that's just a single book. How would I iterate through returning each book?

1
Can you post a sample of your desired output? It's not clear from your question. - Jack Fleeting
If you return $x/bookstore/book instead of return $x/bookstore/book[1] you return all book elements obviously instead of only the first. Seems too obvious so I am not sure what you are looking for. The whole idea of "iterating" in the context of a declarative language is perhaps not the best objective to start with when using XQuery. - Martin Honnen
I don't know how to describe the desired output @JackFleeting but I guess what I want is book #1, then book #2, etc. But, individually not as a single result... - Thufir
What kind of result type do you expect, if you select several book elements then the result is a sequence of book elements e.g. element(book)* in that XPath/XQuery sequence types type system. It doesn't really matter whether for the type whether you use db:open('db-name')/bookstore/book or for $doc in db:open('db-name'), $store in $doc/bookstore, $book in $store/book return $book, the result is a sequence of book elements. - Martin Honnen
if sequence means a sequence of distinct items @MartinHonnen, then it's that sequence which I'm after. I suppose it's already a sequence of book items. I'm thinking of an analog to an array, List or other collection. - Thufir

1 Answers

2
votes

Since it's not clear exactly how you want the output, try something like this (I made up some structure) - it may get you close to your ultimate destination...

for $x in $db/book
return 
(<book-info>
{$x/title/text()}, {$x/author[1]/text()}
</book-info>,'&#10;')

Output:

<book-info>
Everyday Italian, Giada De Laurentiis
</book-info>


<book-info>
Harry Potter, J K. Rowling
</book-info>


<book-info>
XQuery Kick Start, James McGovern
</book-info>


<book-info>
Learning XML, Erik T. Ray
</book-info>