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


18 Processing maps

Maps were introduced as a new datatype in XDM 3.1. This section describes functions that operate on maps.

A map is a kind of item.

[Definition] A map consists of a sequence of entries, also known as key-value pairs. Each entry comprises a key which is an arbitrary atomic item, and an arbitrary sequence called the associated value.

[Definition] Within a map, no two entries have the same key. Two atomic items K1 and K2 are the same key for this purpose if the function call fn:atomic-equal($K1, $K2) returns true.

It is not necessary that all the keys in a map should be of the same type (for example, they can include a mixture of integers and strings).

Maps are immutable, and have no identity separate from their content. For example, the map:remove function returns a map that differs from the supplied map by the omission (typically) of one entry, but the supplied map is not changed by the operation. Two calls on map:remove with the same arguments return maps that are indistinguishable from each other; there is no way of asking whether these are “the same map”.

A map can also be viewed as a function from keys to associated values. To achieve this, a map is also a function item. The function corresponding to the map has the signature function($key as xs:anyAtomicValue) as item()*. Calling the function has the same effect as calling the map:get function: the expression $map($key) returns the same result as get($map, $key). For example, if $books-by-isbn is a map whose keys are ISBNs and whose assocated values are book elements, then the expression $books-by-isbn("0470192747") returns the book element with the given ISBN. The fact that a map is a function item allows it to be passed as an argument to higher-order functions that expect a function item as one of their arguments.

18.4 Functions that Operate on Maps

The functions defined in this section use a conventional namespace prefix map, which is assumed to be bound to the namespace URI http://www.w3.org/2005/xpath-functions/map.

The function call map:get($map, $key) can be used to retrieve the value associated with a given key.

There is no operation to atomize a map or convert it to a string. The function fn:serialize can in some cases be used to produce a JSON representation of a map.

FunctionMeaning
map:buildReturns a map that typically contains one entry for each item in a supplied input sequence.
map:containsTests whether a supplied map contains an entry for a given key.
map:emptyReturns true if the supplied map contains no entries.
map:entriesReturns a sequence containing all the key-value pairs present in a map, each represented as a single-entry map.
map:entryReturns a single-entry map that represents a single key-value pair.
map:filterSelects entries from a map, returning a new map.
map:findSearches the supplied input sequence and any contained maps and arrays for a map entry with the supplied key, and returns the corresponding values.
map:for-eachApplies a supplied function to every entry in a map, returning the sequence concatenationXP of the results.
map:getReturns the value associated with a supplied key in a given map.
map:itemsReturns a sequence containing all the values present in a map, in order.
map:keysReturns a sequence containing all the keys present in a map.
map:keys-whereReturns a sequence containing selected keys present in a map.
map:mergeReturns a map that combines the entries from a number of existing maps.
map:of-pairsReturns a map that combines data from a sequence of key-value pair maps.
map:pairReturns a key-value pair map that represents a single key-value pair.
map:pairsReturns a sequence containing all the key-value pairs present in a map, each represented as a key-value pair map.
map:putReturns a map containing all the contents of the supplied map, but with an additional entry, which replaces any existing entry for the same key.
map:removeReturns a map containing all the entries from a supplied map, except those having a specified key.
map:sizeReturns the number of entries in the supplied map.

18.4.1 map:build

Changes in 4.0  

  1. New in 4.0  [Issue 151 PR 203 18 October 2022]

Summary

Returns a map that typically contains one entry for each item in a supplied input sequence.

Signature
map:build(
$inputas item()*,
$keysas (fn($item as item(), $position as xs:integer) as xs:anyAtomicType*)?:= fn:identity#1,
$valueas (fn($item as item(), $position as xs:integer) as item()*)?:= fn:identity#1,
$optionsas map(*):= {}
) as map(*)
Properties

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

Rules

Informally, the function processes each item in $input in order. It calls the $keys function on that item to obtain a sequence of key values, and the $value function to obtain an associated value. Then, for each key value:

  • If the key is not already present in the target map, the processor adds a new key-value pair to the map, with that key and that value.

  • If the key is already present, the processor combines the new value for the key with the existing value as; the way they are combined is determined by the and duplicates option.

    By default, when two duplicate entries occur:

    • A single combined entry will be present in the result.

    • This entry will contain the sequence concatenationXP of the supplied values.

    • The position of the combined entry in the entry orderDM of the result map will correspond to the position of the first of the duplicates.

    • The key of the combined entry will correspond to the key of one of the duplicates: it is implementation-dependent which one is chosen. (It is possible for two keys to be considered duplicates even if they differ: for example, they may have different type annotations, or they may be xs:dateTime values in different timezones.)

    The $options argument can be used to control the way in which duplicate keys are handled. The allowed options, and their meanings, are the same as for the map:of-pairs function. The option parameter conventions apply.

Formal Equivalent

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

for-each(
  $input, 
  fn($item, $pos) {
    for-each($keys($item, $pos), fn($k) {
      map:pair($k, $value($item, $pos))
    }
  )}
)
=> map:of-pairs($options)
Error Conditions

An error is raised [err:FOJS0003] if the value of $options indicates that duplicates are to be rejected, and a duplicate key is encountered.

An error is raised [err:FOJS0005] if the value of $options includes an entry whose key is defined in this specification, and whose value is not a permitted value for that key.

Notes

The default function for both $keys and $value is the identity function. Although it is permitted to default both, this serves little purpose: usually at least one of these arguments will be supplied.

Examples
Expression:

map:build((), string#1)

Result:
{}
Expression:

map:build(1 to 10, fn { . mod 3 })

Result:
{ 0: (3, 6, 9), 1: (1, 4, 7, 10), 2: (2, 5, 8) }

(Returns a map with one entry for each distinct value of . mod 3. The function to compute the value is the identity function, and duplicates are combined by sequence concatenation.)

Expression:
map:build(
  1 to 5,
  value := format-integer(?, "w")
)
Result:
{ 1: "one", 2: "two", 3: "three", 4: "four", 5: "five" }

(Returns a map with five entries. The function to compute the key is an identity function, the function to compute the value invokes fn:format-integer.)

Expression:
map:build(
  ("January", "February", "March", "April", "May", "June",
   "July", "August", "September", "October", "November", "December"),
  substring(?, 1, 1)
)
Result:
{
  "A": ("April", "August"),
  "D": ("December"),
  "F": ("February"),
  "J": ("January", "June", "July"),
  "M": ("March", "May"),
  "N": ("November"),
  "O": ("October"),
  "S": ("September")
}
Expression:
map:build(
  ("apple", "apricot", "banana", "blueberry", "cherry"), 
  substring(?, 1, 1),
  string-length#1,
  { "duplicates": op("+") }
)
Result:
{ "a": 12, "b": 15, "c": 6 }

(Constructs a map where the key is the first character of an input item, and where the corresponding value is the total string-length of the items starting with that character.)

Expression:
map:build(
  ('Wang', 'Liu', 'Zhao'),
  keys := fn($name, $pos) { $name },
  value := fn($name, $pos) { $pos }
)
Result:
{ "Wang": 1, "Liu": 2, "Zhao": 3 }

(Returns an inverted index for the input sequence with the string stored as key and the position stored as value.)

Expression:
let $titles := <titles>
  <title>A Beginner’s Guide to <ix>Java</ix></title>
  <title>Learning <ix>XML</ix></title>
  <title>Using <ix>XML</ix> with <ix>Java</ix></title>
</titles>
return map:build($titles/title, fn($title) { $title/ix })
Result:
{
  "Java": (
    <title>A Beginner’s Guide to <ix>Java</ix></title>,
    <title>Using <ix>XML</ix> with <ix>Java</ix></title>
  ),
  "XML": (
    <title>Learning <ix>XML</ix></title>,
    <title>Using <ix>XML</ix> with <ix>Java</ix></title>
  )
}

The following expression creates a map whose keys are employee @ssn values, and whose corresponding values are the employee nodes:

map:build(//employee, fn { @ssn })

The following expression creates a map whose keys are employee @location values, and whose corresponding values represent the number of employees at each distinct location. Any employees that lack an @location attribute will be excluded from the result.

map:build(//employee, fn { @location }, fn { 1 }, { "duplicates": op("+") })

The following expression creates a map whose keys are employee @location values, and whose corresponding values contain the employee node for the highest-paid employee at each distinct location:

map:build(
  //employee,
  keys := fn { @location }, 
  combine := fn($a, $b) { highest(($a, $b), fn { xs:decimal(@salary) }) }
)

The following expression creates a map allowing efficient access to every element in a document by means of its fn:generate-id value:

map:build(//*, generate-id#1)