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


20 Processing JNodes

Changes in 4.0  

  1. Introduced the concept of JNodes.   [Issue 2025 PR 2031 11 June 2025]

A JNodeDM is a wrapper around a map or array, or around a value that appears within the content of a map or array. JNodes are described at Section 8.4 JNodesDM. Wrapping a map or array in a JNode enables the use of path expressions such as $jnode/descendant::title, as described at Section 4.6 Path ExpressionsXP.

In addition to the functions defined in this section, functions that operate on JNodes include:

fn:distinct-ordered-nodes
fn:generate-id
fn:root
fn:siblings
fn:transitive-closure

20.1 Functions on JNodes

20.1.2 fn:jnode-content

Summary

Returns the ·content· property of a JNode.

Signature
fn:jnode-content(
$inputas jnode-type()?:= .
) as item()*
Properties

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

Rules

If the argument is omitted, it defaults to the context value (.).

If $input is an empty sequence, the function returns an empty sequence.

Otherwise, the function returns the ·content· property of $input.

Error Conditions

The following errors may be raised when $node is omitted:

  • If the context value is absentDM, type error [err:XPDY0002]XP.

  • If the context value is not an instance of the sequence type jnode-type()?, type error [err:XPTY0004]XP.

Notes

In many cases it is unnecessary to make an explicit call on jnode-content, because the coercion rules will take care of this automatically. For example, in an expression such as $X / descendant::name [matches(., '^J')], the call on matches is supplied with a JNode as its first argument; atomization ensures that the actual value being passed to the first argument of matches is the atomized value of the ·content· property.

One case where the function call may be needed is when computing the effective boolean value. As with XNodes, writing if ($array/child::*[1]) ... tests for the existence of a child, it does not test its value. To test its value, write if (jnode-content($array/child::*[1])) ..., or equivalently if (xs:boolean($array/child::*[1])) ....

Examples
Expression:
let $array := [1, 3, 4.5, 7, "eight", 10]
return $array / child::type(xs:integer) =!> jnode-content()
Result:
1, 3, 7, 10
Expression:
let $map := {'Mo': 'Monday', 'Tu': 'Tuesday', 'We': 'Wednesday'}
return $map / child::get("Mo", "We", "Fr", "Su") =!> jnode-content()
Result:
"Monday", "Wednesday"
Expression:
let $array := [[4, 18], [30, 4, 22]]
return $array / descendant::*[. gt 25][1] / ancestor-or-self::* =!> jnode-content() => reverse()
Result:
[[4, 18], [30, 4, 22]], [30, 4, 22], 30

20.1.3 fn:jnode-selector

Changes in 4.0  

  1. New in 4.0  [Issue 2025 PR 2031 12 June 2025]

Summary

Returns the ·selector· property of a JNode.

Signature
fn:jnode-selector(
$inputas jnode-type()?:= .
) as xs:anyAtomicType?
Properties

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

Rules

If the argument is omitted, it defaults to the context value (.).

If $input is an empty sequence, the function returns an empty sequence.

If $input is a root JNode (one in which the ·selector· property is absent), the function returns an empty sequence.

Otherwise, the function returns the ·selector· property of $input. In the case where the parent JNode wraps a map, this will be the key of the relevant entry within that map; in the case where the parent JNode wraps an array, it will be the 1-based index of the relevant member of the array.

Error Conditions

The following errors may be raised when $node is omitted:

  • If the context value is absentDM, type error [err:XPDY0002]XP.

  • If the context value is not an instance of the sequence type jnode-type()?, type error [err:XPTY0004]XP.

Examples
Expression:
let $array := [1, 3, 4.5, 7, "eight", 10]
return $array / child::type(xs:integer) =!> jnode-selector()
Result:
1, 2, 4, 6
Expression:
let $map := {'Mo': 'Monday', 'Tu': 'Tuesday', 'We': 'Wednesday'}
return $map / child::("Mo", "We", "Fr", "Su") =!> jnode-selector()
Result:
"Mo", "We"
Expression:
let $array := [[4, 18], [30, 4, 22]]
return $array / descendant::*[. gt 25][1] / ancestor::* =!> jnode-selector() => reverse()
Result:
2, 1

20.1.4 fn:jnode-position

Changes in 4.0  

  1. New in 4.0  [Issue 2025 PR 2031 12 June 2025]

Summary

Returns the ·position· property of a JNode.

Signature
fn:jnode-position(
$inputas jnode-type()?:= .
) as xs:anyAtomicType?
Properties

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

Rules

If the argument is omitted, it defaults to the context value (.).

If $input is an empty sequence, the function returns an empty sequence.

If $input is a root JNode (one in which the ·position· property is absent), the function returns an empty sequence.

Otherwise, the function returns the ·position· property of $input. The value of this property will be 1 (one) except in cases where the value of an entry in a map, or a member in an array, is a sequence that contains multiple items including maps and/or arrays; in such cases the position will be the 1-based position of the relevant map or array.

Error Conditions

The following errors may be raised when $node is omitted:

  • If the context value is absentDM, type error [err:XPDY0002]XP.

  • If the context value is not an instance of the sequence type jnode-type()?, type error [err:XPTY0004]XP.

Notes

This function is relevant only when there are maps whose entries are multi-item sequences that include maps and arrays, or arrays whose members include such multi-item sequences. Such structures are uncommon, and never arise from parsing of JSON source text. It is generally best to avoid such structures by using arrays rather than sequences within array and map content; apart from other considerations, this allows the data to be serialized in JSON format.

If an entry within a map, or a member of an array, contains a sequence of items that mixes arrays and maps with other content (for example the array [1, 2, ([1,2], [3,4], 5)), then a lookup using the child axis will only construct JNodes in respect of those items that are non-empty maps or arrays. This may leave gaps in the position numbering sequence, as illustrated in the examples below.

Examples
Expression:
let $input := {
   "a": [10, 20, 30], 
   "b": ([40, 50, 60], [], 0, [70, 80, (90, 100)])
}
return $input / child::b / * 
       ! { "position": jnode-position(.),
           "index": jnode-selector(.)
           "value": jnode-content(.)
         }
let $input := {
   "a": [10, 20, 30], 
   "b": ([40, 50, 60], [], 0, [70, 80, (90, 100)])
}
return $input / child::b / * 
       ! { "position": jnode-position(),
           "index": jnode-selector()
           "value": jnode-content()
         }
Result:
{ "position": 1, "index": 1, "value": 40 },
{ "position": 1, "index": 2, "value": 50 },
{ "position": 1, "index": 3, "value": 60 },
{ "position": 4, "index": 1, "value": 70 },
{ "position": 4, "index": 2, "value": 80 },
{ "position": 4, "index": 3, "value": (90, 100) }
Expression:
let $input := {
   "a": {"x": 10, "y": 20, "z": 30}, 
   "b": ( {"x": 40, "y": 50, "z": 60},
          {},
          {"x": 70, "y": 80, "z": (90, 100)})
}
return $input / child::b / * 
       ! { "position": jnode-position(.),
           "key": jnode-selector(.)
           "value": jnode-content(.)
         }
let $input := {
   "a": {"x": 10, "y": 20, "z": 30}, 
   "b": ( {"x": 40, "y": 50, "z": 60},
          {},
          {"x": 70, "y": 80, "z": (90, 100)})
}
return $input / child::b / * 
       ! { "position": jnode-position(),
           "key": jnode-selector()
           "value": jnode-content()
         }
Result:
{ "position": 1, "key": "x", "value": 40 },
{ "position": 1, "key": "y", "value": 50 },
{ "position": 1, "key": "z", "value": 60 },
{ "position": 3, "key": "x", "value": 70 },
{ "position": 3, "key": "y", "value": 80 },
{ "position": 3, "key": "z", "value": (90, 100) }