XQuery Functions

XQuery supports a large library of built-in functions and also lets you define your own. Functions in XQuery work on sequences, strings, numbers, dates, and nodes. They make complex data operations concise and reusable.

Aggregate Functions

count()

Returns the number of items in a sequence.

count(doc("orders.xml")/orders/order)          → total orders
count(doc("orders.xml")/orders/order[@status='pending'])  → pending only

sum()

Returns the total of a numeric sequence.

sum(doc("orders.xml")/orders/order/total)
    → sum of all order totals

avg()

Returns the average of a numeric sequence.

avg(doc("employees.xml")/company/employee/salary)
    → average salary across all employees

min() and max()

Return the smallest and largest values in a sequence.

min(doc("products.xml")/catalog/product/price)    → cheapest product price
max(doc("products.xml")/catalog/product/price)    → most expensive product price

Combined Example

let $prices := doc("products.xml")/catalog/product/price
return
  <priceReport>
    <count>{ count($prices) }</count>
    <total>{ sum($prices) }</total>
    <average>{ avg($prices) }</average>
    <lowest>{ min($prices) }</lowest>
    <highest>{ max($prices) }</highest>
  </priceReport>

String Functions

string()

Converts a value to its string representation.

string(42)         → "42"
string(true())     → "true"
string(/book/price) → text content of price

string-length()

Returns the number of characters in a string.

string-length("Hello World")       → 11
string-length($emp/name)           → character count of name

concat()

Joins strings together.

concat("INR ", $product/price)         → "INR 1299"
concat($emp/firstName, " ", $emp/lastName)

substring()

Extracts part of a string by position.

substring("Bangalore", 1, 4)      → "Bang"
substring($date, 1, 4)            → extracts 4-digit year from "2024-03-15"

contains()

Tests whether one string contains another. Returns true or false.

contains("Hello World", "World")   → true
contains($emp/role, "Manager")     → true if role mentions Manager

starts-with() and ends-with()

starts-with("OrderID-2024", "OrderID")  → true
ends-with("report.xml", ".xml")        → true

upper-case() and lower-case()

XQuery 1.0+ includes these — unlike XPath 1.0 which requires translate().

upper-case("hello")      → "HELLO"
lower-case("WORLD")      → "world"
upper-case($emp/name)    → name in all caps

normalize-space()

Removes leading/trailing whitespace and collapses internal spaces.

normalize-space("  Hello   World  ")  → "Hello World"

replace()

Replaces all occurrences of a pattern (regex supported).

replace("Hello World", "World", "XQuery")  → "Hello XQuery"
replace($phone, "[^0-9]", "")             → removes non-digits from phone number

tokenize()

Splits a string into a sequence of strings based on a delimiter.

tokenize("red green blue", " ")    → ("red", "green", "blue")
tokenize("2024-03-15", "-")        → ("2024", "03", "15")

Sequence Functions

distinct-values()

Returns unique values from a sequence — duplicates removed.

distinct-values(doc("employees.xml")/company/employee/@dept)
    → unique department names: "Engineering", "Design", "HR"

reverse()

Returns the sequence in reverse order.

reverse((1, 2, 3, 4, 5))     → (5, 4, 3, 2, 1)

subsequence()

Returns a subset of a sequence by position.

subsequence((10, 20, 30, 40, 50), 2, 3)  → (20, 30, 40)
    (starts at position 2, takes 3 items)

Boolean and Comparison Functions

not()

not(true())                    → false
not(contains($name, "Junior")) → true if name has no "Junior"

exists() and empty()

exists(doc("file.xml")/root/element)    → true if at least one element found
empty(doc("file.xml")/root/element)     → true if no elements found

User-Defined Functions

XQuery lets you define your own functions using the declare function syntax. This makes complex logic reusable across the query.

declare function local:discount($price as xs:decimal, $rate as xs:decimal)
  as xs:decimal {
  $price - ($price * $rate)
};

for $product in doc("products.xml")/catalog/product
return
  <item>
    <name>{ $product/name/text() }</name>
    <originalPrice>{ $product/price/text() }</originalPrice>
    <discountedPrice>{ local:discount($product/price, 0.10) }</discountedPrice>
  </item>

Output

<item>
  <name>Laptop Stand</name>
  <originalPrice>1500</originalPrice>
  <discountedPrice>1350</discountedPrice>
</item>

Conditional Functions — if/then/else

XQuery uses if/then/else as an expression, not a statement — it always returns a value.

for $emp in doc("employees.xml")/company/employee
return
  <result>
    <name>{ $emp/name/text() }</name>
    <level>{
      if ($emp/salary > 80000) then "Senior"
      else if ($emp/salary > 60000) then "Mid-level"
      else "Junior"
    }</level>
  </result>

Key Points to Remember

  • Aggregate functions: count(), sum(), avg(), min(), max() — work on numeric sequences.
  • String functions include contains(), starts-with(), ends-with(), replace(), tokenize().
  • XQuery includes upper-case() and lower-case() — unlike XPath 1.0.
  • distinct-values() returns unique items; exists() and empty() test sequence membership.
  • User-defined functions use declare function with a namespace prefix (local: by convention).
  • if/then/else is an expression — it always returns a value and fits inside any expression.

Leave a Comment

Your email address will not be published. Required fields are marked *