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.
Copyright © 2000 W3C® (MIT, ERCIM, Keio, Beihang). W3C liability, trademark and document use rules apply.
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.
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.
The publications of this community group are dedicated to our co-chair, Michael Sperberg-McQueen (1954–2024).
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-nodesfn:generate-idfn:rootfn:siblingsfn:transitive-closure
Returns the ·content· property of a JNode.
fn:jnode-content( | ||
$input | as | := . |
) as | ||
This function is deterministic, context-independent, and focus-independent.
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.
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.
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])) ....
| 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 |
Returns the ·selector· property of a JNode.
fn:jnode-selector( | ||
$input | as | := . |
) as | ||
This function is deterministic, context-independent, and focus-independent.
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.
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.
| 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 |
Returns the ·position· property of a JNode.
fn:jnode-position( | ||
$input | as | := . |
) as | ||
This function is deterministic, context-independent, and focus-independent.
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.
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.
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.
| 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) } |