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.
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.
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
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
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?
wherewhilewithwrite
Show answer
Answer: where
FLWOR = for, let, where, order by, return.