Last modified on 3 October 2014, at 10:24

XQuery/FLWOR Expression

MotivationEdit

You have a sequence of items and you want to create a report that contains these items.

MethodEdit

We will use a basic XQuery FLWOR expression to iterate through each of the items in a sequence. The five parts of a FLWOR expression are:

  • for - specifies what items in the sequence you want to select (optional)
  • let - used to create temporary names used in the return (optional)
  • where - limit items returned (optional)
  • order - change the order of the results (optional)
  • return - specify the structure of the data returned (required)

Lets assume we have a sample file of books that looks like this:

<books>
   <book>
      <title>Introduction to XQuery</title>
      <description>A beginner's guide to XQuery that covers sequences and FLOWR expressions</description>
      <type>softcover</type>
      <sales-count>155</sales-count>
      <price>$19.95</price>
   </book>
  <book>
      <title>Document Transformations with XQuery</title>
      <description>How to transform complex documents like DocBook, TEI and DITA</description>
      <type>hardcover</type>
      <sales-count>105</sales-count>
      <price>$59.95</price>
   </book>
   ...more books here....
 </books>

Here is a simple example of a FLWOR expression that will return only the titles and prices of the books sorted by title:

for $book in doc("catalog.xml")/books/book
   let $title := $book/title/text()
   let $price := $book/price/text()
   where xs:decimal($price) gt 50.00
   order by $title
   return
      <book>
         <title>{$title}</title>
         <price>{$price}</price>
      </book>

This XQuery FLWOR expression will return all books that have a price over $50.00. Note that we have not just one but two let statements after the for loop. We also add a where clauses to restrict the results to books over $50.00. The results are sorted by the title and the result is a new sequence of book items with both the price and the title in them.

Using the "to" function to generate a range of valuesEdit

You can also express a range of values from one number to another number by placing the keyword "to" between two numbers in a sequence.

The following generates a list of values from 1 to 10.

xquery version "1.0";
 
<list>
   {for $i in (1 to 10)
      return
        <value>{$i}</value>
    }
</list>

Using the "at" function as a counterEdit

You can add the "at $my-counter" to add a numerical counter for each item in a FLOWR loop

for $item at $count in $items
   return
      <item>
         <counter>{$count}</counter>
         {$item/*}
      </item>

Comparing FLWOR with procedural for loopsEdit

In traditional procedural programing (JavaScript, Java, .Net, Perl, PHP and Python) each loop is executed sequentially, one after another. With a FLWOR loop each iteration executes in parallel and no communication is allowed between the threads.

As a result you can not increment variables in the traditional way you would in other languages.