XQuery FLWOR
Master the FLWOR expression syntax
đ What is FLWOR?
FLWOR (pronounced "flower") stands for For, Let, Where, Order by, Return. It's XQuery's powerful expression for iterating, filtering, sorting, and transforming XML data in a structured way.
for $x in doc("data.xml")//item
where $x/price < 50
return $x/name
FLWOR Components
FLWOR expressions provide structured control over XML queries. Each component serves a specific purpose: iteration, variable binding, filtering, sorting, and output generation, making complex queries readable and maintainable.
For
Iterate through elements
Let
Bind variables to values
Where
Filter results by condition
Order by
Sort results
Return
Specify output format
đš Basic FLWOR Structure
Understanding the FLWOR syntax:
đ Sample XML (products.xml):
<products>
<product>
<name>Laptop</name>
<price>999</price>
<stock>15</stock>
</product>
<product>
<name>Mouse</name>
<price>25</price>
<stock>50</stock>
</product>
<product>
<name>Keyboard</name>
<price>75</price>
<stock>30</stock>
</product>
</products>
đ Complete FLWOR Example:
for $product in doc("products.xml")//product
let $total := $product/price * $product/stock
where $product/price < 100
order by $product/price descending
return
<item>
<name>{$product/name/text()}</name>
<value>{$total}</value>
</item>
Result:
<item>
<name>Keyboard</name>
<value>2250</value>
</item>
<item>
<name>Mouse</name>
<value>1250</value>
</item>
đš The FOR Clause
Iterate through XML elements:
đ Simple FOR:
(: Loop through all products :)
for $p in doc("products.xml")//product
return $p/name
đ Multiple FOR Clauses:
(: Nested iteration :)
for $p in doc("products.xml")//product
for $attr in ("name", "price")
return concat($attr, ": ", $p/*[name()=$attr])
đš The LET Clause
Bind variables to values for reuse:
đ Using LET:
for $product in doc("products.xml")//product
let $discount := $product/price * 0.10
let $final := $product/price - $discount
return
<sale>
<item>{$product/name/text()}</item>
<original>{$product/price/text()}</original>
<discounted>{$final}</discounted>
</sale>
Result (first item):
<sale>
<item>Laptop</item>
<original>999</original>
<discounted>899.1</discounted>
</sale>
đš The WHERE Clause
Filter results based on conditions:
đ Simple WHERE:
(: Products under $100 :)
for $product in doc("products.xml")//product
where $product/price < 100
return $product/name
đ Multiple Conditions:
(: Affordable items with good stock :)
for $product in doc("products.xml")//product
where $product/price < 100 and $product/stock > 20
return
<available>
{$product/name}
{$product/stock}
</available>
Result:
<available>
<name>Mouse</name>
<stock>50</stock>
</available>
<available>
<name>Keyboard</name>
<stock>30</stock>
</available>
đš The ORDER BY Clause
Sort results in ascending or descending order:
đ Ascending Order:
(: Sort by price (low to high) :)
for $product in doc("products.xml")//product
order by $product/price
return
<item>
{$product/name}
{$product/price}
</item>
đ Descending Order:
(: Sort by stock (high to low) :)
for $product in doc("products.xml")//product
order by $product/stock descending
return $product/name
đ Multiple Sort Keys:
(: Sort by price, then by name :)
for $product in doc("products.xml")//product
order by $product/price, $product/name
return $product/name
đš The RETURN Clause
Specify what to output:
đ Return Elements:
for $product in doc("products.xml")//product
return $product/name
đ Return New XML:
for $product in doc("products.xml")//product
return
<summary>
<title>{$product/name/text()}</title>
<cost>${$product/price/text()}</cost>
</summary>
đ Return Text:
for $product in doc("products.xml")//product
return concat($product/name, " costs $", $product/price)
đš Complete FLWOR Example
Putting it all together:
(: Generate sales report :)
<report>
{
for $product in doc("products.xml")//product
let $revenue := $product/price * $product/stock
let $category := if ($product/price > 500)
then "Premium"
else "Standard"
where $product/stock > 10
order by $revenue descending
return
<product-summary>
<name>{$product/name/text()}</name>
<category>{$category}</category>
<potential-revenue>{$revenue}</potential-revenue>
</product-summary>
}
</report>
Result:
<report>
<product-summary>
<name>Laptop</name>
<category>Premium</category>
<potential-revenue>14985</potential-revenue>
</product-summary>
<product-summary>
<name>Keyboard</name>
<category>Standard</category>
<potential-revenue>2250</potential-revenue>
</product-summary>
<product-summary>
<name>Mouse</name>
<category>Standard</category>
<potential-revenue>1250</potential-revenue>
</product-summary>
</report>
đš FLWOR Best Practices
- Order matters: FOR and LET before WHERE
- Use LET: For calculations used multiple times
- WHERE filtering: Filter early to improve performance
- ORDER BY: Always comes before RETURN
- RETURN: Must be the last clause
-
Comments:
Use
(: :)to document complex queries