View Old View New View Both View Only Previous Next

This draft contains only sections that have differences from the version that it modified.

W3C

XPath and XQuery Functions and Operators 4.0

W3C Editor's Draft 23 February 2026

This version:
https://qt4cg.org/specifications/xpath-functions-40/
Latest version of XPath and XQuery Functions and Operators 4.0:
https://qt4cg.org/specifications/xpath-functions-40/
Most recent Recommendation of XPath and XQuery Functions and Operators:
https://www.w3.org/TR/2017/REC-xpath-functions-31-20170321/
Editor:
Michael Kay, Saxonica <http://www.saxonica.com/>

Please check the errata for any errors or issues reported since publication.

See also translations.

This document is also available in these non-normative formats: Specification in XML format and XML function catalog.


Abstract

This document defines constructor functions, operators, and functions on the datatypes defined in [XML Schema Part 2: Datatypes Second Edition] and the datatypes defined in [XQuery and XPath Data Model (XDM) 3.1]. It also defines functions and operators on nodes and node sequences as defined in the [XQuery and XPath Data Model (XDM) 3.1]. These functions and operators are defined for use in [XML Path Language (XPath) 4.0] and [XQuery 4.0: An XML Query Language] and [XSL Transformations (XSLT) Version 4.0] and other related XML standards. The signatures and summaries of functions defined in this document are available at: http://www.w3.org/2005/xpath-functions/.

A summary of changes since version 3.1 is provided at G Changes since 3.1.

Status of this Document

This version of the specification is work in progress. It is produced by the QT4 Working Group, officially the W3C XSLT 4.0 Extensions Community Group. Individual functions specified in the document may be at different stages of review, reflected in their History notes. Comments are invited, in the form of GitHub issues at https://github.com/qt4cg/qtspecs.

Dedication

The publications of this community group are dedicated to our co-chair, Michael Sperberg-McQueen (1954–2024).


17 Higher-order functions

17.2 Basic higher-order functions

The following functions take function items as an argument.

FunctionMeaning
fn:applyMakes a dynamic call on a function with an argument list supplied in the form of an array.
fn:chainApplies a sequence of functions starting with an initial input.
fn:do-untilProcesses a supplied value repeatedly, continuing when some condition is false, and returning the value that satisfies the condition.
fn:everyReturns true if every item in the input sequence matches a supplied predicate.
fn:filterReturns those items from the sequence $input for which the supplied function $predicate returns true.
fn:fold-leftProcesses the supplied sequence from left to right, applying the supplied function repeatedly to each item in turn, together with an accumulated result value.
fn:fold-rightProcesses the supplied sequence from right to left, applying the supplied function repeatedly to each item in turn, together with an accumulated result value.
fn:for-eachApplies the function item $action to every item from the sequence $input in turn, returning the concatenation of the resulting sequences in order.
fn:for-each-pairApplies the function item $action to successive pairs of items taken one from $input1 and one from $input2, returning the concatenation of the resulting sequences in order.
fn:highestReturns those items from a supplied sequence that have the highest value of a sort key, where the sort key can be computed using a caller-supplied function.
fn:index-whereReturns the positions in an input sequence of items that match a supplied predicate.
fn:lowestReturns those items from a supplied sequence that have the lowest value of a sort key, where the sort key can be computed using a caller-supplied function.
fn:partial-applyPerforms partial application of a function item by binding values to selected arguments.
fn:partitionPartitions a sequence of items into a sequence of non-empty arrays containing the same items, starting a new partition when a supplied condition is true.
fn:scan-leftProduces the sequence of successive partial results from the evaluation of fn:fold-left with the same arguments.
fn:scan-rightProduces the sequence of successive partial results from the evaluation of fn:fold-right with the same arguments.
fn:someReturns true if at least one item in the input sequence matches a supplied predicate.
fn:sortSorts a supplied sequence, based on the value of a number of sort keys supplied as functions.
fn:sort-withSorts a supplied sequence, according to the order induced by the supplied comparator functions.
fn:subsequence-whereReturns a contiguous sequence of items from $input, with the start and end points located by applying predicates.
fn:take-whileReturns items from the input sequence prior to the first one that fails to match a supplied predicate.
fn:transitive-closureReturns all the nodes reachable from a given start node by applying a supplied function repeatedly.
fn:while-doProcesses a supplied value repeatedly, continuing while some condition remains true, and returning the first value that does not satisfy the condition.

With all these functions, if the caller-supplied function fails with a dynamic error, this error is propagated as an error from the higher-order function itself.

17.2.2 fn:chain

Changes in 4.0  

  1. New in 4.0  [Issue 517 PRs 734 1233 20 October 2022]

Summary

Applies a sequence of functions starting with an initial input.

Signature
fn:chain(
$inputas item()*,
$functionsas fn(*)*
) as item()*
Properties

This function is deterministic, context-independent, and focus-independent.

Rules

Informally, the function behaves as follows:

  1. If $functions is empty, then $input is returned, otherwise let $f be the first member of $functions.

  2. Let $current-output be the result of fn:apply($f, $input-array) where $input-array is constructed according to the following rules.

    1. If $f has arity 1, let $input-array be an array containing $input as a single member.

    2. Otherwise ($f has arity not equal to 1) if $input is not an array then let $input-array be an array containing each item of $input as a separate member.

    3. Otherwise ($f has arity not equal to 1 and $input is already an array) let $input-array be $input itself.

  3. Repeat the process from step 1, passing $current-output as $input and fn:tail($functions) as $functions.

Formal Equivalent

The effect of the function is equivalent to the result of the following XPath expression.

let $apply := fn($x, $f)  {
  fn:apply($f,
    if (function-arity($f) eq 1) then [ $x ]
    else if ($x instance of array(*)) then $x 
    else array { $x }
  )
}
return fn($input as item()*, $functions as fn(*)*) as item()* {
  fold-left($functions, $input, $apply)
}
Error Conditions

An error [err:FOAP0001] is raised if the arity of any function $f in $functions is different from the number of members in the array that is passed to fn:apply.

An error [err:FORG0006] is raised if any item supplied as a function argument cannot be coerced to the required type.

Notes
  1. Functions are applied in sequence order, not right-to-left (as might be expected in mathematical composition).

  2. It is not a requirement that every function in $functions must have arity of one. Any function may have any arity.

  3. Using fn:chain may result in more readable XPath expressions than chaining expressions using arrow operators.

Examples
Variables
let $incr := fn($x) { op("+")($x, ?) }
let $double-all := fn($nums) { $nums ! op("*")(., 2) }
let $times := fn($y) { op("*")($y,  ?) }
let $append-all := fn($strings, $add) { $strings ! concat#2(., $add) }
let $make-upper-all := fn($strings) { $strings ! upper-case(.) }
let $count-all := fn($ar) { array:for-each($ar, count#1)?* }
let $product3 := fn($x, $y, $z) { $x * $y * $z }
let $range := fn($n) { 1 to $n }
Expression:
chain((2, 3), ($double-all, op("+"), $incr(3)))
Result:
13
Expression:
chain((2, 3), ($double-all, sum#1, $incr(3)))
Result:
13
Expression:
chain((2, 3), (op("+"), $incr(3)))
Result:
8
Expression:
chain((2, 3), (sum#1, $incr(3)))
Result:
8
Expression:
chain([ 1, (), 2, 3 ], (array:size#1, $incr(3)))
Result:
7
Expression:
chain((1, 2, 3), (count#1, $incr(3)))
Result:
6
Expression:
chain([ 1, 2, 3 ], (count#1, $incr(3)))
Result:
4
Expression:
chain(5, ($range, $double-all, sum#1))
Result:
30
Expression:
chain(2, ($range, $double-all, op("*")))
Result:
8
Expression:
chain([ (1, 2, 3), () ], ($count-all, op("+")))
Result:
3
Expression:
chain([ (1, 2, 3), (), (5, 6) ], ($count-all, sum#1))
Result:
5
Expression:
chain([ (1, 2, 3), (), (5, 6) ], ($count-all, $product3))
Result:
0
Expression:
chain("abra cadabra", (tokenize#2(?, " "), string-join#2(?, "+")))
Result:
"abra+cadabra"
Expression:
chain("The cat sat on the mat", (
  tokenize#2(?, " "), 
  $append-all(?, "."), 
  $make-upper-all, 
  string-join#2(?, " ") 
))
Result:
"THE. CAT. SAT. ON. THE. MAT."
Expression:
chain((
  chain(
    ("A    long   message   ", "   long "), 
    (head#1, normalize-space#1, normalize-unicode#1)
  ),
  chain(
    ("A    long   message   ", "   long "),  
    (tail#1, normalize-space#1, normalize-unicode#1)
  )
  ),
  contains#2
)
Result:
true()
Expression:
chain((), true#0)
Result:
true()
Expression:
chain(3, (array:append([1], ?), op("+")))
Result:
4
Expression:
chain((1, 2, 3), ($product3, $product3))
Result:

Raises error FOAP0001.

Expression:
chain((1, 2, 3, 4), $product3)
Result:

Raises error FOAP0001.

17.2.317.2.2 fn:do-until

Changes in 4.0  

  1. New in 4.0  [Issue 946 PR 962]

  2. The $predicate callback function may return an empty sequence (meaning false).  [Issue 1171 PR 1182 7 May 2024]

Summary

Processes a supplied value repeatedly, continuing when some condition is false, and returning the value that satisfies the condition.

Signature
fn:do-until(
$inputas item()*,
$actionas fn(item()*, xs:integer) as item()*,
$predicateas fn(item()*, xs:integer) as xs:boolean?
) as item()*
Properties

This function is deterministic, context-independent, and focus-independent.

Rules

Informally, the function behaves as follows:

  1. $pos is initially set to 1.

  2. $action($input, $pos) is evaluated, and the resulting value is used as a new $input.

  3. $predicate($input, $pos) is evaluated. If the result is true, the function returns the value of $input. Otherwise, the process repeats from step 2 with $pos incremented by 1.

    When the predicate returns an empty sequence, this is treated as false.

Formal Equivalent

The function delivers the same result as the following XQuery implementation.

declare %private function do-until-helper(
  $input     as item()*,
  $action    as fn(item()*, xs:integer) as item()*,
  $predicate as fn(item()*, xs:integer) as xs:boolean?,
  $pos       as xs:integer
) as item()* {
  let $result := $action($input, $pos)
  return if ($predicate($result, $pos)) then (
    $result
  ) else (
    do-until-helper($result, $action, $predicate, $pos + 1)
  )
};

declare function do-until(
  $input     as item()*,
  $action    as fn(item()*, xs:integer) as item()*,
  $predicate as fn(item()*, xs:integer) as xs:boolean?
) as item()* {
  do-until-helper($input, $action, $predicate, 1)
};
Notes

Do-until loops are very common in procedural programming languages, and this function provides a way to write functionally clean and interruptible iterations without side-effects. A new value is computed and tested until a given condition fails. Depending on the use case, the value can be a simple atomic item or an arbitrarily complex data structure.

The function fn:while-do can be used to perform the action after the first predicate test.

Note that, just as when writing recursive functions, it is easy to construct infinite loops.

Examples
Expression:
do-until(
  (),
  fn($value, $pos) { $value, $pos * $pos },
  fn($value) { foot($value) > 50  }
)
Result:
1, 4, 9, 16, 25, 36, 49, 64

(The loop is interrupted once the last value of the generated sequence is greater than 50.)

Expression:
do-until(
  (1, 0),
  fn($value) { $value[1] + $value[2], $value },
  fn($value) { avg($value) > 10 }
)
Result:
55, 34, 21, 13, 8, 5, 3, 2, 1, 1, 0

(The computation is continued as long as the average of the first Fibonacci numbers is smaller than 10.)

17.2.417.2.3 fn:every

Changes in 4.0  

  1. New in 4.0  [  13 September 2022]

  2. The $predicate callback function may return an empty sequence (meaning false).  [Issue 1171 PR 1182 7 May 2024]

Summary

Returns true if every item in the input sequence matches a supplied predicate.

Signature
fn:every(
$inputas item()*,
$predicateas (fn(item(), xs:integer) as xs:boolean?)?:= fn:boolean#1
) as xs:boolean
Properties

This function is deterministic, context-independent, and focus-independent.

Rules

The function returns true if $input is empty, or if $predicate($item, $pos) returns true for every item $item at position $pos (1-based) in $input.

Formal Equivalent

The effect of the function is equivalent to the result of the following XPath expression.

count(filter($input, $predicate)) = count($input)
Error Conditions

An error is raised if the $predicate function raises an error. In particular, when the default predicate fn:boolean#1 is used, an error is raised if an item has no effective boolean value.

Notes

If the second argument is omitted or an empty sequence, the predicate defaults to fn:boolean#1, which takes the effective boolean value of each item.

It is possible for the supplied $predicate to be a function whose arity is less than two. The coercion rules mean that the additional parameters are effectively ignored. Frequently a predicate function will only consider the item itself, and disregard its position in the sequence.

The predicate is required to return either true, false, or an empty sequence (which is treated as false). A predicate such as fn { self::h1 } results in a type error because it returns a node, not a boolean.

The implementation may deliver a result as soon as one item is found for which the predicate returns false; it is not required to evaluate the predicate for every item, nor is it required to examine items sequentially from left to right.

Examples
Expression:

every(())

Result:
true()
Expression:

every((1 = 1, 2 = 2, 3 = 4))

Result:
false()
Expression:

every((), boolean#1)

Result:
true()
Expression:

every((1, 3, 7), fn { . mod 2 = 1 })

Result:
true()
Expression:

every(-5 to +5, fn { . ge 0 })

Result:
false()
Expression:
every(
  ("January", "February", "March", "April",
   "September", "October", "November", "December"),
  contains(?, "r")
)
Result:
true()
Expression:
every(
  ("January", "February", "March", "April",
   "September", "October", "November", "December")
  =!> contains("r")
)
Result:
true()
Expression:

every((1, 2, number('NaN')))

Result:
false()

(The effective boolean value of NaN is false.)

Expression:

every(1 to 5, fn($num, $pos) { $num = $pos })

Result:
true()
Expression:
let $dl := <dl><dt>Morgawr</dt><dd>Sea giant</dd></dl>
return every($dl/*, fn($elem, $pos) {
  name($elem) = (
    if (($pos mod 2)) then "dt" else "dd"
  )
})
Result:
true()

17.2.517.2.4 fn:filter

Changes in 4.0  

  1. The $predicate callback function accepts an optional position argument.  [Issue 516 PR 828 14 November 2023]

  2. The $predicate callback function may return an empty sequence (meaning false).  [Issue 1171 PR 1182 7 May 2024]

Summary

Returns those items from the sequence $input for which the supplied function $predicate returns true.

Signature
fn:filter(
$inputas item()*,
$predicateas fn(item(), xs:integer) as xs:boolean?
) as item()*
Properties

This function is deterministic, context-independent, and focus-independent.

Rules

The function returns a sequence containing those items from $input for which $predicate($item, $pos) returns true, where $item is the item in question, and $pos is its 1-based ordinal position within $input.

Formal Equivalent

The effect of the function is equivalent to the result of the following XPath expression.

for-each(
  $input,
  fn($item, $pos) { if ($predicate($item, $pos)) { $item } }
)
Error Conditions

As a consequence of the function signature and the function calling rules, a type error occurs if the supplied $predicate function returns anything other than a single xs:boolean item or an empty sequence; there is no conversion to an effective boolean value, but an empty sequence is interpreted as false.

Notes

If $predicate is an arity-1 function, the function call fn:filter($input, $predicate) has a very similar effect to the expression $input[$predicate(.)]. There are some differences, however. In the case of fn:filter, the function $F is required to return an optional boolean; there is no special treatment for numeric predicate values, and no conversion to an effective boolean value. Also, with a filter expression $input[$predicate(.)], the focus within the predicate is different from that outside; this means that the use of a context-sensitive function such as fn:lang#1 will give different results in the two cases.

Examples
Expression:

filter(1 to 10, fn($a) { $a mod 2 = 0 })

Result:
2, 4, 6, 8, 10
Expression:
filter(parse-xml('<doc><a id="2"/><a/></doc>')//a, fn { @id eq "2" })
Result:
<a id="2"/>

(The function returns () when there is no @id attribute; this is treated as false.)

Expression:

filter((), lang("en", ?))

Result:
()
Expression:
let $sequence := (1, 1, 2, 3, 4, 4, 5)
return filter(
  $sequence,
  fn($item, $pos) { $item = $sequence[$pos - 1] }
)
Result:
1, 4

17.2.617.2.5 fn:fold-left

Summary

Processes the supplied sequence from left to right, applying the supplied function repeatedly to each item in turn, together with an accumulated result value.

Signature
fn:fold-left(
$inputas item()*,
$initas item()*,
$actionas fn(item()*, item()) as item()*
) as item()*
Properties

This function is deterministic, context-independent, and focus-independent.

Rules

If $input is empty, the function returns $init.

If $input contains at least one item, the function calls $action($init, $input[1]), returning a value A1.

If $input contains a second item, the function then calls $action(A1, $input[2]), returning A2; to process the nth item it calls $action(An-1, $input[N]).

This continues in the same way until the end of the $input sequence; the final result is the result of the last call on $action.

Formal Equivalent

The function delivers the same result as the following XQuery implementation.

declare function fold-left(
  $input  as item()*,
  $init   as item()*,
  $action as function(item()*, item()) as item()*
) as item()* {
  if (empty($input)) 
  then $init
  else fold-left(tail($input), $action($init, head($input)), $action)
};
Error Conditions

As a consequence of the function signature and the function calling rules, a type error occurs if the supplied function $action cannot be applied to two arguments, where the first argument is either the value of $init or the result of a previous application of $action, and the second is any single item from the sequence $input.

Notes

This operation is often referred to in the functional programming literature as “folding” or “reducing” a sequence. It typically takes a function that operates on a pair of values, and applies it repeatedly, with an accumulated result as the first argument, and the next item in the sequence as the second argument. The accumulated result is initially set to the value of the $init argument, which is conventionally a value (such as zero in the case of addition, one in the case of multiplication, or a zero-length string in the case of string concatenation) that causes the function to return the value of the other argument unchanged.

Unlike other functions that apply a user-supplied callback function to successive items in a sequence, this function does not supply the current position to the callback function as an optional argument. If positional information is required, this can be achieved by first forming the sequence $input ! { 'position': position(), 'item': . } and then applying the fn:fold-left function to this sequence.

Examples
Expression:
fold-left(
  1 to 5,
  0,
  fn($a, $b) { $a + $b }
)
Result:
15

(This returns the sum of the items in the sequence).

Expression:
fold-left(
  (2, 3, 5, 7),
  1,
  fn($a, $b) { $a * $b }
)
Result:
210

(This returns the product of the items in the sequence).

Expression:
fold-left(
  (true(), false(), false()),
  false(),
  fn($a, $b) { $a or $b }
)
Result:
true()

(This returns true if any item in the sequence has an effective boolean value of true).

Expression:
fold-left(
  (true(), false(), false()),
  false(),
  fn($a, $b) { $a and $b }
)
Result:
false()

(This returns true only if every item in the sequence has an effective boolean value of true).

Expression:
fold-left(
  1 to 5,
  (),
  fn($a, $b) { $b, $a }
)
Result:
5, 4, 3, 2, 1

(This reverses the order of the items in a sequence).

Expression:
fold-left(
  1 to 5,
  "",
  concat(?, ".", ?)
)
Result:
".1.2.3.4.5"
Expression:
fold-left(
  1 to 5,
  "$z",
  concat("$f(", ?, ", ", ?, ")")
)
Result:
"$f($f($f($f($f($z, 1), 2), 3), 4), 5)"
Expression:
fold-left(
  1 to 5,
  {},
  fn($map, $n) { map:put($map, $n, $n * 2) }
)
Result:
{ 1: 2, 2: 4, 3: 6, 4: 8, 5: 10 }

17.2.717.2.6 fn:fold-right

Changes in 4.0  

  1. The $action callback function accepts an optional position argument.  [Issue 516 PR 828 14 November 2023]

Summary

Processes the supplied sequence from right to left, applying the supplied function repeatedly to each item in turn, together with an accumulated result value.

Signature
fn:fold-right(
$inputas item()*,
$initas item()*,
$actionas fn(item(), item()*) as item()*
) as item()*
Properties

This function is deterministic, context-independent, and focus-independent.

Rules

If $input is empty, the function returns $init.

Let In be the last item in $input, and let An be $init. The function starts by calling $action(In, $init), producing a result An-1.

If there is a previous item, In-1, the function then calls $action(In-1, An-1), producing the result An-2.

This continues in the same way until the start of the $input sequence is reached; the final result is the value A0.

Formal Equivalent

The function delivers the same result as the following XQuery implementation.

declare function fold-right(
  $input  as item()*,
  $init   as item()*,
  $action as function(item(), item()*) as item()*
) as item()* {
  if (empty($input))
  then $init
  else $action(head($input), fold-right(tail($input), $init, $action))
};
Error Conditions

As a consequence of the function signature and the function calling rules, a type error occurs if the supplied function $action cannot be applied to two arguments, where the first argument is any item in the sequence $input, and the second is either the value of $init or the result of a previous application of $action.

Notes

This operation is often referred to in the functional programming literature as “folding” or “reducing” a sequence. It takes a function that operates on a pair of values, and applies it repeatedly, with the next item in the sequence as the first argument, and the result of processing the remainder of the sequence as the second argument. The accumulated result is initially set to the value of the $init argument, which is conventionally a value (such as zero in the case of addition, one in the case of multiplication, or a zero-length string in the case of string concatenation) that causes the function to return the value of the other argument unchanged.

In cases where the function performs an associative operation on its two arguments (such as addition or multiplication), fn:fold-right produces the same result as fn:fold-left.

Unlike other functions that apply a user-supplied callback function to successive items in a sequence, this function does not supply the current position to the callback function as an optional argument. If positional information is required, this can be achieved by first forming the sequence $input ! { 'position': position(), 'item': . } and then applying the fn:fold-right function to this sequence.

Examples
Expression:
fold-right(
  1 to 5,
  0,
  fn($a, $b) { $a + $b }
)
Result:
15

(This returns the sum of the items in the sequence).

Expression:
fold-right(
  1 to 5,
  "",
  concat(?, ".", ?)
)
Result:
"1.2.3.4.5."
Expression:
fold-right(
  1 to 5,
  "$z",
  concat("$f(", ?, ", ", ?, ")")
)
Result:
"$f(1, $f(2, $f(3, $f(4, $f(5, $z)))))"

17.2.817.2.7 fn:for-each

Changes in 4.0  

  1. The $action callback function accepts an optional position argument.  [Issue 516 PR 828 14 November 2023]

Summary

Applies the function item $action to every item from the sequence $input in turn, returning the concatenation of the resulting sequences in order.

Signature
fn:for-each(
$inputas item()*,
$actionas fn(item(), xs:integer) as item()*
) as item()*
Properties

This function is deterministic, context-independent, and focus-independent.

Rules

The function calls $action($item, $pos) for each item in $input, where $item is the item in question and $pos is its 1-based ordinal position in $input. The final result is the sequence concatenation of the result of these calls, preserving order.

Formal Equivalent

The function is defined as follows, making use of primitive constructors and accessors defined in [XQuery and XPath Data Model (XDM) 4.0].

dm:iterate-sequence($input, $action)
Examples
Expression:

for-each(1 to 5, fn($a) { $a * $a })

Result:
1, 4, 9, 16, 25
Expression:
for-each(
  ("john", "jane"),
  string-to-codepoints#1
)
Result:
106, 111, 104, 110, 106, 97, 110, 101
Expression:

for-each(("23", "29"), xs:int#1)

Result:
23, 29
Expression:
for-each(
  ('one', 'two', 'three'),
  fn($item, $pos) { $pos || '. ' || $item }
)
Result:
"1. one", "2. two", "3. three"

17.2.917.2.8 fn:for-each-pair

Changes in 4.0  

  1. The $action callback function accepts an optional position argument.  [Issue 516 PR 828 14 November 2023]

Summary

Applies the function item $action to successive pairs of items taken one from $input1 and one from $input2, returning the concatenation of the resulting sequences in order.

Signature
fn:for-each-pair(
$input1as item()*,
$input2as item()*,
$actionas fn(item(), item(), xs:integer) as item()*
) as item()*
Properties

This function is deterministic, context-independent, and focus-independent.

Rules

The function returns the value of the expression:

for $pos in 1 to min(count($input1), count($input2))
return $action($input1[$pos], $input2[$pos], $pos)
Notes

If one sequence is longer than the other, excess items in the longer sequence are ignored.

Examples
Expression:
for-each-pair(
  ("a", "b", "c"),
  ("x", "y", "z"),
  concat#2
)
Result:
"ax", "by", "cz"
Expression:
for-each-pair(
  1 to 5,
  1 to 5,
  fn($a, $b) { 10 * $a + $b }
)
Result:
11, 22, 33, 44, 55
Expression:
let $s := 1 to 8
return for-each-pair($s, tail($s), fn($a, $b) { $a * $b })
Result:
2, 6, 12, 20, 30, 42, 56
Expression:
for-each-pair(
  (1, 8, 2),
  (3, 4, 3),
  fn($item1, $item2, $pos) {
    $pos || ': ' || max(($item1, $item2))
  }
)
Result:
"1: 3", "2: 8", "3: 3"

17.2.1017.2.9 fn:highest

Changes in 4.0  

  1. New in 4.0  [  20 September 2022]

Summary

Returns those items from a supplied sequence that have the highest value of a sort key, where the sort key can be computed using a caller-supplied function.

Signature
fn:highest(
$inputas item()*,
$collationas xs:string?:= fn:default-collation(),
$keyas (fn(item()) as xs:anyAtomicType*)?:= fn:data#1
) as item()*
Properties

This function is deterministic, context-dependent, and focus-independent. It depends on collations.

Rules

The second argument, $collation, defaults to ().

Supplying an empty sequence as $collation is equivalent to supplying fn:default-collation(). For more information on collations see 5.3.7 Choosing a collation.

The third argument defaults to the function data#1.

Let $modified-key be the function:

fn($item) {
  $key($item) => data() ! (
    if (. instance of xs:untypedAtomic)
    then xs:double(.)
    else .
  )
}

That is, the supplied function for computing key values is wrapped in a function that converts any xs:untypedAtomic values in its result to xs:double. This makes the function consistent with the behavior of fn:min and fn:max, but inconsistent with fn:sort, which treats untyped values as strings.

The result of the function is obtained as follows:

  • If the input is an empty sequence, the result is an empty sequence.

  • The input sequence is sorted, by applying the function fn:sort($input, $collation, $modified-key).

  • Let $C be the selected collation, or the default collation where applicable.

  • Let $B be the last item in the sorted sequence.

  • The function returns those items $A from the input sequence such that (fn:deep-equal($key($A), $key($B), $C), retaining their order.

Error Conditions

If the set of computed keys contains xs:untypedAtomic values that are not castable to xs:double then operation will fail with a dynamic error ([err:FORG0001]FO).

If the set of computed keys contains values that are not comparable using the lt operator then the sort operation will fail with a type error ([err:XPTY0004]XP).

Examples
Variables
let $e := <a x="10" y="5" z="2"/>
Expression:

highest($e/@*) ! name()

Result:
"x"

(By default, untyped values are compared as numbers.)

Expression:

highest($e/@*, (), string#1) ! name()

Result:
"y"

(Here, the attribute values are compared as strings.)

Expression:

highest(("red", "green", "blue"), (), string-length#1)

Result:
"green"
Expression:
highest(
  ("red", "green", "blue"),
  key := {
    "red"  : xs:hexBinary('FF0000'),
    "green": xs:hexBinary('008000'),
    "blue" : xs:hexBinary('0000FF')
  }
)
Result:
"red"
Expression:
highest(
  ("red", "orange", "yellow", "green", "blue", "indigo", "violet"),
  key := string-length#1
)
Result:
"orange", "yellow", "indigo", "violet"
Expression:

highest(1 to 25, (), fn { . idiv 10 })

Result:
20, 21, 22, 23, 24, 25

To find employees having the highest salary:

highest($employees, (), fn { xs:decimal(salary) })

17.2.1117.2.10 fn:index-where

Changes in 4.0  

  1. New in 4.0  [  20 September 2022]

  2. The $predicate callback function may return an empty sequence (meaning false).  [Issue 1171 PR 1182 7 May 2024]

Summary

Returns the positions in an input sequence of items that match a supplied predicate.

Signature
fn:index-where(
$inputas item()*,
$predicateas fn(item(), xs:integer) as xs:boolean?
) as xs:integer*
Properties

This function is deterministic, context-independent, and focus-independent.

Rules

The result of the function is a sequence of integers, in monotonic ascending order, representing the 1-based positions in the input sequence of those items for which the supplied predicate function returns true. A return value of () from the predicate function is treated as false.

Formal Equivalent

The effect of the function is equivalent to the result of the following XPath expression.

for-each(
  $input,
  fn($item, $pos) { if ($predicate($item, $pos)) { $pos } }
)
Examples
Expression:

index-where((), boolean#1)

Result:
()
Expression:

index-where((0, 4, 9), boolean#1)

Result:
2, 3
Expression:

index-where(1 to 10, fn { . mod 2 = 0 })

Result:
2, 4, 6, 8, 10
Expression:
index-where(
  ("January", "February", "March", "April", "May", "June",
   "July", "August", "September", "October", "November", "December"),
  contains(?, "r")
)
Result:
1, 2, 3, 4, 9, 10, 11, 12
Expression:
index-where(
  ( 1, 8, 2, 7, 3 ),
  fn($item, $pos) { $item < 5 and $pos > 2 }
)
Result:
3, 5

17.2.1217.2.11 fn:lowest

Changes in 4.0  

  1. New in 4.0  [  20 September 2022]

Summary

Returns those items from a supplied sequence that have the lowest value of a sort key, where the sort key can be computed using a caller-supplied function.

Signature
fn:lowest(
$inputas item()*,
$collationas xs:string?:= fn:default-collation(),
$keyas (fn(item()) as xs:anyAtomicType*)?:= fn:data#1
) as item()*
Properties

This function is deterministic, context-dependent, and focus-independent. It depends on collations.

Rules

The second argument, $collation, defaults to ().

Supplying an empty sequence as $collation is equivalent to supplying fn:default-collation(). For more information on collations see 5.3.7 Choosing a collation.

The third argument defaults to the function data#1.

Let $modified-key be the function:

fn($item) {
  $key($item) => data() ! (
    if (. instance of xs:untypedAtomic) then xs:double(.) else .
  )
}

That is, the supplied function for computing key values is wrapped in a function that converts any xs:untypedAtomic values in its result to xs:double. This makes the function consistent with the behavior of fn:min and fn:max, but inconsistent with fn:sort, which treats untyped values as strings.

The result of the function is obtained as follows:

  • If the input is an empty sequence, the result is an empty sequence.

  • The input sequence is sorted, by applying the function fn:sort($input, $collation, $modified-key).

  • Let $C be the selected collation, or the default collation where applicable.

  • Let $B be the first item in the sorted sequence.

  • The function returns those items $A from the input sequence such that (fn:deep-equal($key($A), $key($B), $C), retaining their order.

Error Conditions

If the set of computed keys contains xs:untypedAtomic values that are not castable to xs:double then operation will fail with a dynamic error ([err:FORG0001]FO).

If the set of computed keys contains values that are not comparable using the lt operator then the sort operation will fail with a type error ([err:XPTY0004]XP).

Examples
Variables
let $e := <a x="10" y="5" z="2"/>
Expression:

lowest($e/@*) ! name()

Result:
"z"

(By default, untyped values are compared as numbers.)

Expression:

lowest($e/@*, (), string#1) ! name()

Result:
"x"

(Here, the attribute values are compared as strings.)

Expression:

lowest(("red", "green", "blue"), (), string-length#1)

Result:
"red"
Expression:
lowest(
  ("red", "green", "blue"),
  key := {
    "red"  : xs:hexBinary('FF0000'),
    "green": xs:hexBinary('008000'),
    "blue" : xs:hexBinary('0000FF')
  }
)
Result:
"blue"
Expression:
lowest(
  ("April", "June", "July", "August"),
  key := string-length#1
)
Result:
"June", "July"
Expression:

lowest(1 to 25, (), fn { . idiv 10 })

Result:
1, 2, 3, 4, 5, 6, 7, 8, 9

To find employees having the lowest salary:

lowest($employees, (), fn { xs:decimal(salary) })

17.2.1317.2.12 fn:partial-apply

Changes in 4.0  

  1. New in 4.0  [Issue 1816 PR 1825 25 February 2025]

Summary

Performs partial application of a function item by binding values to selected arguments.

Signature
fn:partial-apply(
$functionas fn(*),
$argumentsas map(xs:positiveInteger, item()*)
) as fn(*)
Properties

This function is deterministic, context-independent, and focus-independent.

Rules

The result is a function obtained by binding values to selected arguments of the function item $function. The arguments to be bound are represented by entries in the $arguments map: an entry with key $i and value $v causes the argument at position $i (1-based) to be bound to $v.

Any entries in $arguments whose keys are greater than the arity of $function are ignored.

If $arguments is an empty map then the function returns $function unchanged.

For example, the effect of calling fn:partial-apply($f, { 2: $x }) is the same as the effect of the partial appplication $f(?, $x, ?, ?, ....). The coercion rules are applied to the supplied arguments in the usual way.

Unlike a partial application using place-holder arguments:

  • The arity of $function need not be statically known.

  • It is possible to bind all the arguments of $function: the effect is to return a zero-arity function.

The result is a partially applied functionXP having the following properties (which are defined in Section 7.1 Function ItemsDM):

  • name: absent.

  • identity: A new function identity distinct from the identity of any other function item.

  • arity: The arity of $function minus the number of parameters in $function that map to supplied arguments in $arguments.

  • parameter names: The names of the parameters of $function that do not map to supplied arguments in $arguments.

  • signature: The parameters in the returned function are the parameters of $function that do not map to supplied arguments in $arguments, retaining order. The result type of the returned function is the same as the result type of $function.

    An implementation that can determine a more specific signature (for example, through use of type analysis) is permitted to do so.

  • body: The body of $function.

  • captured context: The static and dynamic context of $function, augmented, for each supplied argument, with a binding of the converted argument value to the corresponding parameter name.

Error Conditions

A type error is raised if any of the supplied arguments, after applying the coercion rules, does not match the required type of the corresponding function parameter.

In addition, a dynamic error may be raised if any of the supplied arguments does not match other constraints on the value of that argument (for example, if the value supplied for a parameter expecting a regular expression is not a valid regular expression); or if the processor is able to establish that evaluation of the resulting function will fail for any other reason (for example, if an error is raised while evaluating a subexpression in the function body that depends only on explicitly supplied and defaulted parameters).

Notes

See also Section 4.5.4 Partial Function ApplicationXP.

The function is useful where the arity of a function item is not known statically, or where all arguments in a function are to be bound, returning a zero-arity function.

Examples
Expression:
let $f := partial-apply(dateTime#2,  {2: xs:time('00:00:00') })
return $f(xs:date('2025-03-01'))
Result:
xs:dateTime('2025-03-01T00:00:00')

17.2.1417.2.13 fn:partition

Changes in 4.0  

  1. New in 4.0  [Issue 125 PR 507 19 May 2023]

Summary

Partitions a sequence of items into a sequence of non-empty arrays containing the same items, starting a new partition when a supplied condition is true.

Signature
fn:partition(
$inputas item()*,
$split-whenas fn(item()*, item(), xs:integer) as xs:boolean?
) as array(item()*)*
Properties

This function is deterministic, context-independent, and focus-independent.

Rules

Informally, the function starts by creating a partition containing the first item in the input sequence, if any. For each remaining item J in the input sequence, other than the first, it calls the supplied $split-when function with three arguments: the contents of the current partition, the item J, and the current position in the input sequence.

Each partition is a sequence of items; the function result wraps each partition as an array, and returns the sequence of arrays.

If the $split-when function returns true, the current partition is wrapped as an array and added to the result, and a new current partition is created, initially containing the item J only. If the $split-when function returns false or (), the item J is added to the current partition.

Formal Equivalent

The effect of the function is equivalent to the result of the following XPath expression.

for-each(
  $input,
  fn($item, $pos) { map{ 'item': $item, 'pos': $pos } }
)
=> fold-left((), fn($partitions, $pair) {
  if (empty($partitions) or $split-when(foot($partitions)?*, $pair?item, $pair?pos))
  then ($partitions, [ $pair?item ])
  else (trunk($partitions), array { foot($partitions)?*, $pair?item })
})
Notes

The function enables a variety of positional grouping problems to be solved. For example:

  • partition($input, fn($a, $b) { count($a) eq 3 } partitions a sequence into fixed size groups of length 3.

  • partition($input, fn($a, $b) { boolean($b/self::h1) } starts a new group whenever an h1 element is encountered.

  • partition($input, fn($a, $b) { $b lt foot($a) } starts a new group whenever an item is encountered whose value is less than the value of the previous item.

The callback function is not called to process the first item in the input sequence, because this will always start a new partition. The first argument to the callback function (the current partition) is always a non-empty sequence.

Examples
Expression:
partition(
  ("Anita", "Anne", "Barbara", "Catherine", "Christine"), 
  fn($partition, $next) {
    substring(head($partition), 1, 1) ne substring($next, 1, 1)
  }
)
Result:
[ "Anita", "Anne" ], [ "Barbara" ], [ "Catherine", "Christine" ]
Expression:
partition(
  (1, 2, 3, 4, 5, 6, 7),
  fn($partition, $next) { count($partition) eq 2 }
)
Result:
[ 1, 2 ], [ 3, 4 ], [ 5, 6 ], [ 7 ]
Expression:
partition(
  (1, 4, 6, 3, 1, 1),
  fn($partition, $next) { sum($partition) ge 5 }
)
Result:
[ 1, 4 ], [ 6 ], [ 3, 1, 1 ]
Expression:
partition(
  tokenize("In the beginning was the word"), 
  fn($partition, $next) {
    sum(($partition, $next) ! string-length()) gt 10
  }
)
Result:
[ "In", "the" ], [ "beginning" ], [ "was", "the", "word" ]
Expression:
partition(
  (1, 2, 3, 6, 7, 9, 10),
  fn($partition, $next) { $next != foot($partition) + 1 }
)
Result:
[ 1, 2, 3 ], [ 6, 7 ], [ 9, 10 ]
Expression:
partition(
  ('a', 'b', 'c', 'd', 'e'),
  fn($all, $next, $p) { $p mod 2 = 1 }
)
Result:
[ "a", "b" ], [ "c", "d" ], [ "e" ]

17.2.1517.2.14 fn:scan-left

Changes in 4.0  

  1. New in 4.0  [Issue 982 PR 1296 23 June 2024]

Summary

Produces the sequence of successive partial results from the evaluation of fn:fold-left with the same arguments.

Signature
fn:scan-left(
$inputas item()*,
$initas item()*,
$actionas fn(item()*, item()) as item()*
) as array(*)*
Properties

This function is deterministic, context-independent, and focus-independent.

Rules

The function returns a sequence of N+1 single-member arraysDM, where N is the number of items in $input. For values of $n in the range 0 to N, the value of the single member of array $n+1 in the result sequence is the value of the expression fold-left( subsequence($input, 1, $n), $init, $action ).

Formal Equivalent

The effect of the function is equivalent to the result of the following XPath expression.

(0 to count($input)) 
! [fold-left(subsequence($input, 1, .), $init, $action) ]
Notes

A practical implementation is likely to compute each array in the result sequence based on the value of the previous item, rather than computing each item independently as implied by the specification.

Examples
Expression:
scan-left(1 to 5, 0, op('+'))
Result:
[ 0 ], [ 1 ], [ 3 ], [ 6 ], [ 10 ], [ 15 ]
Expression:
scan-left(1 to 3, 0, op('-'))
Result:
[ 0 ], [ -1 ], [ -3 ], [ -6 ]
Expression:
scan-left(1 to 5, 1, op('*'))
Result:
[ 1 ], [ 1 ], [ 2 ], [ 6 ], [ 24 ], [ 120 ]
Expression:
scan-left(1 to 3, (), fn($a, $b) { $b, $a })
Result:
[ () ], [ 1 ], [ (2, 1) ], [ (3, 2, 1) ]

17.2.1617.2.15 fn:scan-right

Changes in 4.0  

  1. New in 4.0

Summary

Produces the sequence of successive partial results from the evaluation of fn:fold-right with the same arguments.

Signature
fn:scan-right(
$inputas item()*,
$initas item()*,
$actionas fn(item(), item()*) as item()*
) as array(*)*
Properties

This function is deterministic, context-independent, and focus-independent.

Rules

The function returns a sequence of N+1 single-member arraysDM, where N is the number of items in $input. For values of $n in the range 0 to N, the value of the single member of array $n+1 in the result sequence is the value of the expression fold-right( subsequence($input, count($input)-$n+1), $init, $action ).

Formal Equivalent

The effect of the function is equivalent to the result of the following XPath expression.

(0 to count($input)) 
! [ fold-right(subsequence($input, count($input)-.+1), $init, $action) ]
Notes

A practical implementation is likely to compute each array in the result sequence based on the value of the previous item, rather than computing each item independently as implied by the specification.

Examples
Expression:
scan-right(1 to 10, 0, op('+'))
Result:
[ 55 ], [ 54 ], [ 52 ], [ 49 ], [ 45 ], [ 40 ],
[ 34 ], [ 27 ], [ 19 ], [ 10 ], [ 0 ]
Expression:
scan-right(1 to 3, 0, op('-'))
Result:
[ 2 ], [ -1 ], [ 3 ], [ 0 ]
Expression:
scan-right(1 to 5, (), fn($a, $b) { $b, $a })
Result:
[ (5, 4, 3, 2, 1) ], [ (5, 4, 3, 2) ], [ (5, 4, 3) ],
[ (5, 4) ], [ 5 ], [ () ]

17.2.1717.2.16 fn:some

Changes in 4.0  

  1. New in 4.0  [  13 September 2022]

  2. The $predicate callback function may return an empty sequence (meaning false).  [Issue 1171 PR 1182 7 May 2024]

Summary

Returns true if at least one item in the input sequence matches a supplied predicate.

Signature
fn:some(
$inputas item()*,
$predicateas (fn(item(), xs:integer) as xs:boolean?)?:= fn:boolean#1
) as xs:boolean
Properties

This function is deterministic, context-independent, and focus-independent.

Rules

The function returns true if (and only if) there is an item $item at position $pos in the input sequence such that $predicate($item, $pos) returns true.

Formal Equivalent

The effect of the function is equivalent to the result of the following XPath expression.

exists(filter($input, $predicate))
Error Conditions

An error is raised if the $predicate function raises an error. In particular, when the default predicate fn:boolean#1 is used, an error is raised if an item has no effective boolean value.

Notes

If the second argument is omitted or an empty sequence, the predicate defaults to fn:boolean#1, which takes the effective boolean value of each item.

It is possible for the supplied $predicate to be a function whose arity is less than two. The coercion rules mean that the additional parameters are effectively ignored. Frequently a predicate function will only consider the item itself, and disregard its position in the sequence.

The predicate is required to return either true, false, or an empty sequence (which is treated as false). A predicate such as fn { self::h1 } results in a type error because it returns a node, not a boolean.

The implementation may deliver a result as soon as one item is found for which the predicate returns true; it is not required to evaluate the predicate for every item, nor is it required to examine items sequentially from left to right.

Examples
Expression:

some(())

Result:
false()
Expression:

some((1 = 1, 2 = 2, 3 = 4))

Result:
true()
Expression:

some((), boolean#1)

Result:
false()
Expression:

some((1, 3, 7), fn { . mod 2 = 1 })

Result:
true()
Expression:

some(-5 to +5, fn { . ge 0 })

Result:
true()
Expression:
some(
  ("January", "February", "March", "April",
   "September", "October", "November", "December"),
  contains(?, "z")
)
Result:
false()
Expression:
some(
  ("January", "February", "March", "April",
   "September", "October", "November", "December")
  =!> contains("r")
)
Result:
true()
Expression:

some(("", 0, number('NaN')))

Result:
false()

(The effective boolean value in each case is false.)

Expression:

some(reverse(1 to 5), fn($num, $pos) { $num = $pos })

Result:
true()

17.2.1817.2.17 fn:sort

Changes in 4.0  

  1. Substantially revised to allow multiple sort key definitions.  [Issue 93 PR 623 19 July 2023]

Summary

Sorts a supplied sequence, based on the value of a number of sort keys supplied as functions.

Signature
fn:sort(
$inputas item()*,
$collationsas xs:string*:= fn:default-collation(),
$keysas (fn(item()) as xs:anyAtomicType*)*:= fn:data#1,
$ordersas enum('ascending', 'descending')*:= 'ascending'
) as item()*
Properties

This function is deterministic, context-dependent, and focus-independent. It depends on collations.

Rules

The result of the function is a sequence that contains all the items from $input, typically in a different order, the order being defined by the supplied sort key definitions.

A sort key definition has three parts:

  1. A sort key function, which is applied to each item in the input sequence to determine a sort key value.

  2. A collation, which is used when comparing sort key values that are of type xs:string or xs:untypedAtomic.

  3. An order direction, which is ascending or descending.

The number of sort key definitions is determined by the number of function items supplied in the $keys argument. If the argument is absent or empty, the default is a single sort key definition using the function data#1.

The $nth sort key definition (where $n counts from one (1)) is established as follows:

  1. The sort key function is $keys[$n] otherwise data#1.

  2. The collation is $collations[$n] otherwise $collations[last()] otherwise default-collation(). That is, it is the collation supplied in the corresponding item of the supplied $collations argument; or in its absence, the last entry in $collations; or if $collations is absent or empty, the default collation from the static context of the caller.

  3. The order direction is $orders[$n] otherwise $orders[last()] otherwise "ascending". That is, it is "ascending" or "descending" according to the value of the corresponding item in the supplied $orders argument; or in its absence, the last entry in $orders; or if $orders is absent or empty, then "ascending".

When comparing values of types other than xs:string or xs:untypedAtomic, the corresponding collation is ignored, and no error is reported if the supplied value is not a known or valid collation name. If it is necessary to supply such an ignored value (for example, in the case where a non-string sort key is followed by another sort key that requires a collation) the empty string can be supplied.

The result of the function is obtained as follows:

  1. The result sequence contains the same items as the input sequence $input, but generally in a different order.

  2. The sort key definitions are established as described above. The sort key definitions are in major-to-minor order. That is, the position of two items $A and $B in the result sequence is determined first by the relative magnitude of their primary sort key values, which are computed by evaluating the sort key function in the first sort key definition. If those two sort key values are equal, then the position is determined by the relative magnitude of their secondary sort key values, computed by evaluating the sort key function in the second sort key definition, and so on.

  3. When a pair of corresponding sort key values of $A and $B are found to be not equal, then $A precedes $B in the result sequence if both the following conditions are true, or if both conditions are false:

    1. The sort key value for $A is less than the sort key value for $B, as defined below.

    2. The order direction in the corresponding sort key definition is "ascending".

  4. If all the sort key values for $A and $B are pairwise equal, then $A precedes $B in the result sequence if and only if $A precedes $B in the input sequence.

    Note:

    That is, the sort is stable.

  5. Each sort key value for a given item is obtained by applying the sort key function of the corresponding sort key definition to that item. The result of this function is in the general case a sequence of atomic items. Two sort key values $a and $b are compared as follows:

    1. Let $C be the collation in the corresponding sort key definition.

    2. Let $REL be the result of evaluating op:lexicographic-compare($key($A), $key($B), $C) where op:lexicographic-compare($a, $b, $C) is defined as follows:

      if (empty($a) and empty($b)) then 0 
      else if (empty($a)) then -1
      else if (empty($b)) then +1
      else let $rel = op:simple-compare(head($a), head($b), $C)
           return if ($rel eq 0)
                  then op:lexicographic-compare(tail($a), tail($b), $C)
                  else $rel
    3. Here op:simple-compare($k1, $k2) is defined as follows:

      if ($k1 instance of (xs:string | xs:anyURI | xs:untypedAtomic)
          and $k2 instance of (xs:string | xs:anyURI | xs:untypedAtomic))
      then compare($k1, $k2, $C)
      else if ($k1 instance of xs:numeric and $k2 instance of xs:numeric)
      then compare($k1, $k2)
      else if ($k1 eq $k2) then 0
      else if ($k2 lt $k2) then -1
      else +1

      Note:

      This raises an error if two keys are not comparable, for example if one is a string and the other is a number, or if both belong to a non-ordered type such as xs:QName.

    4. If $REL is zero, then the two sort key values are deemed equal; if $REL is -1 then $a is deemed less than $b, and if $REL is +1 then $a is deemed greater than $b

Error Conditions

If the set of computed sort keys contains values that are not comparable using the lt operator then the sort operation will fail with a type error ([err:XPTY0004]XP).

Notes

XSLT and XQuery both provide native sorting capability, but earlier releases of XPath provided no sorting functionality for use in standalone environments.

In addition there are cases where this function may be more flexible than the built-in sorting capability for XQuery or XSLT, for example when the sort key or collation is chosen dynamically, or when the sort key is a sequence of items rather than a single item.

The results are compatible with the results of XSLT sorting (using xsl:sort) in the case where the sort key evaluates to a sequence of length zero or one, given the options stable="yes".

The results are compatible with the results of XQuery sorting (using the order by clause) in the case where the sort key evaluates to a sequence of length zero or one, given the options stable, ascending, and empty least.

The function has been enhanced in 4.0 to allow multiple sort keys to be defined, each potentially with a different collation, and to allow sorting in descending order.

The effect of the XQuery option empty least|greatest, which controls whether the empty sequence is sorted before or after all other values, can be achieved by adding an extra sort key definition that evaluates whether or not the actual sort key is empty (when sorting boolean values, false precedes true).

Supplying too many items in the $collations and/or $orders arguments is not an error; the excess values are ignored except for type-checking against the function signature.

Examples
Expression:

sort((1, 4, 6, 5, 3))

Result:
1, 3, 4, 5, 6
Expression:

sort((1, 4, 4e0, 6, 5, 3), orders := "descending")

Result:
6, 5, 4, 4e0, 3, 1
Expression:

sort((1, -2, 5, 10, -10, 10, 8), (), abs#1)

Result:
1, -2, 5, 8, 10, -10, 10

To sort a set of strings $in using Swedish collation:

let $SWEDISH := collation({ 'lang': 'se' })
return sort($in, $SWEDISH)

To sort a sequence of employees by last name as the major sort key and first name as the minor sort key, using the default collation:

sort($employees, (), fn { name ! (last, first) })

To sort a sequence of employees first by increasing last name (using Swedish collation order) and then by decreasing salary:

sort(
  $employees, 
  collation({ 'lang': 'se' }),
  (fn { name/last }, fn { xs:decimal(salary) }), 
  ("ascending", "descending")
)

17.2.1917.2.18 fn:sort-with

Changes in 4.0  

  1. New in 4.0  [Issue 655 PR 795 20 February 2024]

Summary

Sorts a supplied sequence, according to the order induced by the supplied comparator functions.

Signature
fn:sort-with(
$inputas item()*,
$comparatorsas (fn(item(), item()) as xs:integer)*
) as item()*
Properties

This function is deterministic, context-independent, and focus-independent.

Rules

Informally, the items of the supplied $input are compared against each other, using the supplied $comparators. The result is a sorted sequence.

Each comparator function takes two items and returns an xs:integer that defines the relationship between these items, in accordance with the fn:compare function:

  • The comparators are evaluated one after the other, either completely or until the result is an integer other than 0.

  • If the last integer returned is negative or 0, the first item is returned before the second.

  • Otherwise, the second item is returned first.

Users are responsible for supplying transitive comparators; otherwise, the result might not be correctly sorted. An example for a non-transitive and thus unsuitable comparator is fn($a, $b) { if ($a mod 2 = 1) then 1 else -1 }, as it considers odd numbers to be greater than even numbers.

Sorting is stable, which means that the relative order of the input items is maintained.

More formally, assuming that the comparators raise no errors and are transitive, the effect of the function is equivalent to the following implementation in XQuery:

declare function sort-with(
  $input       as item()*,
  $comparators as (fn(item(), item()) as xs:integer)*
) as item()* {
  if (count($input) < 2) then (
    $input
  ) else (
    let $head := head($input), $sorted-tail := sort-with(tail($input), $comparators)
    let $diff := fold-left($comparators, 0, fn($df, $cmp) {
      if ($df != 0) then $df else $cmp($head, head($sorted-tail))
    })
    return if ($diff <= 0) then (
      $head, $sorted-tail
    ) else (
      head($sorted-tail), sort-with(($head, tail($sorted-tail)), $comparators)
    )
  )
};
Notes

An implementation is free to choose any sorting algorithm as long as the result returned is stable and matches the result of the implementation in XQuery.

Examples
Expression:

sort-with((1, 4, 6, 5, 3), compare#2)

Result:
1, 3, 4, 5, 6
Expression:

sort-with((1, 4, 6, 5, 3), op('-'))

Result:
1, 3, 4, 5, 6
Expression:

sort-with((1, 4, 4e0, 6, 5, 3), fn($a, $b) { compare($b, $a) })

Result:
6, 5, 4, 4e0, 3, 1
Expression:
sort-with(
  (1, -2, 5, 10, -12, 8),
  fn($a, $b) { abs($a) - abs($b) }
)
Result:
1, -2, 5, 8, 10, -12
Expression:
let $persons := <persons>
  <person name='Josipa' age='8'/>
  <person name='Jade' age='6'/>
  <person name='Jie' age='8'/>
</persons>
return sort-with($persons/person, (
  fn($a, $b) { compare($a/@age, $b/@age) },
  fn($a, $b) { compare($a/@name, $b/@name) }
))
Result:
<person name="Jade" age="6"/>
<person name="Jie" age="8"/>
<person name="Josipa" age="8"/>

17.2.2017.2.19 fn:subsequence-where

Changes in 4.0  

  1. New in 4.0  [Issue 878 PR 940 5 February 2024]

Summary

Returns a contiguous sequence of items from $input, with the start and end points located by applying predicates.

Signature
fn:subsequence-where(
$inputas item()*,
$fromas (fn(item(), xs:integer) as xs:boolean?)?:= true#0,
$toas (fn(item(), xs:integer) as xs:boolean?)?:= false#0
) as item()*
Properties

This function is deterministic, context-independent, and focus-independent.

Rules

Informally, the function returns the subsequence of $input starting with the first item that matches the $from predicate, and ending with the first subsequent item that matches the $to predicate. If $from is not supplied, it defaults to the start of $input; if $to is not supplied, it defaults to the end of $input. If $from does not match any items in $input, the result is the empty sequence; if $to does not match any items, all items up to the last are included in the result.

Formal Equivalent

The effect of the function is equivalent to the result of the following XPath expression.

let $start := index-where($input, $from)[1] otherwise count($input) + 1
let $end   := index-where($input, $to)[. ge $start][1] otherwise count($input) + 1
return slice($input, $start, $end)
Notes

The result includes both the item that matches the $from condition and the item that matches the $to condition. To select a subsequence that starts after the $from item, apply the fn:tail function to the result. To select a subsequence that ends before the $to item, apply the fn:trunk function to the result.

The predicate functions supplied to the $from and $to parameters can include an integer position argument as well as the item itself. This position will always be 1-based, relative to the start of $input. This means it is possible to select items based on their absolute position in the $input sequence, but there is no mechanism to select an end position relative to the start position. If this is needed, the function can be combined with others: for example, to select a subsequence of four items starting with "Barbara", use $input => subsequence-where(fn { . eq "Barbara" }) => slice(end := 4).

If the requirement is to select all elements stopping before the first h2 element if it exists, or up to the end of the sequence otherwise, the simplest solution is perhaps to write:

slice($input, end:=index-where($input, fn { boolean(self::h2) })[1])

A return value of () from the $from or $to predicate is treated as false.

Examples
Variables
let $names := ("Anna", "Barbara", "Catherine", "Delia",  "Eliza", "Freda",
  "Gertrude", "Hilda")
Expression:

subsequence-where($names, starts-with(?, "E"))

Result:
"Eliza", "Freda", "Gertrude", "Hilda"
Expression:

subsequence-where($names, to := starts-with(?, "D"))

Result:
"Anna", "Barbara", "Catherine", "Delia"
Expression:

subsequence-where($names, to := starts-with(?, "D")) => trunk()

Result:
"Anna", "Barbara", "Catherine"
Expression:

subsequence-where($names, starts-with(?, "E"), starts-with(?, "G"))

Result:
"Eliza", "Freda", "Gertrude"
Expression:
subsequence-where(
  $names,
  starts-with(?, "D"), fn { string-length(.) gt 5 }
)
Result:
"Delia", "Eliza", "Freda", "Gertrude"
Expression:

subsequence-where($names, starts-with(?, "M"))

Result:
()
Expression:

subsequence-where($names, starts-with(?, "G"), starts-with(?, "Z"))

Result:
"Gertrude", "Hilda"
Expression:

subsequence-where($names)

Result:
"Anna", "Barbara", "Catherine", "Delia", "Eliza", "Freda",
  "Gertrude", "Hilda"
Expression:
subsequence-where(
  $names,
  fn($it, $pos) { ends-with($it, "a") and $pos gt 5 }
)
Result:
"Freda", "Gertrude", "Hilda"
Expression:
subsequence-where(
  $names, 
  to := fn($it, $pos) { ends-with($it, "a") and $pos ge 5 }
)
Result:
"Anna", "Barbara", "Catherine", "Delia", "Eliza"

17.2.2117.2.20 fn:take-while

Changes in 4.0  

  1. New in 4.0  [Issues 1002 1038 PR 1046]

  2. The $predicate callback function may return an empty sequence (meaning false).  [Issue 1171 PR 1182 7 May 2024]

Summary

Returns items from the input sequence prior to the first one that fails to match a supplied predicate.

Signature
fn:take-while(
$inputas item()*,
$predicateas fn(item(), xs:integer) as xs:boolean?
) as item()*
Properties

This function is deterministic, context-independent, and focus-independent.

Rules

The function returns all items in the sequence prior to the first one where the result of calling the supplied $predicate function, with the current item and its position as arguments, returns the value false or ().

If every item in the sequence satisfies the predicate, then $input is returned in its entirety.

Formal Equivalent

The effect of the function is equivalent to the result of the following XQuery expression.

for $item at $pos in $input
while $predicate($item, $pos)
return $item
Notes

There is no analogous drop-while or skip-while function, as found in some functional programming languages. The effect of drop-while($input, $predicate) can be achieved by calling fn:subsequence-where($input, fn { not($predicate(.)) }).

Examples
Expression:

take-while(10 to 20, fn { . le 12 })

Result:
10, 11, 12
Expression:

take-while(10 to 20, fn { . lt 100 })

Result:
10 to 20
Expression:

take-while((), boolean#1)

Result:
()
Expression:
take-while(
  ("A", "B", "C", " ", "E"), 
  fn { boolean(normalize-space()) }
 )
Result:
"A", "B", "C"
Expression:
parse-xml("<doc><p/><p/><h2/><img/><p/></doc>")/doc/*
=> take-while(fn { boolean(self::p) })
=> count()
Result:
2
Expression:
("Aardvark", "Antelope", "Bison", "Buffalo", "Camel", "Dingo")
=> take-while(starts-with(?, "A"))
Result:
"Aardvark", "Antelope"
Expression:
take-while(10 to 20, fn($num, $pos) { $num lt 18 and $pos lt 4 })
Result:
10, 11, 12
Expression:
take-while(
  characters("ABCD-123"), 
  fn($ch, $pos) { $pos lt 4 and $ch ne '-' }
) => string-join()
Result:
"ABC"
Expression:
take-while(
  ("A", "a", "B", "b", "C", "D", "d"),
   fn($ch, $pos) {
     matches($ch, if ($pos mod 2 eq 1) then "\p{Lu}" else "\p{Ll}")
   }
 )
Result:
"A", "a", "B", "b", "C"

17.2.2217.2.21 fn:transitive-closure

Changes in 4.0  

  1. New in 4.0  [Issues 518 554 754 PRs 521 761 18 October 2023]

Summary

Returns all the nodes reachable from a given start node by applying a supplied function repeatedly.

Signature
fn:transitive-closure(
$nodeas node()?,
$stepas fn(node()) as node()*
) as node()*
Properties

This function is deterministic, context-independent, and focus-independent.

Rules

The value of $node is a node from which navigation starts. If $node is an empty sequence, the function returns an empty sequence.

The value of $step is a function that takes a single node as input, and returns a set of nodes as its result.

The result of the fn:transitive-closure function is the set of nodes that are reachable from $node by applying the $step function one or more times.

Although $step may return any sequence of nodes, the result is treated as a set: the order of nodes in the sequence is ignored, and duplicates are ignored. The result of of the transitive-closure function will always be a sequence of nodes in document order with no duplicates.

Formal Equivalent

The function delivers the same result as the following XQuery implementation.

declare %private function tc-inclusive(
  $nodes as node()*,
  $step  as fn(node()) as node()*
) as node()* {
  let $nextStep := $nodes/$step(.)
  let $newNodes := $nextStep except $nodes
  return if (exists($newNodes))
         then $nodes union tc-inclusive($newNodes, $step)
         else $nodes
};

declare function transitive-closure (
  $node as node(),
  $step as fn(node()) as node()*
) as node()* {
  tc-inclusive($node/$step(.), $step)
};

(: Explanation:

   The private helper function tc-inclusive takes a set of nodes as input,
   and calls the $step function on each one of those nodes; if the result 
   includes nodes that are not already present in the input, then it makes 
   a recursive call to find nodes reachable from these new nodes, and returns
   the union of the supplied nodes and the nodes returned from the recursive
   call (which will always include the new nodes selected in the first step).
   
   If there are no new nodes, the recursion ends, returning the nodes that 
   have been found up to this point.
   
   The main function fn:transitive-closure finds the nodes that are reachable 
   from the start node in a single step, and then invokes the helper function 
   tc-inclusive to add nodes that are reachable in multiple steps.
:)
Notes

Cycles in the data are not a problem; the function stops searching when it finds no new nodes.

The function may fail to terminate if the supplied $step function constructs and returns new nodes. A processor may detect this condition but is not required to do so.

The $node node is not included in the result, unless it is reachable by applying the $step function one or more times. If a result is required that does include $node, it can be readily added to the result using the union operator: $node | transitive-closure($node, $step).

Examples
Variables
let $data := document { <doc>
  <person id="0"/>
  <person id="1" manager="0"/>
  <person id="2" manager="0"/>
  <person id="3" manager="2"/>
  <person id="4" manager="2"/>
  <person id="5" manager="1"/>
  <person id="6" manager="3"/>
  <person id="7" manager="6"/>
  <person id="8" manager="6"/>
</doc> }
let $direct-reports := fn($p as element(person)) as element(person)* {
  $p/../person[@manager = $p/@id]
}
Expression:
transitive-closure(
  $data//person[@id = "2"],
  $direct-reports
)/string(@id)
Result:
"3", "4", "6", "7", "8"
Expression:
transitive-closure(
  $data, 
  function { child::* }
)/@id ! string()
Result:
"0", "1", "2", "3", "4", "5", "6", "7", "8"

The following example, given $root as the root of an XSLT stylesheet module, returns the URIs of all stylesheet modules reachable using xsl:import and xsl:include declarations:

transitive-closure($root, fn { document(//(xsl:import|xsl:include)/@href) }) 
=!> document-uri()

This example uses the XSLT-defined document() function.

17.2.2317.2.22 fn:while-do

Changes in 4.0  

  1. New in 4.0  [Issue 946 PR 962]

  2. The $predicate callback function may return an empty sequence (meaning false).  [Issue 1171 PR 1182 7 May 2024]

Summary

Processes a supplied value repeatedly, continuing while some condition remains true, and returning the first value that does not satisfy the condition.

Signature
fn:while-do(
$inputas item()*,
$predicateas fn(item()*, xs:integer) as xs:boolean?,
$actionas fn(item()*, xs:integer) as item()*
) as item()*
Properties

This function is deterministic, context-independent, and focus-independent.

Rules

Informally, the function behaves as follows:

  1. $pos is initially set to 1.

  2. $predicate($input, $pos) is evaluated. If the result is false or (), the function returns the value of $input.

  3. Otherwise, $action($input, $pos) is evaluated, the resulting value is used as a new $input, and the process repeats from step 2 with $pos incremented by 1.

Formal Equivalent

The function delivers the same result as the following XQuery implementation.

declare %private function while-do-helper(
  $input     as item()*,
  $predicate as fn(item()*, xs:integer) as xs:boolean?,
  $action    as fn(item()*, xs:integer) as item()*,
  $pos       as xs:integer
) as item()* {
  if ($predicate($input, $pos))
  then while-do-helper($action($input, $pos), $predicate, $action, $pos + 1)
  else $input
};

declare function while-do(
  $input     as item()*,
  $predicate as fn(item()*, xs:integer) as xs:boolean?,
  $action    as fn(item()*, xs:integer) as item()*
) as item()* {
  while-do-helper($input, $predicate, $action, 1)
};
Notes

While-do loops are very common in procedural programming languages, and this function provides a way to write functionally clean and interruptible iterations without side-effects. As long as a given condition is met, an new value is computed and tested again. Depending on the use case, the value can be a simple atomic item or an arbitrarily complex data structure.

The function fn:do-until can be used to perform the action before the first predicate test.

Note that, just as when writing recursive functions, it is easy to construct infinite loops.

Examples
Expression:
while-do(2, fn { . <= 100 }, fn { . * . })
Result:
256

(The loop is interrupted as soon as the computed product is greater than 100.)

Expression:
while-do(
  1,
  fn($num, $pos) { $pos <= 10 },
  fn($num, $pos) { $num * $pos }
)
Result:
3628800

(This returns the factorial of 10, i.e., the product of all integers from 1 to 10.)

Expression:
let $input := (0 to 4, 6 to 10)
return while-do(
  0,
  fn($n) { $n = $input },
  fn($n) { $n + 1 }
)
Result:
5

(This returns the first positive number missing in a sequence.)

Expression:
while-do(
  1 to 9,
  fn($value) { head($value) < 5 },
  fn($value) { tail($value) }
)
Result:
5, 6, 7, 8, 9

(The first number of a sequence is removed as long as it is smaller than 5.)

Expression:
let $input := 3936256
return while-do(
  $input,
  fn($result) { abs($result * $result - $input) >= 0.0000000001 },
  fn($guess) { ($guess + $input div $guess) div 2 }
) => round(5)
Result:
1984

(This computes the square root of a number.)

The following example generates random doubles. It is interrupted once a number exceeds a given limit:

let $result := while-do(
  random-number-generator(),
  fn($random) {
    $random?number < 0.8
  },
  fn($random) {
    map:put($random?next(), 'numbers', ($random?numbers, $random?number))
  }
)
return $result?numbers

G Changes since 3.1 (Non-Normative)

G.1 Summary of Changes

  1. Use the arrows to browse significant changes since the 3.1 version of this specification.

    See 1 Introduction

  2. Sections with significant changes are marked Δ in the table of contents. New functions introduced in this version are marked ➕ in the table of contents.

    See 1 Introduction

  3. PR 1620 1886 

    Options are added to customize the form of the output.

    See 2.2.6 fn:path

  4. PR 1547 1551 

    New in 4.0

    See 2.2.8 fn:siblings

  5. PR 629 803 

    New in 4.0

    See 3.2.2 fn:message

  6. PR 1260 1275 

    A third argument has been added, providing control over the rounding mode.

    See 4.4.4 fn:round

  7. New in 4.0

    See 4.4.7 fn:is-NaN

  8. PR 1049 1151 

    Decimal format parameters can now be supplied directly as a map in the third argument, rather than referencing a format defined in the static context.

    See 4.7.2 fn:format-number

  9. PR 1205 1230 

    New in 4.0

    See 4.8.2 math:e

    See 4.8.16 math:sinh

    See 4.8.17 math:cosh

    See 4.8.18 math:tanh

  10. The 3.1 specification suggested that every value in the result range should have the same chance of being chosen. This has been corrected to say that the distribution should be arithmetically uniform (because there are as many xs:double values between 0.01 and 0.1 as there are between 0.1 and 1.0).

    See 4.9.2 fn:random-number-generator

  11. PR 261 306 993 

    New in 4.0

    See 5.4.1 fn:char

  12. New in 4.0

    See 5.4.2 fn:characters

  13. PR 937 995 1190 

    New in 4.0

    See 5.4.13 fn:hash

  14. New in 4.0

    See 7.6.2 fn:parse-uri

  15. PR 1423 1413 

    New in 4.0

    See 7.6.3 fn:build-uri

  16. New in 4.0

    See 11.2.6 fn:in-scope-namespaces

  17. Reformulated in 4.0 in terms of the new fn:in-scope-namespaces function; the semantics are unchanged.

    See 11.2.7 fn:in-scope-prefixes

  18. Reformulated in 4.0 in terms of the new fn:in-scope-namespaces function; the semantics are unchanged.

    See 11.2.8 fn:namespace-uri-for-prefix

  19. New in 4.0

    See 14.1.9 fn:replicate

  20. New in 4.0

    See 14.1.12 fn:slice

  21. New in 4.0. The function is identical to the internal op:same-key function in 3.1

    See 14.2.1 fn:atomic-equal

  22. PR 1120 1150 

    A callback function can be supplied for comparing individual items.

    See 14.2.2 fn:deep-equal

  23. Changed in 4.0 to use transitive equality comparisons for numeric values.

    See 14.2.4 fn:distinct-values

  24. PR 614 987 

    New in 4.0

    See 14.2.5 fn:duplicate-values

  25. New in 4.0. Originally proposed under the name fn:uniform

    See 14.4.6 fn:all-equal

  26. New in 4.0. Originally proposed under the name fn:unique

    See 14.4.7 fn:all-different

  27. PR 1117 1279 

    The $options parameter has been added.

    See 14.6.6 fn:unparsed-text-lines

  28. New in 4.0

    See 15.1.4 fn:xsd-validator

  29. PR 259 956 

    A new function is available for processing input data in HTML format.

    See 15.2 Functions on HTML Data

    New in 4.0

    See 15.2.2 fn:parse-html

  30. PR 975 1058 1246 

    An option is provided to control how JSON numbers should be formatted.

    See 15.3.4 fn:parse-json

  31. Additional options are available, as defined by fn:parse-json.

    See 15.3.5 fn:json-doc

  32. PR 533 719 834 1066 

    New in 4.0

    See 15.4.4 fn:csv-to-arrays

    See 15.4.7 fn:parse-csv

  33. PR 533 719 834 1066 1605 

    New in 4.0

    See 15.4.9 fn:csv-to-xml

  34. PR 791 1256 1282 1405 

    New in 4.0

    See 15.5.1 fn:invisible-xml

  35. New in 4.0

    See 17.2.417.2.3 fn:every

  36. New in 4.0

    See 17.2.1017.2.9 fn:highest

  37. New in 4.0

    See 17.2.1117.2.10 fn:index-where

  38. New in 4.0

    See 17.2.1217.2.11 fn:lowest

  39. New in 4.0

    See 17.2.1617.2.15 fn:scan-right

  40. New in 4.0

    See 17.2.1717.2.16 fn:some

  41. PR 521 761 

    New in 4.0

    See 17.2.2217.2.21 fn:transitive-closure

  42. New in 4.0

    See 18.4.6 map:filter

  43. New in 4.0

    See 18.4.10 map:items

  44. PR 478 515 

    New in 4.0

    See 18.4.12 map:keys-where

  45. New in 4.0

    See 18.4.14 map:of-pairs

  46. New in 4.0

    See 18.4.15 map:pair

  47. New in 4.0

    See 18.4.16 map:pairs

  48. PR 1575 1906 

    A new function fn:element-to-map is provided for converting XDM trees to maps suitable for serialization as JSON. Unlike the fn:xml-to-json function retained from 3.1, this can handle arbitrary XML as input.

    See 18.5 Converting elements to maps

  49. New in 4.0

    See 19.2.3 array:empty

  50. PR 968 1295 

    New in 4.0

    See 19.2.13 array:index-of

  51. PR 476 1087 

    New in 4.0

    See 19.2.16 array:items

  52. PR 360 476 

    New in 4.0

    See 19.2.18 array:members

    See 19.2.19 array:of-members

  53. New in 4.0

    See 19.2.24 array:slice

  54. New in 4.0

    See 19.2.25 array:sort

  55. New in 4.0

    See 19.2.26 array:split

  56. Supplying an empty sequence as the value of an optional argument is equivalent to omitting the argument.

    See 19.2.27 array:subarray

  57. PR 533 719 834 

    New functions are available for processing input data in CSV (comma separated values) format.

    See 15.4 Functions on CSV Data

  58. PR 734 1233 

    New in 4.0

    See 17.2.2 fn:chain

  59. PR 289 1901 

    A third argument is added, allowing user control of how absent keys should be handled.

    See 18.4.9 map:get

    A third argument is added, allowing user control of how index-out-of-bounds conditions should be handled.

    See 19.2.11 array:get

  60. A new collation URI is defined for Unicode case-insensitive comparison and ordering.

    See 5.3.5 The Unicode case-insensitive collation

  61. The specification now describes how an initial BOM should be handled.

    See 14.6.5 fn:unparsed-text

  62. PR 1727 1740 

    It is no longer guaranteed that the new key replaces the existing key.

    See 18.4.17 map:put

  63. PR 173 

    New in 4.0

    See 17.3.4 fn:op

  64. PR 203 

    New in 4.0

    See 18.4.1 map:build

  65. PR 207 

    New in 4.0

    See 11.1.2 fn:parse-QName

    See 11.2.5 fn:expanded-QName

  66. PR 222 

    New in 4.0

    See 14.2.7 fn:starts-with-subsequence

    See 14.2.8 fn:ends-with-subsequence

    See 14.2.9 fn:contains-subsequence

  67. PR 250 

    New in 4.0

    See 14.1.3 fn:foot

    See 14.1.15 fn:trunk

    See 19.2.2 array:build

    See 19.2.8 array:foot

    See 19.2.29 array:trunk

  68. PR 258 

    New in 4.0

    See 19.2.14 array:index-where

  69. PR 313 

    The second argument can now be a sequence of integers.

    See 14.1.8 fn:remove

  70. PR 314 

    New in 4.0

    See 18.4.4 map:entries

  71. PR 326 

    Higher-order functions are no longer an optional feature.

    See 1.2 Conformance

  72. PR 419 

    New in 4.0

    See 14.1.7 fn:items-at

  73. PR 434 

    New in 4.0

    See 4.5.2 fn:parse-integer

    The function has been extended to allow output in a radix other than 10, for example in hexadecimal.

    See 4.6.1 fn:format-integer

  74. PR 482 

    Deleted an inaccurate statement concerning the behavior of NaN.

    See 4.3 Comparison operators on numeric values

  75. PR 507 

    New in 4.0

    See 17.2.1417.2.13 fn:partition

  76. PR 546 

    It is no longer automatically an error if the input contains a codepoint that is not valid in XML. Instead, the codepoint must be a permitted character. The set of permitted characters is implementation-defined, but it is recommended that all Unicode characters should be accepted.

    See 5.2.1 fn:codepoints-to-string

    It is no longer automatically an error if the resource (after decoding) contains a codepoint that is not valid in XML. Instead, the codepoint must be a permitted character. The set of permitted characters is implementation-defined, but it is recommended that all Unicode characters should be accepted.

    See 14.6.5 fn:unparsed-text

    The rules regarding use of non-XML characters in JSON texts have been relaxed.

    See 15.3.3 JSON character repertoire

    See 15.3.4 fn:parse-json

    It is no longer automatically an error if the input contains a codepoint that is not valid in XML. Instead, the codepoint must be a permitted character. The set of permitted characters is implementation-defined, but it is recommended that all Unicode characters should be accepted.

    See 15.3.5 fn:json-doc

  77. PR 623 

    Substantially revised to allow multiple sort key definitions.

    See 17.2.1817.2.17 fn:sort

  78. PR 631 

    New in 4.0

    See 7.3 fn:decode-from-uri

  79. PR 662 

    Constructor functions now have a zero-arity form; the first argument defaults to the context item.

    See 21 Constructor functions

  80. PR 680 

    The case-insensitive collation is now defined normatively within this specification, rather than by reference to the HTML "living specification", which is subject to change. The collation can now be used for ordering comparisons as well as equality comparisons.

    See 5.3.6 The HTML ASCII Case-Insensitive Collation

  81. PR 702 

    The function can now take any number of arguments (previously it had to be two or more), and the arguments can be sequences of strings rather than single strings.

    See 5.4.4 fn:concat

  82. PR 710 

    Changes the function to return a sequence of key-value pairs rather than a map.

    See 17.1.5 fn:function-annotations

  83. PR 727 

    It has been clarified that loading a module has no effect on the static or dynamic context of the caller.

    See 17.3.2 fn:load-xquery-module

  84. PR 795 

    New in 4.0

    See 17.2.1917.2.18 fn:sort-with

  85. PR 828 

    The $predicate callback function accepts an optional position argument.

    See 17.2.517.2.4 fn:filter

    The $action callback function accepts an optional position argument.

    See 17.2.717.2.6 fn:fold-right

    See 17.2.817.2.7 fn:for-each

    See 17.2.917.2.8 fn:for-each-pair

    The $predicate callback function now accepts an optional position argument.

    See 19.2.4 array:filter

    The $action callback function now accepts an optional position argument.

    See 19.2.7 array:fold-right

    See 19.2.9 array:for-each

    See 19.2.10 array:for-each-pair

  86. PR 881 

    The way that fn:min and fn:max compare numeric values of different types has changed. The most noticeable effect is that when these functions are applied to a sequence of xs:integer or xs:decimal values, the result is an xs:integer or xs:decimal, rather than the result of converting this to an xs:double

    See 14.4.3 fn:max

    See 14.4.4 fn:min

  87. PR 901 

    All three arguments are now optional, and each argument can be set to an empty sequence. Previously if $description was supplied, it could not be empty.

    See 3.1.1 fn:error

    The $label argument can now be set to an empty sequence. Previously if $label was supplied, it could not be empty.

    See 3.2.1 fn:trace

    The third argument can now be supplied as an empty sequence.

    See 5.4.6 fn:substring

    The second argument can now be an empty sequence.

    See 6.3.3 fn:tokenize

    The optional second argument can now be supplied as an empty sequence.

    See 7.1 fn:resolve-uri

    The 3rd, 4th, and 5th arguments are now optional; previously the function required either 2 or 5 arguments.

    See 10.8.1 fn:format-dateTime

    See 10.8.2 fn:format-date

    See 10.8.3 fn:format-time

    The optional third argument can now be supplied as an empty sequence.

    See 14.1.13 fn:subsequence

  88. PR 905 

    The rule that multiple calls on fn:doc supplying the same absolute URI must return the same document node has been clarified; in particular the rule does not apply if the dynamic context for the two calls requires different processing of the documents (such as schema validation or whitespace stripping).

    See 14.6.1 fn:doc

  89. PR 909 

    The function has been expanded in scope to handle comparison of values other than strings.

    See 14.2.3 fn:compare

  90. PR 924 

    Rules have been added clarifying that users should not be allowed to change the schema for the fn namespace.

    See C Schemas

  91. PR 925 

    The decimal format name can now be supplied as a value of type xs:QName, as an alternative to supplying a lexical QName as an instance of xs:string.

    See 4.7.2 fn:format-number

  92. PR 932 

    The specification now prescribes a minimum precision and range for durations.

    See 9.1.2 Limits and precision

  93. PR 933 

    When comments and processing instructions are ignored, any text nodes either side of the comment or processing instruction are now merged prior to comparison.

    See 14.2.2 fn:deep-equal

  94. PR 940 

    New in 4.0

    See 17.2.2017.2.19 fn:subsequence-where

  95. PR 953 

    Constructor functions for named record types have been introduced.

    See 21.6 Constructor functions for named record types

  96. PR 962 

    New in 4.0

    See 17.2.317.2.2 fn:do-until

    See 17.2.2317.2.22 fn:while-do

  97. PR 969 

    New in 4.0

    See 18.4.3 map:empty

  98. PR 984 

    New in 4.0

    See 9.4.1 fn:seconds

  99. PR 987 

    The order of results is now prescribed; it was previously implementation-dependent.

    See 14.2.4 fn:distinct-values

  100. PR 988 

    New in 4.0

    See 15.3.8 fn:pin

    See 15.3.9 fn:label

  101. PR 1022 

    Regular expressions can include comments (starting and ending with #) if the c flag is set.

    See 6.1 Regular expression syntax

    See 6.2 Flags

  102. PR 1028 

    An option is provided to control how the JSON null value should be handled.

    See 15.3.4 fn:parse-json

  103. PR 1032 

    New in 4.0

    See 14.1.17 fn:void

  104. PR 1046 

    New in 4.0

    See 17.2.2117.2.20 fn:take-while

  105. PR 1059 

    Use of an option keyword that is not defined in the specification and is not known to the implementation now results in a dynamic error; previously it was ignored.

    See 1.7 Options

  106. PR 1068 

    New in 4.0

    See 5.4.3 fn:graphemes

  107. PR 1072 

    The return type is now specified more precisely.

    See 17.3.2 fn:load-xquery-module

  108. PR 1090 

    When casting from a string to a duration or time or dateTime, it is now specified that when there are more digits in the fractional seconds than the implementation is able to retain, excess digits are truncated. Rounding upwards (which could affect the number of minutes or hours in the value) is not permitted.

    See 22.2 Casting from xs:string and xs:untypedAtomic

  109. PR 1093 

    New in 4.0

    See 5.3.9 fn:collation

  110. PR 1117 

    The $options parameter has been added.

    See 14.6.5 fn:unparsed-text

    See 14.6.7 fn:unparsed-text-available

  111. PR 1182 

    The $predicate callback function may return an empty sequence (meaning false).

    See 17.2.317.2.2 fn:do-until

    See 17.2.417.2.3 fn:every

    See 17.2.517.2.4 fn:filter

    See 17.2.1117.2.10 fn:index-where

    See 17.2.1717.2.16 fn:some

    See 17.2.2117.2.20 fn:take-while

    See 17.2.2317.2.22 fn:while-do

    See 18.4.6 map:filter

    See 18.4.12 map:keys-where

    See 19.2.4 array:filter

    See 19.2.14 array:index-where

  112. PR 1191 

    New in 4.0

    See 2.3.1 fn:distinct-ordered-nodes

    The $options parameter has been added, absorbing the $collation parameter.

    See 14.2.2 fn:deep-equal

  113. PR 1250 

    For selected properties including percent and exponent-separator, it is now possible to specify a single-character marker to be used in the picture string, together with a multi-character rendition to be used in the formatted output.

    See 4.7.2 fn:format-number

  114. PR 1257 

    The $options parameter has been added.

    See 15.1.1 fn:parse-xml

    See 15.1.2 fn:parse-xml-fragment

  115. PR 1262 

    New in 4.0

    See 5.3.10 fn:collation-available

  116. PR 1265 

    The constraints on the result of the function have been relaxed.

    See 2.1.6 fn:document-uri

  117. PR 1280 

    As a result of changes to the coercion rules, the number of supplied arguments can be greater than the number required: extra arguments are ignored.

    See 17.2.1 fn:apply

  118. PR 1288 

    Additional error conditions have been defined.

    See 15.1.1 fn:parse-xml

  119. PR 1296 

    New in 4.0

    See 17.2.1517.2.14 fn:scan-left

  120. PR 1333 

    A new option is provided to allow the content of the loaded module to be supplied as a string.

    See 17.3.2 fn:load-xquery-module

  121. PR 1353 

    An option has been added to suppress the escaping of the solidus (forwards slash) character.

    See 15.3.7 fn:xml-to-json

  122. PR 1358 

    New in 4.0

    See 10.3.2 fn:unix-dateTime

  123. PR 1361 

    The term atomic value has been replaced by atomic item.

    See 1.9 Terminology

  124. PR 1393 

    Changes the function to return a sequence of key-value pairs rather than a map.

    See 17.1.5 fn:function-annotations

  125. PR 1409 

    This section now uses the term primitive type strictly to refer to the 20 atomic types that are not derived by restriction from another atomic type: that is, the 19 primitive atomic types defined in XSD, plus xs:untypedAtomic. The three types xs:integer, xs:dayTimeDuration, and xs:yearMonthDuration, which have custom casting rules but are not strictly-speaking primitive, are now handled in other subsections.

    See 22.1 Casting from primitive types to primitive types

    The rules for conversion of dates and times to strings are now defined entirely in terms of XSD 1.1 canonical mappings, since these deliver exactly the same result as the XPath 3.1 rules.

    See 22.1.2.2 Casting date/time values to xs:string

    The rules for conversion of durations to strings are now defined entirely in terms of XSD 1.1 canonical mappings, since the XSD 1.1 rules deliver exactly the same result as the XPath 3.1 rules.

    See 22.1.2.3 Casting xs:duration values to xs:string

  126. PR 1455 

    Numbers now retain their original lexical form, except for any changes needed to satisfy JSON syntax rules (for example, stripping leading zero digits).

    See 15.3.7 fn:xml-to-json

  127. PR 1473 

    New in 4.0

    See 14.1.5 fn:identity

  128. PR 1481 

    The function has been extended to handle other Gregorian types such as xs:gYearMonth.

    See 10.5.1 fn:year-from-dateTime

    See 10.5.2 fn:month-from-dateTime

    The function has been extended to handle other Gregorian types such as xs:gMonthDay.

    See 10.5.3 fn:day-from-dateTime

    The function has been extended to handle other types including xs:time.

    See 10.5.4 fn:hours-from-dateTime

    See 10.5.5 fn:minutes-from-dateTime

    The function has been extended to handle other types such as xs:gYearMonth.

    See 10.5.7 fn:timezone-from-dateTime

  129. PR 1504 

    New in 4.0

    See 14.1.11 fn:sequence-join

    Optional $separator added.

    See 19.2.17 array:join

  130. PR 1523 

    New functions are provided to obtain information about built-in types and types defined in an imported schema.

    See 20 Processing types

    New in 4.0

    See 20.1.2 fn:schema-type

    See 20.1.4 fn:atomic-type-annotation

    See 20.1.5 fn:node-type-annotation

  131. PR 1545 

    New in 4.0

    See 10.6.4 fn:civil-timezone

  132. PR 1565 

    The default for the escape option has been changed to false. The 3.1 specification gave the default value as true, but this appears to have been an error, since it was inconsistent with examples given in the specification and with tests in the test suite.

    See 15.3.4 fn:parse-json

  133. PR 1570 

    New in 4.0

    See 20.1.3 fn:type-of

  134. PR 1587 

    New in 4.0

    See 14.6.8 fn:unparsed-binary

  135. PR 1611 

    The spec has been corrected to note that the function depends on the implicit timezone.

    See 14.2.3 fn:compare

  136. PR 1671 

    New in 4.0.

    See 4.4.6 fn:divide-decimals

  137. PR 1703 

    The order of entries in maps is retained.

    See 15.3.4 fn:parse-json

    Ordered maps are introduced.

    See 18.1 Ordering of Maps

    Enhanced to allow for ordered maps.

    See 18.4.6 map:filter

    See 18.4.7 map:find

    See 18.4.8 map:for-each

    See 18.4.17 map:put

    See 18.4.18 map:remove

  138. PR 1711 

    It is explicitly stated that the limits for $precision are implementation-defined.

    See 4.4.4 fn:round

    See 4.4.5 fn:round-half-to-even

  139. PR 1727 

    For consistency with the new functions map:build and map:of-pairs, the handling of duplicates may now be controlled by supplying a user-defined callback function as an alternative to the fixed values for the earlier duplicates option.

    See 18.4.13 map:merge

  140. PR 1734 

    In 3.1, given a mixed input sequence such as (1, 3, 4.2e0), the specification was unclear whether it was permitted to add the first two integer items using integer arithmetic, rather than converting all items to doubles before performing any arithmetic. The 4.0 specification is clear that this is permitted; but since the items can be reordered before being added, this is not required.

    See 14.4.2 fn:avg

    See 14.4.5 fn:sum

  141. PR 1825 

    New in 4.0

    See 17.2.1317.2.12 fn:partial-apply

  142. PR 1856 

    Word boundaries can be matched. Lookahead and lookbehind assertions are supported. Assertions (including ^ and $) can no longer be followed by a quantifier.

    See 6.1 Regular expression syntax

    It is now permitted for the regular expression to match a zero-length string.

    See 6.3.2 fn:replace

    See 6.3.3 fn:tokenize

    The output of the function is extended to allow the represention of captured groups found within lookahead assertions.

    See 6.3.4 fn:analyze-string

    It is now permitted for the regular expression to match a zero-length string.

    See 6.3.4 fn:analyze-string

  143. PR 1879 

    Additional options to control DTD and XInclude processing have been added.

    See 15.1.1 fn:parse-xml

  144. PR 1897 

    The $replacement argument can now be a function that computes the replacement strings.

    See 6.3.2 fn:replace

  145. PR 1906 

    New in 4.0

    See 18.5.10 fn:element-to-map-plan

    New in 4.0.

    See 18.5.11 fn:element-to-map

  146. PR 1910 

    An $options parameter is added. Note that the rules for the $options parameter control aspects of processing that were implementation-defined in earlier versions of this specification. An implementation may provide configuration options designed to retain backwards-compatible behavior when no explicit options are supplied.

    See 14.6.1 fn:doc

    See 14.6.2 fn:doc-available