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.
