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

🧠 Test Your Knowledge

What does FLWOR stand for?