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 version 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).


13 Functions and operators on sequences

A sequence is an ordered collection of zero or more items. An item is a node, an atomic item, or a function, such as a map or an array. The terms sequence and item are defined formally in [XQuery 4.0: An XML Query Language] and [XML Path Language (XPath) 4.0].

13.2 Comparison functions

The functions in this section perform comparisons between the items in one or more sequences.

FunctionMeaning
fn:atomic-equalDetermines whether two atomic items are equal, under the rules used for comparing keys in a map.
fn:deep-equal This function assesses whether two sequences are deep-equal to each other. To be deep-equal, they must contain items that are pairwise deep-equal; and for two items to be deep-equal, they must either be atomic items that compare equal, or nodes of the same kind, with the same name, whose children are deep-equal, or maps with matching entries, or arrays with matching members.
fn:compareReturns -1, 0, or 1, depending on whether the first value is less than, equal to, or greater than the second value.
fn:distinct-valuesReturns the values that appear in a sequence, with duplicates eliminated.
fn:duplicate-valuesReturns the values that appear in a sequence more than once.
fn:index-ofReturns a sequence of positive integers giving the positions within the sequence $input of items that are equal to $target.
fn:starts-with-subsequenceDetermines whether one sequence starts with another, using a supplied callback function to compare items.
fn:ends-with-subsequenceDetermines whether one sequence ends with another, using a supplied callback function to compare items.
fn:contains-subsequenceDetermines whether one sequence contains another as a contiguous subsequence, using a supplied callback function to compare items.

13.2.4 fn:distinct-values

Changes in 4.0  

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

  2. The order of results is now prescribed; it was previously implementation-dependent.  [Issue 628 PR 987]

Summary

Returns the values that appear in a sequence, with duplicates eliminated.

Signature
fn:distinct-values(
$valuesas xs:anyAtomicType*,
$collationas xs:string?:= fn:default-collation()
) as xs:anyAtomicType*
Properties

The one-argument form of this function is ·deterministic·, ·context-dependent·, and ·focus-independent·. It depends on collations, and implicit timezone.

The two-argument form of this function is ·deterministic·, ·context-dependent·, and ·focus-independent·. It depends on collations, and static base URI, and implicit timezone.

Rules

The function returns the sequence that results from removing from $values all but one of a set of values that are considered equal to one another. Two items $J and $K in the input sequence (after atomization, as required by the function signature) are considered equal if fn:deep-equal($J, $K, $coll) is true, where $coll is the collation selected according to the rules in 5.3.6 Choosing a collation. This collation is used when string comparison is required.

If ordering mode (in the static context) is ordered then:

The ordering of the result is as follows:

  • For any set of values that compare equal, the one that is returned is the one that appears first in $values.

  • The items that are returned appear in the order in which they occurof their first appearance within $values.

By contrast, if ordering mode is unordered then:

Notes

If $values is the empty sequence, the function returns the empty sequence.

Values of type xs:untypedAtomic are compared as if they were of type xs:string.

Values that cannot be compared, because the eq operator is not defined for their types, are considered to be distinct.

For xs:float and xs:double values, positive zero is equal to negative zero and, although NaN does not equal itself, if $values contains multiple NaN values a single NaN is returned.

If xs:dateTime, xs:date or xs:time values do not have a timezone, they are considered to have the implicit timezone provided by the dynamic context for the purpose of comparison. Note that xs:dateTime, xs:date or xs:time values can compare equal even if their timezones are different.

Editorial note 
Ordering mode has been dropped.
Examples
ExpressionResult
distinct-values((1, 2.0, 3, 2))
1, 2.0, 3

(Assuming ordering mode is ordered.)

distinct-values((
  xs:untypedAtomic("cherry"),
  xs:untypedAtomic("plum"),
  xs:untypedAtomic("plum")
))
xs:untypedAtomic("cherry"), xs:untypedAtomic("plum")

(Assuming ordering mode is ordered.)

13.2.5 fn:duplicate-values

Changes in 4.0  

  1. New in 4.0  [Issue 123 PR 614]

  2. The order of results is now prescribed; it was previously implementation-dependent.  [Issue 628 PR 987]

Summary

Returns the values that appear in a sequence more than once.

Signature
fn:duplicate-values(
$valuesas xs:anyAtomicType*,
$collationas xs:string?:= fn:default-collation()
) as xs:anyAtomicType*
Properties

The one-argument form of this function is ·deterministic·, ·context-dependent·, and ·focus-independent·. It depends on collations, and implicit timezone.

The two-argument form of this function is ·deterministic·, ·context-dependent·, and ·focus-independent·. It depends on collations, and static base URI, and implicit timezone.

Rules

The items of $values are compared against each other, according to the rules of fn:distinct-values and with $coll as the collation selected according to the rules in 5.3.6 Choosing a collation.

From each resulting set of values that are considered equal, one value will be returned if the set contains more than one value.

If ordering mode (in the static context) is ordered then:

The ordering of the result is as follows:

  • For any set of values that compare equal, the one that is returned is the one that appears first in $values.

  • The items that are returned appear in the order in which they occurof their first appearance within $values.

By contrast, if ordering mode is unordered then:

Notes

The effect of the function is equivalent to the following XSLT expression:

<xsl:for-each-group select="$values" group-by="." collation="{ $collation }">
  <xsl:sequence select="current-group()[2]"/>
</xsl:for-each>

The following XQuery expression is equivalent if no collation is specified (group by requires collation URIs to be static):

for $group in $values
group by $value := $group
where count($group) > 1
return $value
Examples
Expression:

duplicate-values((1, 2, 3, 1.0, 1e0))

Result:
1

(If ordering mode is ordered the result will be the xs:integer value 1.)

Expression:

duplicate-values(1 to 100)

Result:
()
Expression:

duplicate-values(('1', <x>1</x>, '2', 2))

Result:
"1"

(The string "1" and the untyped value of the element node are considered equal, whereas the string "2" and the integer are considered unequal.)

Raise an error for duplicates in an ID sequence:

let $ids := duplicate-values(//@id)
where exists($ids)
return error((), 'Duplicate IDs found: ' || string-join($ids, ', '))

16 Higher-order functions

16.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: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 complete (ordered) sequence of all partial results from every new value the accumulator is assigned to during the evaluation of fn:fold-left.
fn:scan-rightProduces the complete (ordered) sequence of all partial results from every new value the accumulator is assigned to during the evaluation of fn:fold-right.
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.

16.2.8 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 (provided that ordering mode is ordered).

Formal Equivalent

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

fold-left($input, (), fn($result, $next, $pos) {
  $result, $action($next, $pos)
})
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"