XML Tutorial · XPath, XSLT and XQuery · Lesson 16 of 28

XQuery

Querying XML like a database with XQuery FLWOR expressions, constructing results, and XQuery 3.1 maps and JSON.

Create a free account to save this page, take notes and track your progress. Sign in

What XQuery is

XQuery is to XML what SQL is to tables. It extends XPath with FLWOR expressions (for, let, where, order by, return) and element constructors. It's used in XML databases (BaseX, eXist-db, MarkLogic) and with Saxon. Every XPath expression is also an XQuery expression.

for $p in //product          (: for: loop :)
let $value := $p/price * $p/stock   (: let: bind a variable :)
where $p/stock > 0           (: where: filter :)
order by $value descending   (: order by: sort :)
return <line>{ $p/name/text() }</line>   (: return: build a result :)

The examples on this page were run with Saxon-HE (XQuery 3.1); there's no in-browser runner for XQuery.

A FLWOR expression
let $shop := <shop>
  <product sku="TEA-01" category="drinks"><name>Green tea</name><price>3.50</price><stock>40</stock></product>
  <product sku="COF-02" category="drinks"><name>Coffee beans</name><price>9.90</price><stock>0</stock></product>
  <product sku="MUG-07" category="kitchen"><name>Camel mug</name><price>12.00</price><stock>15</stock></product>
  <product sku="PAN-03" category="kitchen"><name>Frying pan</name><price>29.00</price><stock>4</stock></product>
</shop>
for $p in $shop/product
let $value := xs:decimal($p/price) * xs:integer($p/stock)
where $p/stock > 0
order by $value descending
return <line sku="{ $p/@sku }" value="{ $value }">{ $p/name/text() }</line>

Output

<line sku="MUG-07" value="180">Camel mug</line>
<line sku="TEA-01" value="140">Green tea</line>
<line sku="PAN-03" value="116">Frying pan</line>

Run this on your computer — see “Get Started” for setup.

Grouping and aggregation

Group by
let $shop := <shop>
  <product sku="TEA-01" category="drinks"><name>Green tea</name><price>3.50</price><stock>40</stock></product>
  <product sku="COF-02" category="drinks"><name>Coffee beans</name><price>9.90</price><stock>0</stock></product>
  <product sku="MUG-07" category="kitchen"><name>Camel mug</name><price>12.00</price><stock>15</stock></product>
  <product sku="PAN-03" category="kitchen"><name>Frying pan</name><price>29.00</price><stock>4</stock></product>
</shop>
return <report>{
  for $p in $shop/product
  group by $category := $p/@category/string()
  order by $category
  return <category name="{ $category }" products="{ count($p) }"
                   total="{ format-number(sum($p/price), '0.00') }"/>
}</report>

Output

<report>
   <category name="drinks" products="2" total="13.40"/>
   <category name="kitchen" products="2" total="41.00"/>
</report>

Run this on your computer — see “Get Started” for setup.

XQuery 3.1: maps, arrays and JSON

XML to JSON with maps
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare option output:method "json";
declare option output:indent "yes";

let $shop := <shop>
  <product sku="TEA-01" category="drinks"><name>Green tea</name><price>3.50</price><stock>40</stock></product>
  <product sku="COF-02" category="drinks"><name>Coffee beans</name><price>9.90</price><stock>0</stock></product>
  <product sku="MUG-07" category="kitchen"><name>Camel mug</name><price>12.00</price><stock>15</stock></product>
  <product sku="PAN-03" category="kitchen"><name>Frying pan</name><price>29.00</price><stock>4</stock></product>
</shop>
return map {
  "products": array {
    for $p in $shop/product[stock > 0]
    return map { "sku": $p/@sku/string(), "price": xs:decimal($p/price) }
  },
  "count": count($shop/product)
}

Output

{
  "products": [
    { "sku":"TEA-01", "price":3.5 },
    { "sku":"MUG-07", "price":12 },
    { "sku":"PAN-03", "price":29 }
  ],
  "count": 4
}

Run this on your computer — see “Get Started” for setup.

Test yourself

What does the W in FLWOR stand for?

  1. where
  2. while
  3. with
  4. write
Show answer

Answer: where

FLWOR = for, let, where, order by, return.

Was this page helpful?