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

XML Path Language (XPath) 4.0 WG Review Draft

W3C Editor's Draft 30 January2 February 2026

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

This document is also available in these non-normative formats: XML.


Abstract

XPath 4.0 is an expression language that allows the processing of values conforming to the data model defined in [XDM 4.0]. The name of the language derives from its most distinctive feature, the path expression, which provides a means of hierarchic addressing of the nodes in an XML tree. As well as modeling the tree structure of XML, the data model also includes atomic items, function items, maps, arrays, and sequences. This version of XPath supports JSON as well as XML, and adds many new functions in [Functions and Operators 4.0].

XPath 4.0 is a superset of XPath 3.1. A detailed list of changes made since XPath 3.1 can be found in I Change Log.

Status of this Document

This section describes the status of this document at the time of its publication. Other documents may supersede this document.

This document is a working draft developed and maintained by a W3C Community Group, the XQuery and XSLT Extensions Community Group unofficially known as QT4CG (where "QT" denotes Query and Transformation). This draft is work in progress and should not be considered either stable or complete. Standard W3C copyright and patent conditions apply.

The community group welcomes comments on the specification. Comments are best submitted as issues on the group's GitHub repository.

As the Community Group moves towards publishing dated, stable drafts, some features that the group thinks may likely be removed or substantially changed are marked “at risk” in their changes section. In this draft:

The community group maintains two extensive test suites, one oriented to XQuery and XPath, the other to XSLT. These can be found at qt4tests and xslt40-test respectively. New tests, or suggestions for correcting existing tests, are welcome. The test suites include extensive metadata describing the conditions for applicability of each test case as well as the expected results. They do not include any test drivers for executing the tests: each implementation is expected to provide its own test driver.

Dedication

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

Michael was central to the development of XML and many related technologies. He brought a polymathic breadth of knowledge and experience to everything he did. This, combined with his indefatigable curiosity and appetite for learning, made him an invaluable contributor to our project, along with many others. We have lost a brilliant thinker, a patient teacher, and a loyal friend.


2 Basics

2.1 Terminology

Changes in 4.0 (next | previous)

  1. The EBNF operators ++ and ** have been introduced, for more concise representation of sequences using a character such as "," as a separator. The notation is borrowed from Invisible XML.  [Issue 1366 PR 1498]

The basic building block of XPath 4.0 is the expression, which is a string of [Unicode] characters; the version of Unicode to be used is implementation-defined. The language provides several kinds of expressions which may be constructed from keywords, symbols, and operands. In general, the operands of an expression are other expressions. XPath 4.0 allows expressions to be nested with full generality.

Note:

This specification contains no assumptions or requirements regarding the character set encoding of strings of [Unicode] characters.

Like XML, XPath 4.0 is a case-sensitive language. Keywords in XPath 4.0 use lower-case characters and are not reserved—that is, names in XPath 4.0 expressions are allowed to be the same as language keywords, except for certain unprefixed function-names listed in A.4 Reserved Function Names.

In this specification the phrases must, must not, should, should not, may, required, and recommended, when used in normative text and rendered in small capitals, are to be interpreted as described in [RFC2119].

Certain aspects of language processing are described in this specification as implementation-defined or implementation-dependent.

  • [Definition: Implementation-defined indicates an aspect that may differ between implementations, but must be specified by the implementer for each particular implementation.]

  • [Definition: Implementation-dependent indicates an aspect that may differ between implementations, is not specified by this or any W3C specification, and is not required to be specified by the implementer for any particular implementation.]

A language aspect described in this specification as implementation-defined or implementation dependent may be further constrained by the specifications of a host language in which XPath is embedded.

2.1.3 Values

Changes in 4.0 (next | previous)

  1. The term atomic value has been replaced by atomic item.   [Issue 1337 PR 1361 2 August 2024]

  2. The terms XNode and JNode are introduced; the existing term node remains in use as a synonym for XNode where the context does not specify otherwise.   [Issue 2025 PR 2031 13 June 2025]

[Definition: In the data model, a value is always a sequence.]

[Definition: A sequence is an ordered collection of zero or more items.]

[Definition: An item is either an atomic item, a node, or a function item.]

[Definition: An atomic item is a value in the value space of an atomic type, as defined in [XML Schema 1.0] or [XML Schema 1.1].]

[Definition: An XNode is an instance of one of the node kinds defined in [XDM 4.0] section 7.1 XML Nodes.] Each XNode has a unique node identity, a typed value, and a string value. In addition, some XNodes have a name. The typed value of an XNode is a sequence of zero or more atomic items. The string value of an XNode is a value of type xs:string. The name of an XNode is a value of type xs:QName.

[Definition: Except where the context indicates otherwise, the term node is used as a synonym for XNode.]

[Definition: A JNode (see also [XDM 4.0] section 8.4 JNodes) is an encapsulation of a value as it appears within a tree of maps and arrays, typically (but not necessarily) obtained by parsing JSON texts.]

[Definition: A GNode (for generalized node) is either an XNode or a JNode.]

[Definition: A function item is an item that can be called using a dynamic function call.]

Maps (see 4.14.1 Maps) and arrays (see 4.14.2 Arrays) are specific kinds of function items.

[Definition: A sequence containing exactly one item is called a singleton.] An item is identical to a singleton sequence containing that item. Sequences are never nested—for example, combining the values 1, (2, 3), and ( ) into a single sequence results in the sequence (1, 2, 3). [Definition: AThe sequence containing zero items is called anthe empty sequence.]

[Definition: The term XDM instance is used, synonymously with the term value, to denote an unconstrained sequence of items.]

2.3 External Resources and Security

Changes in 4.0 (next | previous)

  1. This section (“External Resources and Security”) is new.  [Issue 2047 PR 2213 23 October 2025]

The XPath, XQuery, and XSLT languages provide a number of capabilities to access external resources. These include:

  • Functions such as doc, doc-available, unparsed-text, unparsed-text-lines, unparsed-text-available, collectionuri-collection, and unparsed-binary, and in XSLT, the document function and the xsl:source-document and xsl:merge instructions.

  • Static inclusion of code using import module in XQuery, or xsl:include, xsl:import, and xsl:use-package in XSLT.

  • Dynamic inclusion and execution of external code using the functions transform and load-xquery-module, and in XSLT, the xsl:evaluate instruction.

  • The ability to write to external resources using the xsl:result-document instruction in XSLT, or the put function in the XQuery Update Facility.

  • The ability to invoke arbitrary user-defined external functions (called extension functions in XSLT).

  • The ability to invoke vendor-defined external/extension functions; a notable example being the EXPath File library.

  • Access to environment variables and system properties using functions such as environment-variable, available-environment-variables, and (in XSLT) system-property.

  • Static inclusion of XSD schemas and schema documents using import schemain XQuery or xsl:import-schema in XSLT, or indirectly using xs:import, xs:include, xs:redefine, or xs:override in XSD schema documents.

  • Dynamic loading of XSD schema documents (directly or indirectly) using the xsd-validator function.

  • The ability to parse XML or HTML documents that contain references to external entities, for example by using the parse-xml and parse-html functions.

  • The ability to parse XML documents in a way that causes other external resources to be fetched, for example by activating XInclude, or by performing XSD validation using xsi:schema-location.

  • Implicit access to third-party libraries supporting (for example) collations or localization.

External resources are always referenced by means of a URI. The way in which a URI is dereferenced to obtain a resource is implementation defined. It is recommended that popular URI schemes such as http, https, and file should be supported, but this may be subject to user configuration and security constraints. Implementations are free to support indirection mechanisms such as catalogs and resolver callbacks, as well as supporting additional URI schemes and protocols, whether standardized or not.

[Definition: The static context includes a boolean property called trusted that determines whether external resources are available.] This may take the following values:

  1. false: No external resources are available other than resources explicitly made available by the caller through some trusted implementation-defined mechanism.

    [Definition: ]Code executing with trusted set to false is said to be untrusted.

  2. true: Trusted code has access to all the resources available to its immediate caller.

The functions transform and load-xquery-module, and the XSLT instruction xsl:evaluate, have an option allowing the trust level of the executed code to be set:

  1. If trusted is set to true, the invoked code executes with the same trust level as its caller.

  2. If trusted is set to false, the invoked code is not able to access any external resources other than resources explicitly made available using an implementation defined mechanism under the control of the caller.

Some resources, such as XML documents, may themselves contain references to other resources. For example, an XML document may reference external entities (including an external DTD). External entity expansion is recognized as a known security risk. Functions that invoke XML parsing (such as parse-xml, doc, or collection) therefore have a trusted option indicating whether the document being parsed is trusted to access external entities. Such access is allowed only if (a) the trusted option is set to true, or (b) access to the external entity in question is explicitly enabled by the caller.

Note:

The term explicitly enabled is not intended to mean that every resource to which access is permitted must be individually listed. The mechanism for enabling access might provide access to a class of resources (for example, all resources accessible using the HTTPS protocol, or all resources within the containing XML database having particular access permissions). The mechanism might also take account of other criteria, for example it might impose limits on the size or other characteristics of the resources accessed.

It is recommended that any external API used to invoke XPath, XQuery, or XSLT processing should similarly offer the ability to indicate whether the code being executed is trusted.

In the interests of security, the default for these options is false. However, for backwards compatibility reasons, processors may provide an option whereby a trusted user can change the default.

In general, when an application requests access to an external resource which is not available because the application is untrusted, the processor should behave in the same way as if the resource did not exist. However, the processor may choose to disclose in its diagnostics why the request was unsuccessful.

A processor may (but is not required to) limit an application’s consumption of resources such as CPU cycles and memory when the application is untrusted.

[Definition: The term available documents refers (TODO: for the time being) to the set of XML documents that an application is able to access by URI.]

2.4 Processing Model

Changes in 4.0 (next | previous)

  1. The static typing option has been dropped.   [Issue 1343 PR 1344 3 September 2024]

The semantics of XPath 4.0 are defined in terms of the data model and the expression context.

Processing_ModelclusterQT4XPath Expression ProcessingclusterEPExternal processingExecExecutionEngineXDMXPath DataModelExec->XDM DQ4SerializeSerializeXDM->Serialize DM4ASTAbstractSyntax TreeAST->Exec DQ1AST->AST SQ5StaticStaticContextStatic->AST SQ4DynamicDynamicContextStatic->Dynamic DQ2Dynamic->Exec DQ5SchemaIn-ScopeSchemaDefinitionsSchema->StaticXPathXPathXPath->AST SQ1XMLXMLPSVIInfoset/PSVIXML->PSVI DM1JSONJSONJSON->XDM DM2PSVI->XDM DM2DirectOther/DirectGenerationDirect->XDM DM3XSDXMLSchemaXSD->Schema SI1DirectXSDOther/DirectGenerationDirectXSD->Schema SI2HostHostEnvironmentHost->Static SQ2Host->Dynamic DQ3

Figure 1: Processing Model Overview

Figure 1 provides a schematic overview of the processing steps that are discussed in detail below. Some of these steps are completely outside the domain of XPath 4.0; in Figure 1, these are depicted outside the line that represents the boundaries of the language, an area labeled external processing. The external processing domain includes generation of XDM instances that represent the data to be queried (see 2.4.1 Data Model Generation), schema import processing (see 2.4.2 Schema Import Processing), and serialization. The area inside the boundaries of the language is known as the XPath processing domain, which includes the static analysis and dynamic evaluation phases (see 2.4.3 Expression Processing). Consistency constraints on the XPath processing domain are defined in 2.4.6 Consistency Constraints.

2.4.3 Expression Processing

XPath 4.0 defines two phases of processing called the static analysis phase and the dynamic evaluation phase (see Figure 1). During the static analysis phase, static errors, dynamic errors, or type errors may be raised. During the dynamic evaluation phase, only dynamic errors or type errors may be raised. These kinds of errors are defined in 2.5.1 Kinds of Errors.

Within each phase, an implementation is free to use any strategy or algorithm whose result conforms to the specifications in this document.

2.4.3.1 Static Analysis Phase

[Definition: The static analysis phase depends on the expression itself and on the static context. The static analysis phase does not depend on input data (other than schemas).]

During the static analysis phase, the XPath expression is typically parsed into an internal representation called the operation tree (step SQ1 in Figure 1). A parse error is raised as a static error [err:XPST0003]. The static context is initialized by the implementation (step SQ2). The static context is used to resolve schema type names, function names, namespace prefixes, and variable names (step SQ4). If a name of one of these kinds in the operation tree is not found in the static context, a static error ([err:XPST0008] or [err:XPST0017]) is raised (however, see exceptions to this rule in 3.2.7.2 Element Types and 3.2.7.3 Attribute Types.)

The operation tree is then typically normalized by making explicit the implicit operations such as atomization and extraction of effective boolean values (step SQ5).

During the static analysis phase, a processor may perform type analysis. The effect of type analysis is to assign a static type to each expression in the operation tree. [Definition: The static type of an expression is the best inference that the processor is able to make statically about the type of the result of the expression.] This specification does not define the rules for type analysis nor the static types that are assigned to particular expressions: the only constraint is that the inferred type must match all possible values that the expression is capable of returning.

Examples of inferred static types might be:

  • For the expression concat(a,b) the inferred static type is xs:string

  • For the expression $a = $v the inferred static type is xs:boolean

  • For the expression $s[exp] the inferred static type has the same item type as the static type of $s, but a cardinality that allows the empty sequence even if the static type of $s does not allow anthe empty sequence.

  • The inferred static type of the expression data($x) (whether written explicitly or inserted into the operation tree in places where atomization is implicit) depends on the inferred static type of $x: for example, if $x has type element(*, xs:integer) then data($x) has static type xs:integer.

In XQuery 1.0 and XPath 2.0, rules for static type inferencing were published normatively in [XQuery 1.0 and XPath 2.0 Formal Semantics], but implementations were allowed to refine these rules to infer a more precise type where possible. In subsequent versions, the rules for static type inferencing are entirely implementation-dependent.

Every kind of expression also imposes requirements on the type of its operands. For example, with the expression substring($a, $b, $c), $a must be of type xs:string (or something that can be converted to xs:string by the function calling rules), while $b and $c must be numeric.

A processor may raise a type error during static analysis if the inferred static type of an expression has no overlap (intersection) with the required type, and cannot be converted to the required type using the coercion rules. For example, given the call fn:upper-case($s), the processor may raise an error if the declared or inferred type of $s is xs:integer, but not if it is xs:anyAtomicType.

In addition, type analysis may conclude that an expression is implausible. Implausible expressions may be considered erroneous unless such checks have been disabled. For example, the expression round(tokenize($input)) is implausible because the required type for fn:round is xs:numeric?, while the static type of tokenize($input) is xs:string*, and these two sequence types are substantively disjoint. This topic is described further in 2.5.6 Implausible Expressions.

Alternatively, the processor may defer all type checking until the dynamic evaluation phase.

2.5 Error Handling

2.5.4 Errors and Optimization

Because different implementations may choose to evaluate or optimize an expression in different ways, certain aspects of raising dynamic errors are implementation-dependent, as described in this section.

An implementation is always free to evaluate the operands of an operator in any order.

In some cases, a processor can determine the result of an expression without accessing all the data that would be implied by the formal expression semantics. For example, the formal description of filter expressions suggests that $s[1] should be evaluated by examining all the items in sequence $s, and selecting all those that satisfy the predicate position()=1. In practice, many implementations will recognize that they can evaluate this expression by taking the first item in the sequence and then exiting. If $s is defined by an expression such as //book[author eq 'Berners-Lee'], then this strategy may avoid a complete scan of a large document and may therefore greatly improve performance. However, a consequence of this strategy is that a dynamic error or type error that would be detected if the expression semantics were followed literally might not be detected at all if the evaluation exits early. In this example, such an error might occur if there is a book element in the input data with more than one author subelement.

The extent to which a processor may optimize its access to data, at the cost of not raising errors, is defined by the following rules.

Consider an expression Q that has an operand (sub-expression) E. In general the value of E is a sequence. At an intermediate stage during evaluation of the sequence, some of its items will be known and others will be unknown. If, at such an intermediate stage of evaluation, a processor is able to establish that there are only two possible outcomes of evaluating Q, namely the value V or an error, then the processor may deliver the result V without evaluating further items in the operand E. For this purpose, two values are considered to represent the same outcome if their items are pairwise the same, where nodes are the same if they have the same identity, and values are the same if they are equal and have exactly the same type.

There is an exception to this rule: If a processor evaluates an operand E (wholly or in part), then it is required to establish that the actual value of the operand E does not violate any constraints on its cardinality. For example, the expression $e eq 0 results in a type error if the value of $e contains two or more items. A processor is not allowed to decide, after evaluating the first item in the value of $e and finding it equal to zero, that the only possible outcomes are the value true or a type error caused by the cardinality violation. It must establish that the value of $e contains no more than one item.

These rules apply to all the operands of an expression considered in combination: thus if an expression has two operands E1 and E2, it may be evaluated using any samples of the respective sequences that satisfy the above rules.

The rules cascade: if A is an operand of B and B is an operand of C, then the processor needs to evaluate only a sufficient sample of B to determine the value of C, and needs to evaluate only a sufficient sample of A to determine this sample of B.

The effect of these rules is that the processor is free to stop examining further items in a sequence as soon as it can establish that further items would not affect the result except possibly by causing an error. For example, the processor may return true as the result of the expression S1 = S2 as soon as it finds a pair of equal values from the two sequences.

Another consequence of these rules is that where none of the items in a sequence contributes to the result of an expression, the processor is not obliged to evaluate any part of the sequence. Again, however, the processor cannot dispense with a required cardinality check: if anthe empty sequence is not permitted in the relevant context, then the processor must ensure that the operand is not anthe empty sequence.

Examples:

  • If an implementation can find (for example, by using an index) that at least one item returned by $expr1 in the following example has the value 47, it is allowed to return true as the result of the some expression, without searching for another item returned by $expr1 that would raise an error if it were evaluated.

    some $x in $expr1 satisfies $x = 47
  • In the following example, if an implementation can find (for example, by using an index) the product element-nodes that have an id child with the value 47, it is allowed to return these nodes as the result of the path expression, without searching for another product node that would raise an error because it has an id child whose value is not an integer.

    //product[id = 47]

For a variety of reasons, including optimization, implementations may rewrite expressions into a different form. There are a number of rules that limit the extent of this freedom:

  • Other than the raising or not raising of errors, the result of evaluating a rewritten expression must conform to the semantics defined in this specification for the original expression.

    Note:

    This allows an implementation to return a result in cases where the original expression would have raised an error, or to raise an error in cases where the original expression would have returned a result. The main cases where this is likely to arise in practice are (a) where a rewrite changes the order of evaluation, such that a subexpression causing an error is evaluated when the expression is written one way and is not evaluated when the expression is written a different way, and (b) where intermediate results of the evaluation cause overflow or other out-of-range conditions.

    Note:

    This rule does not mean that the result of the expression will always be the same in non-error cases as if it had not been rewritten, because there are many cases where the result of an expression is to some degree implementation-dependent or implementation-defined.

  • The rules described in 2.5.5 Guarded Expressions ensure that for certain kinds of expression (for example conditional expressions), changing the order of evaluation of subexpressions does not result in dynamic errors that would not otherwise occur.

  • Expressions must not be rewritten in such a way as to create or remove static errors. The static errors in this specification are defined for the original expression, and must be preserved if the expression is rewritten.

  • As stated earlier, an expression must not be rewritten to dispense with a required cardinality check: for example, string-length(//title) must raise an error if the document contains more than one title element.

2.5.5 Guarded Expressions

Changes in 4.0 (next | previous)

  1. The rules for “errors and optimization” have been tightened up to disallow many cases of optimizations that alter error behavior. In particular there are restrictions on reordering the operands of and and or, and of predicates in filter expressions, in a way that might allow the processor to raise dynamic errors that the author intended to prevent.   [Issue 71 PR 230 15 November 2022]

[Definition: An expression E is said to be guarded by some governing condition C if evaluation of E is not allowed to fail with a dynamic error except when C applies.]

For example, in a conditional expression if (P) then T else F, the subexpression T is guarded by P, and the subexpression F is guarded by not(P). One way an implementation can satisfy this rule is by not evaluating T unless P is true, and likewise not evaluating F unless P is false. Another way of satisfying the rule is for the implementation to evaluate all the subexpressions, but to catch any errors that occur in a guarded subexpression so they are not propagated.

The existence of this rule enables errors to be prevented by writing expressions such as if ($y eq 0) then "N/A" else ($x div $y). This example will never fail with a divide-by-zero error because the else branch of the conditional is guarded.

Similarly, in the mapping expression E1!E2, the subexpression E2 is guarded by the existence of an item from E1. This means, for example, that the expression (1 to $n)!doc('bad.xml') must not raise a dynamic error if $n is zero. The rule governing evaluation of guarded expressions is phrased so as not to disallow “loop-lifting” or “constant-folding” optimizations whose aim is to avoid repeated evaluation of a common subexpression; but such optimizations must not result in errors that would not otherwise occur.

The complete list of expressions that have guarded subexpressions is as follows:

  • In a conditional expression (IfExpr) the then branch is guarded by the condition being true, and the else branch is guarded by the condition being false.

  • In an and expression, the second operand is guarded by the value of the first operand being true.

  • In an or expression, the second operand is guarded by the value of the first operand being false.

  • In an otherwise expression (OtherwiseExpr), the second operand is guarded by the value of the first operand being anthe empty sequence.

  • In a path expression of the form E1/E2 or E1//E2, and in a mapping expression of the form E1!E2, the right-hand operand E2 is guarded by the existence of at least one item in the result of evaluating E1.

    This rule applies even if E2 does not reference the context value. For example, no dynamic error can be thrown by the expression (1 to $n)!doc('bad.xml') in the case where $n is zero.

  • In a filter expression of the form E[P], the predicate P is guarded by the existence of at least one item in the result of evaluating E.

    This rule has the consequence that in a filter expression with multiple predicates, such as E[P1][P2], evaluation of P2 must not raise a dynamic error unless P1 returns true. This rule does not prevent reordering of predicates (for example, to take advantage of indexes), but it does require that any such reordering must not result in errors that would not otherwise occur.

  • In a for expression (ForExpr) such as for $x in S return E, the expression E is guarded by the existence of an item bound to $x.

    This means that the expression for $x in 1 to $n return doc('bad.xml') must not raise a dynamic error in the case where $n is zero.

  • In a quantified expression (QuantifiedExpr) such as some $x in S satisfies P, the expression P is guarded by the existence of an item bound to $x.

The fact that an expression is guarded does not remove the obligation to report static errors in the expression; nor does it remove the option to report statically detectable type errors.

Note:

These rules do not constrain the order of evaluation of subexpressions. For example, given an expression such as //person[@first = "Winston"][@last = "Churchill"], or equivalently //person[@first = "Winston" and @last = "Churchill"], an implementation might use an index on the value of @last to select items that satisfy the second condition, and then filter these items on the value of the first condition. Alternatively, it might evaluate both predicates in parallel. Or it might interpose an additional redundant condition: //person[string-length(@first) + string-length(@last) = 16][@first = "Winston"][@last = "Churchill"]. But implementations must ensure that such rewrites do not result in dynamic errors being reported that would not occur if the predicates were evaluated in order as written.

Note:

Although the rules for guarded expressions prevent optimizations resulting in spurious errors, they do not prevent optimizations whose effect is to mask errors. For example, the rules guarantee that ("A", 3)[. instance of xs:integer][. eq 3] will not raise an error caused by the comparison ("A" eq 3), but they do not guarantee the converse: the expression ("A", 3)[. eq 3][. instance of xs:integer] may or may not raise a dynamic error.

Note:

The rules in this section do not disallow all expression rewrites that might result in dynamic errors. For example, rewriting ($x - $y + $z) as ($x + $z - $y) is permitted even though it might result in an arithmetic overflow.

Note:

Some implementations allow calls on external functions that have side-effects. The semantics of such function calls are entirely implementation defined. Processors may choose to reference the rules for guarded expressions when defining the behavior of such function calls, but this is outside the scope of the language specification.

2.5.6 Implausible Expressions

Changes in 4.0 (next | previous)

  1. The rules for reporting type errors during static analysis have been changed so that a processor has more freedom to report errors in respect of constructs that are evidently wrong, such as @price/@value, even though dynamic evaluation is defined to return anthe empty sequence rather than an error.   [Issue 602 PR 603 25 July 2023]

[Definition: Certain expressions, while not erroneous, are classified as being implausible, because they achieve no useful effect.]

An example of an implausible expression is @code/text(). This expression will always evaluate to anthe empty sequence, because attribute nodes cannot have text node children. The semantics of the expression are well defined, but it is likely that the user writing this expression intended something different: if they wanted to write an expression that evaluated to anthe empty sequence, there would be easier ways to write it.

Where an expression is classified (by rules in this specification) as being implausible, a processor may (but is not required to) raise a static error.

For reasons of backwards compatibility and interoperability, and to facilitate automatic generation of XPath 4.0 code, a processor must provide a mode of operation in which implausible expressions are not treated as static errors, but are evaluated with the defined semantics for the expression.

Some other examples of implausible expressions include:

  • round(tokenize($input)). The result of fn:tokenize is a sequence of strings (xs:string*), while the required type for the first argument of fn:round is optional numeric (xs:numeric?). The expression can succeed only in the exceptional case where the result of fn:tokenize is anthe empty sequence, in which case the result of fn:round will also be anthe empty sequence; it is therefore highly likely that the expression was written in error.

  • parse-csv($input)?column-names. The signature of the parse-csv function declares its return type as record(columns, rows). There is no field in this record named column-names, and therefore the lookup expression will always return anthe empty sequence. Again, there is no good reason that a user would write this, so it is likely that it was written in error.

Note:

The specification is deliberately conservative in the choice of constructs that have been classified as implausible. Constructs have not been classified as implausible merely because there are better ways of writing the same thing, but only in cases where it is considered that no user in full understanding of the specification would intentionally write such a construct. All these cases correspond to situations that would be classed as errors in a language with stricter static typing rules.

Note:

In many cases the classification of constructs as implausible is designed to protect users from usability problems that have been found with earlier versions of the language. without introducing backwards incompatibilities.

2.6 Concepts

This section explains some concepts that are important to the processing of XPath 4.0 expressions.

2.6.1 Document Order

An ordering called document order is defined among all the nodes accessible during processing of a given expression, which may consist of one or more trees (documents or fragments).

Document order applies both to XNodes (typically corresponding to nodes in an XML document, and generally referred to simply as nodes), and also to JNodesDM, often corresponding to the contents of a JSON source text. These are known collectively as GNodes (for "generalized node").

Document order is defined in [XDM 4.0] section 6.2 Document Order, and its definition is repeated here for convenience. Document order is a total ordering, although the relative order of some nodes is implementation-dependent. [Definition: Informally, document order is the order in which nodes appear in the XML serialization of a document.] [Definition: Document order is stable, which means that the relative order of two nodes will not change during the processing of a given expression, even if this order is implementation-dependent.] [Definition: The node ordering that is the reverse of document order is called reverse document order.]

Within an XTreeDM, (that is, a tree consisting of XNodes), document order satisfies the following constraints:

  1. The root node precedes all other nodes.

  2. A parent node precedes its children (and therefore its descendants).

  3. The children of a node N precede the following siblings of N.

  4. Namespace nodes immediately follow the element node with which they are associated. The relative order of namespace nodes is stable but implementation-dependent.

  5. Attribute nodes immediately follow the namespace nodes of the element node with which they are associated. The relative order of attribute nodes is stable but implementation-dependent.

  6. The relative order of siblings is the order in which they occur in the children property of their parent node.

Similarly, within an JTreeDM, (that is, a tree consisting of JNodes), document order satisfies the following constraints:

  1. The root JNode precedes all other JNodes.

  2. A parent JNode precedes its children (and therefore its descendants).

  3. The children of a JNode N precede the following siblings of N.

  4. The children of a JNode that wraps an array follow the ordering of the members of the array.

  5. The children of a JNode that wraps a map follow the ordering of the entries in the map.

The relative order of nodes in distinct trees is stable but implementation-dependent, subject to the following constraint: If any node in a given tree T1 is before any node in a different tree T2, then all nodes in tree T1 are before all nodes in tree T2.

2.6.4 Effective Boolean Value

Under certain circumstances (some of which are listed below), it is necessary to find the effective boolean value of a value. [Definition: The effective boolean value of a value is defined as the result of applying the fn:boolean function to the value.]

The dynamic semantics of fn:boolean are repeated here for convenience:

  1. If its operand is anthe empty sequence, fn:boolean returns false.

  2. If its operand is a sequence whose first item is a GNode, fn:boolean returns true.

  3. If its operand is a singleton value of type xs:boolean or derived from xs:boolean, fn:boolean returns the value of its operand unchanged.

  4. If its operand is a singleton value of type xs:string, xs:anyURI, xs:untypedAtomic, or a type derived from one of these, fn:boolean returns false if the operand value has zero length; otherwise it returns true.

  5. If its operand is a singleton value of any numeric type or derived from a numeric type, fn:boolean returns false if the operand value is NaN or is numerically equal to zero; otherwise it returns true.

  6. In all other cases, fn:boolean raises a type error [err:FORG0006]FO40.

    Note:

    For instance, fn:boolean raises a type error if the operand is a function, a map, or an array.

The effective boolean value of a sequence is computed implicitly during processing of the following types of expressions:

Note:

The definition of effective boolean value is not used when casting a value to the type xs:boolean, for example in a cast expression. It also plays no role in the coercion rules used when passing a value to a function whose signature declares a parameter of type xs:boolean.

3 Types

As noted in 2.1.3 Values, every value in XPath 4.0 is regarded as a sequence of zero, one, or more items. The type system of XPath 4.0, described in this section, classifies the kinds of value that the language can handle, and the operations permitted on different kinds of value.

The type system of XPath 4.0 is related to the type system of [XML Schema 1.0] or [XML Schema 1.1] in two ways:

This chapter of the specification starts by defining sequence types and item types, which describe the range of values that can be bound to variables, used in expressions, or passed to functions. It then describes how these relate to schema types, that is, the simple and complex types defined in an XSD schema.

Note:

In many situations the terms item type and sequence type are used interchangeably to refer either to the type itself, or to the syntactic construct that designates the type: so in the expression $x instance of xs:string*, the construct xs:string* uses the SequenceType syntax to designate a sequence type whose instances are sequences of strings. When more precision is required, the specification is careful to use the terms item type and sequence type to refer to the actual types, while using the production names ItemType and SequenceType to refer to the syntactic designators of these types.

3.1 Sequence Types

[Definition: A sequence type is a type that can be expressed using the SequenceType syntax. Sequence types are used whenever it is necessary to refer to a type in an XPath 4.0 expression. Since all values are sequences, every value matches one or more sequence types.]

Whenever it is necessary to refer to a sequence type in an XPath 4.0 expression, the SequenceType syntax is used.

SequenceType::=("empty-sequence" "(" ")")
| (ItemTypeOccurrenceIndicator?)
ItemType::=RegularItemType | FunctionType | TypeName | ChoiceItemType
OccurrenceIndicator::="?" | "*" | "+"
/* xgc: occurrence-indicators */

[Definition: A sequence type designator is a syntactic construct conforming to the grammar rule SequenceType. A sequence type designator is said to designate a sequence type.]

With the exception of the special type empty-sequence(), a sequence type consists of an item type that constrains the type of each item in the sequence, and a cardinality that constrains the number of items in the sequence. Apart from the item type item(), which permits any kind of item, item types divide into node types (such as element()), generalized atomic types (such as xs:integer) and function types (such as function() as item()*).

The cardinality of a sequence type is represented in the sequence type designator syntax by an OccurrenceIndicator. The occurrence indicators +, *, and ? bind to the last ItemType in the SequenceType, as described in the occurrence-indicators constraint.

3.1.2 Sequence Type Matching

[Definition: SequenceType matching compares a value with an expected sequence type. ] For example, an instance of expression returns true if a given value matches a given sequence type, and false if it does not.

An XPath 4.0 implementation must be able to determine relationships among the types in type annotations in an XDM instance and the types in the in-scope schema definitions (ISSD).

[Definition: The use of a value that has a dynamic type that is a subtype of the expected type is known as subtype substitution.] Subtype substitution does not change the actual type of a value. For example, if an xs:integer value is used where an xs:decimal value is expected, the value retains its type as xs:integer.

The rules for SequenceType matching are given below, with examples (the examples are for purposes of illustration, and do not cover all possible cases).

An OccurrenceIndicator specifies the number of items in a sequence, as follows:

  • ? matches zero or one items

  • * matches zero or more items

  • + matches one or more items

As a consequence of these rules, any sequence type whose OccurrenceIndicator is * or ? matches a value that is anthe empty sequence.

3.2 Item Types

[Definition: An item type is a type that can be expressed using the ItemType syntax, which forms part of the SequenceType syntax. Item types match individual items.]

Note:

While this definition is adequate for the purpose of defining the syntax of XPath 4.0, it ignores the fact that there are also item types that cannot be expressed using XPath 4.0 syntax: specifically, item types that reference an anonymous simple type or complex type defined in a schema. Such types can appear as type annotations on nodes following schema validation.

In most cases, the set of items matched by an item type consists either exclusively of atomic items, exclusively of nodes, or exclusively of function itemsDM. Exceptions include the generic types item(), which matches all items, xs:error, which matches no items, and choice item types, which can match any combination of types.

[Definition: An item type designator is a syntactic construct conforming to the grammar rule ItemType. An item type designator is said to designate an item type.]

Note:

Two item type designators may designate the same item type. For example, element() and element(*) are equivalent, as are attribute(A) and attribute(A, xs:anySimpleType).

Lexical QNames appearing in an item type designator are expanded using the default type namespace rule. Equality of QNames is defined by the eq operator.

ItemType::=RegularItemType | FunctionType | TypeName | ChoiceItemType
RegularItemType::=AnyItemTest | NodeKindTest | GNodeType | JNodeType | MapType | ArrayType | RecordType | EnumerationType
AnyItemTest::="item" "(" ")"
NodeKindTest::=DocumentTest
| ElementTest
| AttributeTest
| SchemaElementTest
| SchemaAttributeTest
| PITest
| CommentTest
| TextTest
| NamespaceNodeTest
| AnyNodeKindTest
DocumentTest::="document-node" "(" (ElementTest | SchemaElementTest | NameTestUnion)? ")"
ElementTest::="element" "(" (NameTestUnion ("," TypeName "?"?)?)? ")"
SchemaElementTest::="schema-element" "(" ElementName ")"
NameTestUnion::=(NameTest ++ "|")
NameTest::=EQName | Wildcard
AttributeTest::="attribute" "(" (NameTestUnion ("," TypeName)?)? ")"
SchemaAttributeTest::="schema-attribute" "(" AttributeName ")"
PITest::="processing-instruction" "(" (NCName | StringLiteral)? ")"
StringLiteral::=AposStringLiteral | QuotStringLiteral
/* ws: explicit */
CommentTest::="comment" "(" ")"
TextTest::="text" "(" ")"
NamespaceNodeTest::="namespace-node" "(" ")"
AnyNodeKindTest::="node" "(" ")"
GNodeType::="gnode" "(" ")"
JNodeType::="jnode" "(" (("*" | NCName | Constant) ("," ("*" | SequenceType))?)? ")"
MapType::=AnyMapType | TypedMapType
ArrayType::=AnyArrayType | TypedArrayType
RecordType::=AnyRecordType | TypedRecordType
EnumerationType::="enum" "(" (StringLiteral ++ ",") ")"
FunctionType::=AnyFunctionType
| TypedFunctionType
TypeName::=EQName
EQName::=QName | URIQualifiedName
ChoiceItemType::="(" (ItemType ++ "|") ")"

This section defines the syntax and semantics of different ItemTypes in terms of the values that they match.

Note:

For an explanation of the EBNF grammar notation (and in particular, the operators ++ and **), see A.1 EBNF.

An item type designator written simply as an EQName (that is, a TypeName) is interpreted as follows:

  1. If the name is written as a lexical QName, then it is expanded using the default type namespace rule.

  2. If the expanded name matches a named item type in the static context, then it is taken as a reference to the corresponding item type. The rules that apply are the rules for the expanded item type definition.

  3. Otherwise, it must match the name of a type in the in-scope schema types in the static context: specifically, an atomic type or a pure union type. See 3.5 Schema Types for details.

    Note:

    A name in the xs namespace will always fall into this category, since the namespace is reserved. See 2.1.4 Namespaces and QNames.

  4. If the name cannot be resolved to a type, a static error is raised [err:XPST0051].

3.2.8 Function, Map, and Array Types

The following sections describe the syntax for item types for functions, including arrays and maps.

The subtype relation among these types is described in the various subsections of 3.3.2 Subtypes of Item Types.

3.2.8.2 Map Types

A MapType designates an item type that either matches any map, or that matches maps whose keys and values are constrained to specific types.

MapType::=AnyMapType | TypedMapType
AnyMapType::="map" "(" "*" ")"
TypedMapType::="map" "(" ItemType "," SequenceType ")"
ItemType::=RegularItemType | FunctionType | TypeName | ChoiceItemType
SequenceType::=("empty-sequence" "(" ")")
| (ItemTypeOccurrenceIndicator?)

An AnyMapTypemap(*) matches any map.

The MapTypemap(K, V) matches any map where every key is an instance of K and every value is an instance of V.

The entry-orderDM of a map has no effect on whether the map matches a particular map type.

Although the grammar for TypedMapType allows the key to be described using the full ItemType syntax, the item type used must be a generalized atomic type [err:XPST0152].

For example, given a map $M whose keys are integers and whose results are strings, such as { 0: "no", 1: "yes" }, the following following expressions deliver the result shown:

  • $M instance of map(*) returns true

  • $M instance of map(xs:integer, xs:string) returns true

  • $M instance of map(xs:decimal, xs:anyAtomicType) returns true

  • $M instance of map(xs:int, xs:string) returns false

  • $M instance of map(xs:integer, xs:token)) returns false

A map is also a function item, and therefore matches certain function types. Specifically, a map that matches map(K, V) also matches a function type of the form function(xs:anyAtomicType) as R provided that both the following conditions are satisfied:

Note:

To understand this rule, consider the use of a map $M in a function call $M($K), which is equivalent to the function call map:get($M, $K). This function accepts any atomic item for the argument $K, and hence matches a function type that requires an argument type of xs:anyAtomicType. If the key $K is present in the map, the result of the function will be a value of type V; if not, it will be anthe empty sequence. The map is therefore substitutable for the function type provided that the function type allows both a value of type V and the empty sequence as possible results.

The key type K does not enter into this rule. That is because in the function call $M($K), the sought key $K does not have to be of the same type as the keys actually present in the map.

The transitivity rules for item type matching mean that if an item M matches a type T, and T is a subtype of U, then M also matches type U. So the fact that a map from integers to strings (map(xs:integer, xs:string)) matches function(xs:anyAtomicType) as xs:string? means that it will also match other function types such as function(xs:integer) as xs:string? and function(xs:decimal) as xs:anyAtomicType?

Furthermore, the rules for function coercion mean that any map can be supplied as a value in a context where it does not actually match the required function type, but can be coerced to a function that does. For example a map of type map(xs:integer, xs:string) can be coerced to a function of type function(xs:integer) as xs:string; in this situation a type error will occur only if a call on the function actually returns anthe empty sequence.

Examples:

  • $M instance of fn(*) returns true

  • $M instance of fn(xs:anyAtomicType) as item()* returns true

  • $M instance of fn(xs:integer) as item()* returns true

  • $M instance of fn(xs:int) as item()* returns true

  • $M instance of fn(xs:string) as item()* returns true

  • not($M instance of fn(xs:integer) as xs:string) returns true

Note:

The last case might seem surprising; however, function coercion ensures that $M can be used successfully anywhere that the required type is fn(xs:integer) as xs:string.

Rules defining whether one map type is a subtype of another are given in 3.3.2.7 Subtyping Maps.

3.2.8.3 Record Types

Changes in 4.0 (next | previous)

  1. Record types are added as a new kind of ItemType, constraining the value space of maps.

  2. The syntax record(*) is allowed; it matches any map.   [Issue 52 PR 728 10 October 2023]

  3. The syntax record() is allowed; the only thing it matches is anthe empty map.   [Issue 1491 PR 1577 17 October 2024]

A RecordType matches maps that meet specific criteria.

For example, the RecordTyperecord(r as xs:double, i as xs:double) matches a map if the map has exactly two entries: an entry with key "r" whose value is a singletonxs:double value, and an entry with key "i" whose value is also a singletonxs:double value.

Record types describe a subset of the value space of maps. They do not define any new kinds of values, or any additional operations. They are useful in many cases to describe more accurately the type of a variable, function parameter, or function result, giving benefits both in the readability of the code, and in the ability of the processor to detect and diagnose type errors and to optimize execution.

RecordType::=AnyRecordType | TypedRecordType
AnyRecordType::="record" "(" "*" ")"
TypedRecordType::="record" "(" (FieldDeclaration ** ",") ExtensibleFlag? ")"
FieldDeclaration::=FieldName "?"? ("as" SequenceType)?
FieldName::=NCName | StringLiteral
StringLiteral::=AposStringLiteral | QuotStringLiteral
/* ws: explicit */
SequenceType::=("empty-sequence" "(" ")")
| (ItemTypeOccurrenceIndicator?)
ExtensibleFlag::="," "*"

If the list of fields ends with ",*" then the record type is said to be extensible. For example, the RecordTyperecord(e as element(Employee), *) matches a map if it has an entry with key "e" whose value matches element(Employee), regardless what other entries the map might contain.

For generality:

  • The syntax record() defines a record type that has no explicit fields and that is not extensible. The only thing it matches is an empty mapDM.

  • The syntax record(*) defines an extensible record type that has no explicit field declarations. It is equivalent to the item type map(*): that is, it matches any map.

A record type can constrain only those entries whose keys are strings, but when the record type is marked as extensible, then other entries may be present in the map with either string or non-string keys. Entries whose key is a string can be expressed using an (unquoted) NCName if the key conforms to NCName syntax, or using a (quoted) string literal otherwise.

Although constructors for named record types produce a map in which the entry orderDM reflects the order of field definitions in the record type definition, the entry orderDM of a map has no effect on whether the map matches a particular record type: the entries in a map do not have to be in any particular order.

Note:

Lookup expressions have been extended in 4.0 so that non-NCName keys can be used without parentheses: employee?"middle name"

If the type declaration for a field is omitted, then item()* is assumed: that is, the map entry may have any type.

If the field name is followed by a question mark, then the value must have the specified type if it is present, but it may also be absent. For example, the RecordTyperecord(first as xs:string, middle? as xs:string, last as xs:string, *) requires the map to have string-valued entries with keys "first" and "last"; it also declares that if the map has an entry with key "middle", the value of that entry must be a single xs:string. Declaring the type as record(first as xs:string, middle? as xs:string?, last as xs:string, *) also allows the entry with key "middle" to be present but empty.

Note:

Within an extensible record type, a FieldDeclaration that is marked optional and has no declared type does not constrain the map in any way, so it serves no practical purpose, but it is permitted because it may have documentary value.

The names of the fields in a record type must be distinct [err:XPST0021].

If a variable $rec is known to conform to a particular record type, then when a lookup expression $rec?field is used, (a) the processor can report a type error if $rec cannot contain an entry with name field (see 4.14.3.4 Implausible Lookup Expressions), and (b) the processor can make static type inferences about the type of value returned by $rec?field.

Note:

(TODO: change function signatures as suggested here!) A number of functions in the standard function library use maps as function arguments; this is a useful technique where the information to be supplied across the interface is highly variable. However, the type signature for such functions typically declares the argument type as map(*), which gives very little information (and places very few constraints) on the values that are actually passed across. Using record types offers the possibility of improving this: for example, the options argument of fn:parse-json, previously given as map(*), can now be expressed as record(liberal? as xs:boolean, duplicates? as xs:string, escape? as xs:boolean, fallback as fn(xs:string) as xs:string, *). In principle the xs:string type used to describe the duplicates option could also be replaced by a schema-defined subtype of xs:string that enumerates the permitted values ("reject", "use-first", "use-last").

The use of a record type in the signature of such a function causes the coercion rules to be invoked. So, for example, if the function expects an entry in the map to be an xs:double value, it becomes possible to supply a map in which the corresponding entry has type xs:integer.

Greater precision in defining the types of such arguments also enables better type checking, better diagnostics, better optimization, better documentation, and better syntax-directed editing tools.

Note:

One of the motivations for introducing record types is to enable better pattern matching in XSLT when processing JSON input. With XML input, patterns are often based around XML element names. JSON has no direct equivalent of XML’s element names; matching a JSON object such as {longitude: 130.2, latitude: 53.4} relies instead on recognizing the property names appearing in the object. XSLT 4.0, by integrating record types into pattern matching syntax, allows such an object to be matched with a pattern of the form match="record(longitude, latitude)"

Rules defining whether one record type is a subtype of another are given in 3.3.2.9 Subtyping Records.

3.3 Subtype Relationships

Changes in 4.0 (next | previous)

  1. The presentation of the rules for the subtype relationship between sequence types and item types has been substantially rewritten to improve clarity; no change to the semantics is intended.  [Issue 196 PR 202 25 October 2022]

[Definition: Given two sequence types or item types, the rules in this section determine if one is a subtype of the other. If a type A is a subtype of type B, it follows that every value matched by A is also matched by B.]

Note:

The relationship subtype(A, A) is always true: every type is a subtype of itself.

Note:

The converse is not necessarily true: we cannot infer that if every value matched by A is also matched by B, then A is a subtype of type B. For example, A might be defined as the set of strings matching the regular expression [A-Z]*, while B is the set of strings matching the regular expression [A-Za-z]*; no subtype relationship holds between these types.

The rules for deciding whether one sequence type is a subtype of another are given in 3.3.1 Subtypes of Sequence Types. The rules for deciding whether one item type is a subtype of another are given in 3.3.2 Subtypes of Item Types.

Note:

The subtype relationship is not acyclic. There are cases where subtype(A, B) and subtype(B, A) are both true. This implies that A and B have the same value space, but they can still be different types. For example this applies when A is a union type with member types xs:string and xs:integer, while B is a union type with member types xs:integer and xs:string. These are different types ("23" cast as A produces a string, while "23" cast as B produces an integer, because casting is attempted to each member type in order) but both types have the same value space.

3.3.2 Subtypes of Item Types

We use the notation A ⊆ B, or itemtype-subtype(A, B) to indicate that an item typeA is a subtype of an item type B. This section defines the rules for deciding whether any two item types have this relationship.

The rules in this section apply to item types, not to item type designators. For example, if the name STR has been defined in the static context as a named item type referring to the type xs:string, then anything said here about the type xs:string applies equally whether it is designated as xs:string or as STR, or indeed as the parenthesized forms (xs:string) or (STR).

References to named item types are handled as described in 3.3.2.10 Subtyping of Named Item Types.

The relationship A ⊆ B is true if and only if at least one of the conditions listed in the following subsections applies:

3.3.2.7 Subtyping Maps

Given item types A and B, AB is true if any of the following apply:

  1. Both of the following are true:

    1. A is map(K, V), for any K and V

    2. B is map(*)

    Example:

    map(xs:integer, item()*) ⊆ map(*)

  2. All the following are true:

    1. A is map(Ka, Va)

    2. B is map(Kb, Vb)

    3. KaKb

    4. VaVb

    Example:

    map(xs:long, item()) ⊆ map(xs:integer, item()+)

  3. Both the following are true:

    1. A is map(*) (or, because of the transitivity rules, any other map type)

    2. B is function(*)

    Example:

    map(xs:long, xs:string?) ⊆ function(*)

  4. Both the following are true:

    1. A is map(*) (or, because of the transitivity rules, any other map type)

    2. B is function(xs:anyAtomicType) as item()*

    Example:

    map(xs:long, xs:string?) ⊆ function(xs:anyAtomicType) as item()*

  5. All the following are true:

    1. A is map(K, V)

    2. B is function(xs:anyAtomicType) as R

    3. VR

    4. empty-sequence()R

    Examples:
    • map(xs:int, node()) ⊆ function(xs:anyAtomicType) as node()?

    • map(xs:int, node()+) ⊆ function(xs:anyAtomicType) as node()*

    The function accepts type xs:anyAtomicType rather than xs:int, because $M("xyz") is a valid call on a map (treated as a function) even when all the keys in the map are integers.

    The return type of the function is extended from node() or node()+ to allow anthe empty sequence because $M("xyz") can return anthe empty sequence even if none of the entries in the map contains anthe empty sequence.

3.4 Coercion Rules

Changes in 4.0 (next | previous)

  1. The term "function conversion rules" used in 3.1 has been replaced by the term "coercion rules".   [ PR 254 29 November 2022]

  2. The coercion rules allow “relabeling” of a supplied atomic item where the required type is a derived atomic type: for example, it is now permitted to supply the value 3 when calling a function that expects an instance of xs:positiveInteger.   [Issue 117 PR 254 29 November 2022]

  3. The coercion rules now allow any numeric type to be implicitly converted to any other, for example an xs:double is accepted where the required type is xs:decimal.   [Issue 980 PR 911 30 January 2024]

  4. The coercion rules now allow conversion in either direction between xs:hexBinary and xs:base64Binary.   [Issues 130 480 PR 815 7 November 2023]

  5. The coercion rules now apply recursively to the members of an array and the entries in a map.   [Issue 1318 PR 1501 29 October 2024]

  6. The coercion rules now reorder the entries in a map when the required type is a record type.   [Issue 1862 PR 1874 25 March 2025]

[Definition: The coercion rules are rules used to convert a supplied value to a required type, for example when converting an argument of a function call to the declared type of the function parameter. ] The required type is expressed as a sequence type. The effect of the coercion rules may be to accept the value as supplied, to convert it to a value that matches the required type, or to reject it with a type error.

This section defines how the coercion rules operate; the situations in which the rules apply are defined elsewhere, by reference to this section.

Note:

In previous versions of this specification, the coercion rules were referred to as the function conversion rules. The terminology has changed because the rules are not exclusively associated with functions or function calling.

If the required type is empty-sequence(), no coercion takes place (the supplied value must be anthe empty sequence, or a type error occurs).

In all other cases, the required sequence typeT comprises a required item typeR and an optional occurrence indicator. The coercion rules are then applied to a supplied value V and the required type T as follows:

  1. If XPath 1.0 compatibility mode is true and V is not an instance of the required type T, then the conversions defined in 3.4.1 XPath 1.0 Compatibility Rules are applied to V. Then:

  2. Each item in V is processed against the required item type R using the item coercion rules defined in 3.4.2 Item Coercion Rules, and the results are sequence-concatenated into a single sequence V′.

  3. A type error is raised if the cardinality of V′ does not match the required cardinality of T [err:XPTY0004].

3.4.2 Item Coercion Rules

The rules in this section are used to process each item J in a supplied sequence, given a required item typeR.

  1. If R is a generalized atomic type (for example, if it is an atomic type, a pure union type, or an enumeration type), and J is not an atomic item, then:

    1. J is atomized to produce a sequence of atomic items JJ.

    2. Each atomic item in JJ is coerced to the required type R by recursive application of the item coercion rules (the rules in this section) to produce a value V.

    3. The result is the sequence concatenation of the V values.

    Note:

    For example, if J is an element with type annotation xs:integer, and R is the union type xs:numeric, then the effect is to atomize the element to an xs:integer, and then to coerce the resulting xs:integer to xs:numeric (which leaves the integer unchanged). This is not the same as attempting to coerce the element to each of the alternatives of the union type in turn, which would deliver an instance of xs:double.

  2. Otherwise, if R is a choice item type or a pure union type (which includes the case where it is an enumeration type), then:

    1. If J matches (is an instance of) one of the alternatives in R, then J is coerced to the first alternative in R that J matches.

      Note:

      There are two situations where coercing an item to a type that it already matches does not simply return the item unchanged:

      • When the required type is a typed function type (see 3.2.8.1 Function Types), then function coercion is applied to coerce J to that function type, as described in 3.4.4 Function Coercion.

      • When the required type is a record type and the supplied value is a map, then coercion may change the entry orderDM of the entries in the map.

    2. Otherwise, the item coercion rules (the rules in this section) are applied to J recursively with R set to each of the alternatives in the choice or union item type, in order, until an alternative is found that does not result in a type error; a type error is raised only if all alternatives fail.

      The error code used in the event of failure should be the error code arising from the first unsuccessful matching attempt. (The diagnostic information associated with the error may also describe how further attempts failed.)

    Note:

    Suppose the required type is (xs:integer | element(e))* and the supplied value is the sequence (<e>22</e>, 23, <f>24</f>). Item coercion is applied independently to each of the three items in this sequence. The first item matches one of the alternatives, namely element(e), so it is returned unchanged as an element node. The second item (the integer 23) also matches one of the alternatives, and is returned unchanged as an integer. The third item does not match any of the alternatives, so coercion is attempted to each one in turn. Coercion to type xs:integer succeeds (by virtue of atomization and untyped atomic conversion), so the final result is the sequence (<e>22</e>, 23, 24)

    Note:

    Suppose the required type is enum("red", "green", "blue") and the supplied value is "green". The enumeration type is defined as a choice item type whose alternatives are singleton enumerations, so the rules are applied first to the type enum("red") (which fails), and then to the type enum("green") (which succeeds). The strings in an enumeration type are required to be distinct so the order of checking is in this case immaterial. The supplied value will be accepted, and will be relabeled if necessary as an instance of xs:string.

    Note:

    Schema-defined union types behave in exactly the same way as choice item types.

  3. If R is an atomic type and J is an atomic item, then:

    1. If J is an instance of R then it is used unchanged.

    2. If J is an instance of type xs:untypedAtomic then:

      1. If R is namespace-sensitive then a type error [err:XPTY0117] is raised.

      2. Otherwise, J is cast to type R.

  4. If there is an entry (from, to) in the following table such that J is an instance of from, and to is R, then J is cast to type R.

    Implicit Casting
    fromto
    xs:decimalxs:double
    xs:doublexs:decimal
    xs:decimalxs:float
    xs:floatxs:decimal
    xs:floatxs:double
    xs:doublexs:float
    xs:stringxs:anyURI
    xs:anyURIxs:string
    xs:hexBinaryxs:base64Binary
    xs:base64Binaryxs:hexBinary

    Note:

    The item type in the to column must match R exactly; however, J may belong to a subtype of the type in the from column.

    For example, an xs:NCName will be cast to type xs:anyURI, but an xs:anyURI will not be cast to type xs:NCName.

    Similarly, an xs:integer will be cast to type xs:double, but an xs:double will not be cast to type xs:integer.

  5. If R is an singleton enumeration type and J is an instance of xs:untypedAtomic or xs:anyURI, then J is cast to type xs:string.

    Note:

    The effect of this rule, when taken in conjunction with the rules above regarding atomization and choice item types, is that when the required type is based on an enumeration type, for example enum("red", "green", "blue")*, the supplied value can be, in this example:

    • AnThe empty sequence.

    • The string "red".

    • An untyped node whose string value is "red".

    • A list-valued node whose typed value contains zero or more strings (or xs:anyURI values), each of which is codepoint-equal to one of "red", "green", or "blue".

    • The xs:anyURI value "red".

    • An array with zero or more members each of which is codepoint-equal to one of "red", "green", or "blue".

    • A JNode whose ·content· property is any of the above.

  6. If R is derived from some primitive atomic type P, then J is relabeled as an instance of R if it satisfies all the following conditions:

    • J is an instance of P.

    • J is not an instance of R.

    • The datumDM of J is within the value space of R.

    Relabeling an atomic item changes the type annotation but not the datumDM. For example, the xs:integer value 3 can be relabeled as an instance of xs:unsignedByte, because the datum is within the value space of xs:unsignedByte.

    Note:

    Relabeling is not the same as casting. For example, the xs:decimal value 10.1 can be cast to xs:integer, but it cannot be relabeled as xs:integer, because its datum not within the value space of xs:integer.

    Note:

    The effect of this rule is that if, for example, a function parameter is declared with an expected type of xs:positiveInteger, then a call that supplies the literal value 3 will succeed, whereas a call that supplies -3 will fail.

    This differs from previous versions of this specification, where both these calls would fail.

    This change allows the arguments of existing functions to be defined with a more precise type. For example, the $position argument of array:get could be defined as xs:positiveInteger rather than xs:integer.

    Note:

    If T is a union type with members xs:negativeInteger and xs:positiveInteger and the supplied value is the sequence (20, -20), then the effect of these rules is that the first item 20 is relabeled as type xs:positiveInteger and the second item -20is relabeled as type xs:negativeInteger.

    Note:

    Promotion (for example of xs:float to xs:double) occurs only when T is a primitive type. Relabeling occurs only when T is a derived type. Promotion and relabeling are therefore never combined.

    Note:

    A singleton enumeration type such as enum("green") is treated as an atomic type derived by restriction from xs:string; so if the xs:string value "green" is supplied in a context where the required type is enum("red", "green", "blue"), the value will be accepted.

  7. If J is a JNodeDM and does not match R, then each item in the ·content· of J is coerced to type R by applying the coercion rules recursively.

    Note:

    For example, if $A is an array and the members of the array are maps, then $A/child::* returns a sequence of JNodes that encapsulate maps, and the average size of these maps can be obtained using the expression avg($A/child::* ! map:size(.)). The first argument of map:size does not accept a JNode directly, but it does (in effect) accept a JNode that encapsulates a map.

  8. If R is an ArrayType other than array(*) and J is an array, then J is converted to a new array by converting each member to the required member type by applying the coercion rules recursively.

    Note:

    For example, if the required type is array(xs:double) and the supplied value is [ 1, 2 ], the array is converted to [ 1e0, 2e0 ].

  9. If R is a MapType other than map(*) and J is a map, then J is converted to a new map as follows:

    1. Each key in the supplied map is converted to the required map key type by applying the coercion rules. If the resulting map would contain duplicate keys, a type error is raised [err:XPTY0004].

    2. The corresponding value is converted to the required map value type by applying the coercion rules recursively.

    3. The order of entries in the map remains unchanged.

    Note:

    For example, if the required type is map(xs:string, xs:double) and the supplied value is { "x": 1, "y": 2 }, the map is converted to { "x": 1e0, "y": 2e0 }.

    Note:

    Duplicate keys can occur if the value space of the target type is more restrictive than the original type. For example, an error is raised if the map { 1.2: 0, 1.2000001: 0 }, which contains two keys of type xs:decimal, is coerced to the type map(xs:float, xs:integer).

  10. If R is a RecordType and J is a map, then J is converted to a new map as follows:

    1. The keys in the supplied map are unchanged.

    2. In any map entry whose key is equal to the name of one of the field declarations in R (under the rules of the atomic-equal function), the corresponding value is converted to the required type defined by that field declaration, by applying the coercion rules recursively (but with XPath 1.0 compatibility mode treated as false).

    3. The order of entries in the map is changed: entries whose keys correspond to the names of field declarations in R appear first, in the order of the corresponding field declarations, and (if the record type is extensible) other entries then follow retaining their relative order in J.

    Note:

    For example, if the required type is record(longitude as xs:double, latitude as xs:double) and the supplied value is { "latitude": 53.2, "longitude": 0 }, then the map is converted to { "longitude": 0.0e0, "latitude": 53.2e0 }.

  11. If R is a TypedFunctionType and J is a function item, then function coercion is applied to J.

    Note:

    Function coercion applies even if J is already an instance of R.

    Maps and arrays are functions, so function coercion applies to them as well.

  12. If, after the above conversions, the resulting item does not match the expected item type R according to the rules for SequenceType Matching, a type error is raised [err:XPTY0004].

    Note:

    Under the general rules for type errors (see 2.5.1 Kinds of Errors), a processor may report a type error during static analysis if it will necessarily occur when the expression is evaluated. For example, the function call fn:abs("beer") will necessarily fail when evaluated, because the function requires a numeric value as its argument; this may be detected and reported as a static error.

3.4.3 Implausible Coercions

An expression is deemed to be implausible [err:XPTY0006] if the static type of the expression, after applying all necessary coercions, is substantively disjoint with the required type T.

[Definition: Two sequence types are deemed to be substantively disjoint if (a) neither is a subtype of the other (see 3.3.1 Subtypes of Sequence Types) and (b) the only values that are instances of both types are one or more of the following:

]

Note:

Examples of pairs of sequence types that are substantively disjoint include:

  • xs:integer* and xs:string*

  • map(xs:integer, node()) and map(xs:string, node())

  • array(xs:integer) and array(xs:string)

For example, supplying a value whose static type is xs:integer* when the required type is xs:string* is implausible, because it can succeed only in the special case where the actual value supplied is anthe empty sequence.

Note:

The case where the supplied type and the required type are completely disjoint (for example map(*) and array(*)) is covered by the general rules for type errors: that case can always be reported as a static error.

Examples of implausible coercions include the following:

  • round(timezone-from-time($now)). The result of fn:timezone-from-time is of type xs:dayTimeDuration?, which is substantively disjoint with the required type of fn:round, namely xs:numeric?.

  • function($x as xs:integer) as array(xs:string) { array { 1 to $x } }. The type of the function body is array(xs:integer), which is substantively disjoint with the required type array(xs:string): the function can succeed only in the exceptional case where the function body delivers an empty arrayDM.

3.4.4 Function Coercion

Changes in 4.0 (next | previous)

  1. Function coercion now allows a function with arity N to be supplied where a function of arity greater than N is expected. For example this allows the function true#0 to be supplied where a predicate function is required.

  2. It has been clarified that function coercion applies even when the supplied function item matches the required function type. This is to ensure that arguments supplied when calling the function are checked against the signature of the required function type, which might be stricter than the signature of the supplied function item.   [Issue 1020 PRs 1023 1128 9 April 2024]

Function coercion is a transformation applied to function items during application of the coercion rules. [Definition: Function coercion wraps a function item in a new function whose signature is the same as the expected type. This effectively delays the checking of the argument and return types until the function is called.]

Given a function F, and an expected function type T, function coercion proceeds as follows:

  1. If F has higher arity than T, a type error is raised [err:XPTY0004]

  2. If F has lower arity than T, then F is wrapped in a new function that declares and ignores the additional argument; the following steps are then applied to this new function.

    For example, if T is function(node(), xs:boolean) as xs:string, and the supplied function is fn:name#1, then the supplied function is effectively replaced by function($n as node(), $b as xs:boolean) as xs:string { fn:name($n) }

    Note:

    This mechanism makes it easier to design versatile and extensible higher-order functions. For example, in previous versions of this specification, the second argument of the fn:filter function expected an argument of type function(item()) as xs:boolean. This has now been extended to function(item(), xs:integer) as xs:boolean, but existing code continues to work, because callback functions that are not interested in the value of the second argument simply ignore it.

  3. A type error is raised [err:XPTY0004] if, for any parameter type, or for the result type, the relevant type in the signature of the supplied function and the relevant type in the expected function type are substantively disjoint.

    For example, the types xs:integer and xs:string are substantively disjoint, so a function with signature function(xs:integer) as xs:boolean cannot be supplied where the expected type is function(xs:string) as xs:boolean.

  4. Function coercion then returns a new function item with the following properties (as defined in [XDM 4.0] section 8.1 Function Items):

    • name: The name of F(if not absent).

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

    • signature: Annotations is set to the annotations of F. TypedFunctionType is set to the expected type.

    • implementation: In effect, a FunctionBody that calls F, passing it the parameters of this new function, in order.

    • nonlocal variable bindings: An empty mapping.

These rules have the following consequences:

  • SequenceType matching of the function’s arguments and result are delayed until that function is called.

  • When the coerced function is called, the supplied arguments must match the parameter typed defined in T; it is not sufficient to match the parameter types defined in F.

  • The coercion rules rules applied to the function’s arguments and result are defined by the SequenceType it has most recently been coerced to. Additional coercion rules could apply when the wrapped function is called.

  • If an implementation has static type information about a function, that can be used to type check the function’s argument and return types during static analysis.

  • When function coercion is applied to a map or an array, the resulting function is not a map or array, and cannot be used as such. For example, the expression

    let $f as function(xs:integer) as xs:boolean := { 0: false(), 1: true() }
    return $f?0

    raises a type error, because a lookup expression requires the left hand operand to be a map or array, and $f is neither.

  • When function types are used as alternatives in a choice item type, the supplied function is coerced to the first alternative for which coercion does not raise a type error. In this situation it is important to write the alternatives in order, with the most specific first.

Note:

The semantics of function coercion are specified in terms of wrapping the functions. Static typing may be able to reduce the number of places where this is actually necessary. However, it cannot be assumed that because a supplied function is an instance of the required function type, no function coercion is necessary: the supplied function might not perform all required checks on the types of its arguments.

Since maps and arrays are also functions in XPath 4.0, function coercion applies to them as well. For instance, consider the following expression:

let $m := {
  "Monday" : true(),
  "Wednesday" : false(),
  "Friday" : true()
}
let $days := ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday")
return filter($days, $m)

The map $m is an instance of function(xs:anyAtomicType?) as item()*. When the fn:filter() function is called, the following occurs to the map:

  1. The map $m is treated as a function equivalent to map:get($m, ?).

  2. The coercion rules result in applying function coercion to this function, wrapping it in a new function (M′) with the signature function(item(), xs:integer) as xs:boolean.

  3. When M′ is called by fn:filter(), coercion and SequenceType matching rules are applied to the argument, resulting in an item() value ($a) or a type error.

  4. The function map:get($m, ?) is called with $a as the argument; this returns either an xs:boolean or the empty sequence (call the result R).

  5. The wrapper function $p applies the coercion rules to R. If R is an xs:boolean the matching succeeds. When it is anthe empty sequence (in particular, $m does not contain a key for "Tuesday"), a type error is raised [err:XPTY0004], since the expected type is xs:boolean and the actual type is an, which does not allow the empty sequence.

Consider the following expression:

let $m := {
   "Monday" : true(),
   "Wednesday" : false(),
   "Friday" : true(),
}
let $days := ("Monday", "Wednesday", "Friday")
return filter($days, $m)

In this case the result of the expression is the sequence ("Monday", "Friday"). But if the input sequence included the string "Tuesday", the filter operation would fail with a type error.

Note:

Function coercion applies even if the supplied function matches the required type.

For example, consider this case:

declare function local:filter(
  $s as item()*, 
  $p as function(xs:string) as xs:boolean
) as item()* {
  $s[$p(.)]
};

let $f := function($a) { $a mod 2 = 0 }
return local:filter(1 to 10, $f)

Here the supplied function $f is an instance of the required type, because its signature defaults the argument type to item()*, which is a supertype of xs:string. The expression $s[$p(.)] could in principle succeed. However, function coercion ensures that the supplied function is wrapped in a function that requires the argument to be of type xs:string, so the call fails with a type error when the wrapping function is invoked supplying an xs:integer as the argument.

3.4.5 Examples of Coercions

This section illustrates the effect of the coercion rules with examples.

Example: Coercion to xs:string

Consider the case where the required type (of a variable, or a function argument) is xs:string. For example, the second argument of fn:matches, which expects a regular expression. The table below illustrates the values that might be supplied, and the coercions that are applied.

Supplied ValueCoercion
"[0-9]"

None; the supplied value is an instance of the required type.

default-language()

None; the supplied value is an instance of xs:language, which is a subtype of the required type xs:string.

<a>[0-9]</a>

The supplied element node is atomized. Unless it has been schema-validated, the typed value will be an instance of xs:untypedAtomic, which is accepted when the required type is xs:string.

Supplying an element whose type annotation is (say) xs:date will fail with a type error.

The effect is subtly different if XPath 1.0 compatibility mode is enabled. In this case coercion takes the string value of the element node. This differs from the typed value only in the case where the element has been schema-validated and has a type annotation other than xs:string.

xs:anyURI("urn:dummy")

Supplying an instance of xs:anyURI where the expected type is xs:string is permitted; this is one of the pairs of types where implicit casting is allowed.

17.2

Supplying a number where a string is expected raises a type error.

However, if XPath 1.0 compatibility mode is enabled, the number is converted to a string as if by the fn:string function.

//author/@id

Supplying a sequence of nodes where a single string is expected will raise a type error unless either there is only one node in the sequence. In this case the typed value of the node will be used (this must be of type xs:string, xs:untypedAtomic, or xs:anyURI).

If XPath 1.0 compatibility mode is enabled, however, all strings after the first are discarded, and the string value of the first node is used; if the sequence is empty, a zero-length string is supplied.

("red", "green", "blue")

Supplying a sequence of strings where a single string is expected raises a type error.

If XPath 1.0 compatibility mode is enabled, however, all strings after the first are discarded; the effect is as if the supplied value were "red".

()

Supplying anthe empty sequence where a single string is expected will fail.

If XPath 1.0 compatibility mode is enabled, however, the value is coerced by applying the function fn:string(()), which delivers the zero-length string.

["a|b"]

Supplying an array holding a single string succeeds, because the rules cause the array to be atomized, and the value after atomization is a single string.

Supplying an array holding multiple strings would fail.

In XPath 1.0 compatibility mode, supplying an array will fail, regardless of the array contents, because the fn:string function does not accept arrays.

 

Example: Coercion to xs:decimal?

Consider the case where the required type (of a variable, or a function argument) is xs:decimal?. For example, the first argument of fn:seconds, which expects a decimal number of seconds. The table below illustrates the values that might be supplied, and the coercions that are applied.

Supplied ValueCoercion
12.4

None; the supplied value is an instance of the required type.

()

None; anthe empty sequence is an instance of the required type.

42

None; the supplied value is an instance of xs:integer, which is a subtype of the required type.

math:pi()

The supplied value is an instance of xs:double, which can be converted to xs:decimal under the coercion rules.

("a", "b")[.="c"]

The supplied value is anthe empty sequence, which is a valid instance of the required type xs:decimal?. However, the processor may (optionally) reject this as an implausible coercion, on the grounds that it can only succeed in one special case, namely where the filter expression selects no values.

(1.5, 2.5, 3.5)

A type error is raised, except in the case where XPath 1.0 compatibility is enabled, in which case all values after the first are discarded.

<a>3.14159</a>

The element node is atomized; unless it has been schema-validated, the result will be "3.14159" as an instance of xs:untypedAtomic. This is converted to an instance of xs:decimal following the rules of the cast as operator.

"12.2"

Supplying a string where an xs:decimal is a type error, even if XPath 1.0 compatibility mode is enabled. The rules for compatibility mode would allow conversion if the required type were xs:double, but not for xs:decimal.

[1.5]

The array is atomized, and the result is a valid instance of the required type xs:decimal?

[]

The array is atomized, and the result is anthe empty sequence, which is a valid instance of the required type xs:decimal?

 

Example: Coercion to xs:positive-integer

Consider the case where the required type (of a variable, or a function argument) is xs:positive-integer. The table below illustrates the values that might be supplied, and the coercions that are applied.

Supplied ValueCoercion
12

The supplied value is of type xs:integer. Because the supplied value and the required type, xs:positiveInteger, both come under the primitive type xs:decimal, and the value 12 is within the value space of xs:positiveInteger, the value is relabeled as an xs:positiveInteger and the call succeeds.

12.1

This fails with a type error, because the xs:decimal value 12.1 is not a value in the value space of xs:positiveInteger. This is so even though casting to xs:positiveInteger would succeed.

math:pi()

This fails with a type error. A value of type xs:double is accepted where the required type is xs:decimal or xs:float, but not where it is xs:positiveInteger.

<a>1200</a>

The supplied element node is atomized. If the element has not been schema-validated, the result will be an xs:untypedAtomic item, which is successfully cast to the required type xs:positiveInteger. If the element has been validated against a schema, then coercion succeeds if the typed value would itself be acceptable, for example if it is an xs:positiveInteger, or some other xs:decimal within the value space of xs:positiveInteger.

 

Example: Coercion to a union type

Consider the first parameter of the function fn:char, whose declared type is (xs:string | xs:positiveInteger). The rules are the same as if it were a union typed declared in an imported schema.

Supplied ValueCoercion
"amp"

The supplied value is of type xs:string, which is one of the allowed types. The call therefore succeeds.

"#"

The supplied value is of type xs:string, which is one of the allowed types. As far as the coercion rules are concerned, the call therefore succeeds. Under the semantic rules for the fn:char function, however, this value is not accepted; a dynamic error (as distinct from a type error) is therefore raised.

0x25

The supplied value is of type xs:integer. Although this is not one of the allowed types, it is acceptable because coercion of the value to type xs:positiveInteger succeeds. The value is relabeled as an instance of xs:positiveInteger.

<a>0x25</a>

The supplied element node is atomized. Assuming that the node has not been schema-validated, the result is an instance of xs:untypedAtomic. The member types of the choice are tested in order. Conversion to xs:string with the value "0x25" succeeds, so the fn:char function is called supplying this string; but the function rejects this string as semantically invalid. The same would happen if the value were, say, <a>37</a>. Supplying such a value requires an explicit cast, for example fn:char( xs:positiveInteger( ./a )).

 

Example: Coercion to a choice type

Suppose the required type is (record(x as xs:decimal, y as xs:decimal, *) | record(size as enum("S", "M", "L", "XL"), *)).

Supplied ValueCoercion
{ "x": 1, "y": 2, "z": 3 }

The supplied value is an instance of the first record type: no coercion is necessary.

{ "size": "M" }

The supplied value is an instance of the second record type: no coercion is necessary.

{ "x": 1, "y": 2, "size": "XL" }

The supplied value is an instance of both record types: no coercion is necessary.

{ "x": 1e0, "y": 2e0, "size": "XL" }

The supplied value is not an instance of the first record type because the fields are of type xs:double rather than xs:decimal. It is however an instance of the second record type. It is therefore accepted as is; the fields x and y are not converted from xs:double to xs:decimal.

{ "x": 1e0, "y": 2e0, "size": "XXL" }

The supplied value is not an instance of the first record type because the fields are of type xs:double rather than xs:decimal, and it is not an instance of the second record type because the size value does not match the enumeration type. Coercion is therefore attempted to the first record type, and succeeds. The x and y fields are coerced to xs:decimal, and the size field is accepted as is.

4 Expressions

This section discusses each of the basic kinds of expression. Each kind of expression has a name such as PathExpr, which is introduced on the left side of the grammar production that defines the expression. Since XPath 4.0 is a composable language, each kind of expression is defined in terms of other expressions whose operators have a higher precedence. In this way, the precedence of operators is represented explicitly in the grammar.

The order in which expressions are discussed in this document does not reflect the order of operator precedence. In general, this document introduces the simplest kinds of expressions first, followed by more complex expressions. For the complete grammar, see Appendix [A XPath 4.0 Grammar].

The highest-level symbol in the XPath grammar is XPath.

XPath::=(DefaultElementNamespaceDecl ";")? (NamespaceDecl ";")* Expr
DefaultElementNamespaceDecl::="declare" "default" "element" "namespace" URILiteral
NamespaceDecl::="declare" "namespace" NCName "=" URILiteral
Expr::=(ExprSingle ++ ",")

The effect of a DefaultElementNamespaceDecl or NamespaceDecl is described in 4.1 Namespace Declarations.

ExprSingle::=ForExpr
| LetExpr
| QuantifiedExpr
| IfExpr
| OrExpr
ForExpr::=ForClauseForLetReturn
LetExpr::=LetClauseForLetReturn
QuantifiedExpr::=("some" | "every") (QuantifierBinding ++ ",") "satisfies" ExprSingle
IfExpr::="if" "(" Expr ")" (UnbracedActions | BracedAction)
OrExpr::=AndExpr ("or" AndExpr)*

The XPath 4.0 operator that has lowest precedence is the comma operator, which is used to combine two operands to form a sequence. As shown in the grammar, a general expression (Expr) can consist of multiple ExprSingle operands, separated by commas.

The name ExprSingle denotes an expression that does not contain a top-level comma operator (despite its name, an ExprSingle may evaluate to a sequence containing more than one item.)

The symbol ExprSingle is used in various places in the grammar where an expression is not allowed to contain a top-level comma. For example, each of the arguments of a function call must be a ExprSingle, because commas are used to separate the arguments of a function call.

After the comma, the expressions that have next lowest precedence are ForExpr, LetExpr, QuantifiedExpr, IfExpr, and OrExpr. Each of these expressions is described in a separate section of this document.

4.3 Primary Expressions

[Definition: A primary expression is an instance of the production PrimaryExpr. Primary expressions are the basic primitives of the language. They include literals, variable references, context value references, and function calls. A primary expression may also be created by enclosing any expression in parentheses, which is sometimes helpful in controlling the precedence of operators.] Map and Array Constructors are described in 4.14.1 Maps and 4.14.2 Arrays.

PrimaryExpr::=Literal
| VarRef
| ParenthesizedExpr
| ContextValueRef
| FunctionCall
| FunctionItemExpr
| MapConstructor
| ArrayConstructor
| StringTemplate
| UnaryLookup
Literal::=NumericLiteral | StringLiteral | QNameLiteral
VarRef::="$" EQName
ParenthesizedExpr::="(" Expr? ")"
ContextValueRef::="."
FunctionCall::=EQNameArgumentList
/* xgc: reserved-function-names */
/* gn: parens */
FunctionItemExpr::=NamedFunctionRef | InlineFunctionExpr
NamedFunctionRef::=EQName "#" IntegerLiteral
/* xgc: reserved-function-names */
InlineFunctionExpr::=("function" | "fn") FunctionSignature? FunctionBody
MapConstructor::="map"? "{" (MapConstructorEntry ** ",") "}"
ArrayConstructor::=SquareArrayConstructor | CurlyArrayConstructor
StringTemplate::="`" (StringTemplateFixedPart | StringTemplateVariablePart)* "`"
/* ws: explicit */
UnaryLookup::=Lookup

4.3.4 Parenthesized Expressions

ParenthesizedExpr::="(" Expr? ")"
Expr::=(ExprSingle ++ ",")

Parentheses may be used to override the precedence rules. For example, the expression (2 + 4) * 5 evaluates to thirty, since the parenthesized expression (2 + 4) is evaluated first and its result is multiplied by five. Without parentheses, the expression 2 + 4 * 5 evaluates to twenty-two, because the multiplication operator has higher precedence than the addition operator.

Empty parentheses are used to denote anthe empty sequence, as described in 4.8.1 Sequence Concatenation.

4.6 Functions

Functions in XPath 4.0 arise in two ways:

The functions defined by a statically known function definition can be invoked using a static function call. Function items corresponding to these definitions can also be obtained, as dynamic values, by evaluating a named function reference. Function items can also be obtained using the fn:function-lookup function: in this case the function name and arity do not need to be known statically, and the function definition need not be present in the static context, so long as it is in the dynamic context.

Static and dynamic function calls are described in the following sections.

4.6.1 Static Function Calls

The static context for an expression includes a set of statically known function definitions. Every function definition in the static context has a name (which is an expanded QName) and an arity range, which is a range of permitted arities for calls on that function. Two function definitions having the same name must not have overlapping arity ranges. This means that for a given static function call, it is possible to identify the target function definition in the static context unambiguously from knowledge of the function name and the number of supplied arguments.

A static function call is bound to a function definition in the static context by matching the name and arity. If the function call has P positional arguments followed by K keyword arguments, then the required arity is P+K, and the static context must include a function definition whose name matches the expanded QName in the function call, and whose arity range includes this required arity. This is the function chosen to be called. The result of the function is obtained by evaluating the expression that forms its implementation, with a dynamic context that provides values for all the declared parameters, initialized as described in 4.6.1.2 Evaluating Static Function Calls below.

Similarly, a named function reference of the form f#N binds to a function definition in the static context whose name matches f where MinP ≤ N and MaxP ≥ N. The result of evaluating a function reference is a function item which can be called using a dynamic function call. Function items are never variadic and their arguments are always supplied positionally. For example, the function reference fn:concat#3 returns a function item with arity 3, which is always called by supplying three positional arguments, and whose effect is the same as a static call on fn:concat with three positional arguments.

The detailed rules for evaluating static function calls and function references are defined in subsequent sections.

4.6.1.1 Static Function Call Syntax

Changes in 4.0 (next | previous)

  1. Keyword arguments are allowed on static function calls, as well as positional arguments.   [Issue 155 PR 159 30 September 2020]

FunctionCall::=EQNameArgumentList
/* xgc: reserved-function-names */
/* gn: parens */
EQName::=QName | URIQualifiedName
ArgumentList::="(" ((PositionalArguments ("," KeywordArguments)?) | KeywordArguments)? ")"
PositionalArguments::=(Argument ++ ",")
Argument::=ExprSingle | ArgumentPlaceholder
ExprSingle::=ForExpr
| LetExpr
| QuantifiedExpr
| IfExpr
| OrExpr
ArgumentPlaceholder::="?"
KeywordArguments::=(KeywordArgument ++ ",")
KeywordArgument::=EQName ":=" Argument

[Definition: A static function call is an instance of the production FunctionCall: it consists of an EQName followed by a parenthesized list of zero or more arguments.].

The EQName is expanded using the default function namespace rule.

The argument list consists of zero or more positional arguments, followed by zero or more keyword arguments.

[Definition: An argument to a function call is either an argument expression or an ArgumentPlaceholder (?); in both cases it may either be supplied positionally, or identified by a name (called a keyword).]

This section is concerned with static function calls in which none of the arguments are ArgumentPlaceholders. Calls using one or more ArgumentPlaceholders are covered in the section 4.6.4 Partial Function Application.

The expanded QName used as the function name and the number of arguments used in the static function call (the required arity) must match the name and arity range of a function definition in the static context using the rules defined in the previous section; if there is no match, a static error is raised [err:XPST0017].

Evaluation of static function calls is described in 4.6.1.2 Evaluating Static Function Calls .

Since the arguments of a function call are separated by commas, any argument expression that contains a top-level comma operator must be enclosed in parentheses. Here are some illustrative examples of static function calls:

  • my:three-argument-function(1, 2, 3) denotes a static function call with three positional arguments. The corresponding function declaration must define at least three parameters, and may define more, provided they are optional.

  • my:two-argument-function((1, 2), 3) denotes a static function call with two arguments, the first of which is a sequence of two values. The corresponding function declaration must define at least two parameters, and may define more, provided they are optional.

  • my:two-argument-function(1, ()) denotes a static function call with two arguments, the second of which is anthe empty sequence.

  • my:one-argument-function((1, 2, 3)) denotes a static function call with one argument that is a sequence of three values.

  • my:one-argument-function(( )) denotes a static function call with one argument that is anthe empty sequence.

  • my:zero-argument-function( ) denotes a static function call with zero arguments.

  • lang(node := $n, language := 'de') is a static function call with two keyword arguments. The corresponding function declaration defines two parameters, a required parameter language and an optional parameter node. This call supplies values for both parameters. It is equivalent to the call fn:lang('de', $n). Note that the keyword arguments are in a different order from the parameter declarations.

  • sort(//employee, key := fn($e) { xs:decimal($e/salary) }) is a static function call with one positional argument and one keyword argument. The corresponding function declaration defines three parameters, a required parameter $input, an optional parameter $collation, and an optional parameter $key This call supplies values for the first and third parameters, leaving the second parameter ($collation) to take its default value. The default value of the $collation parameter is given as fn:default-collation(), so the value supplied to the function is the default collation from the dynamic context of the caller. It is equivalent to the call fn:sort(//employee, fn:default-collation(), fn($e) { xs:decimal($e/salary) }).

An EQName in a KeywordArgument is expanded using the no-namespace rule. The keywords used in a function call (after expansion) must be distinct [err:XPST0017].

4.6.3 Dynamic Function Calls

DynamicFunctionCall::=PostfixExprPositionalArgumentList
PostfixExpr::=PrimaryExpr | FilterExpr | DynamicFunctionCall | LookupExpr | MethodCall | FilterExprAM
PositionalArgumentList::="(" PositionalArguments? ")"
PositionalArguments::=(Argument ++ ",")
Argument::=ExprSingle | ArgumentPlaceholder
ExprSingle::=ForExpr
| LetExpr
| QuantifiedExpr
| IfExpr
| OrExpr
ArgumentPlaceholder::="?"

A dynamic function call consists of a base expression that returns the function and a parenthesized list of zero or more arguments (argument expressions or ArgumentPlaceholders).

A dynamic function call is evaluated as described in 4.6.3.1 Evaluating Dynamic Function Calls.

The following are examples of dynamic function calls:

  • This example calls the function contained in $f, passing the arguments 2 and 3:

    $f(2, 3)
  • This example fetches the second item from sequence $f, treats it as a function and calls it, passing an xs:string argument:

    $f[2]("Hi there")
  • This example calls the function $f passing no arguments, and filters the result with a positional predicate:

    $f()[2]

Note:

Arguments in a dynamic function call are always supplied positionally.

4.6.3.1 Evaluating Dynamic Function Calls

Changes in 4.0 (next | previous)

  1. A dynamic function call can now be applied to a sequence of functions, and in particular to anthe empty sequence. This makes it easier to chain a sequence of calls.  [Issue 1240 ]

This section applies to dynamic function calls whose arguments do not include an ArgumentPlaceholder. For function calls that include a placeholder, see 4.6.4 Partial Function Application.

A dynamic function call is an expression that is evaluated by calling a function item, which is typically obtained dynamically.

When a dynamic function call FC is evaluated, the result is obtained as follows:

  1. The base expression of the function call is evaluated. If this is not of type function(*)* (a sequence of zero or more function items) then a type error is raised [err:XPTY0004].

  2. The result of the dynamic function call is the sequence concatenation of the results of applying each function item individually, retaining order. That is, the result of F(X, Y, ...) is for $FI in F return $FI(X, Y, ...). The result of a dynamic function call applied to a single function item FI is defined by the rules that follow.

  3. [err:XPTY0004]. If the arity of FI does not match the number of arguments in the ArgumentList, a type error is raised [err:XPTY0004].

  4. Argument expressions are evaluated, producing argument values. The order of argument evaluation is implementation-dependent and an argument need not be evaluated if the function body can be evaluated without evaluating that argument.

  5. Each argument value is converted to the corresponding parameter type in FI’s signature by applying the coercion rules, resulting in a converted argument value

  6. If FI is a map, it is evaluated as described in 4.14.1.2 Maps as Functions.

  7. If FI is an array, it is evaluated as described in 4.14.2.2 Arrays as Functions.

  8. If FI’s body is an XPath 4.0 expression (for example, if FI is an anonymous function, or a partial application of such a function):

    1. FI’s body is evaluated. The static context for this evaluation is the static context of the XPath 4.0 expression. The dynamic context for this evaluation is obtained by taking the dynamic context of the InlineFunctionExpr that contains the FunctionBody, and making the following changes:

      • The focus (context value, context position, and context size) is absentDM.

      • In the variable values component of the dynamic context, each converted argument value is bound to the corresponding parameter name.

        When this is done, the converted argument values retain their dynamic types, even where these are subtypes of the declared parameter types. For example, a function with a parameter $p of type xs:decimal can be called with an argument of type xs:integer, which is derived from xs:decimal. During the processing of this function call, the value of $p inside the body of the function retains its dynamic type of xs:integer.

      • FI’s nonlocal variable bindings are also added to the variable values. (Note that the names of the nonlocal variables are by definition disjoint from the parameter names, so there can be no conflict.)

    2. The value returned by evaluating the function body is then converted to the declared return type of FI by applying the coercion rules. The result is then the result of evaluating FC.

      As with argument values, the value returned by a function retains its dynamic type, which may be a subtype of the declared return type of FI. For example, a function that has a declared return type of xs:decimal may in fact return a value of dynamic type xs:integer.

  9. If the implementation of FI is not an XPath 4.0 expression (for example, if FI is a system function ), the body of the function is evaluated, and the result is converted to the declared return type, in the same way as for a static function call (see 4.6.1.1 Static Function Call Syntax).

    Errors may be raised in the same way.

Example: Derived Types and Nonlocal Variable Bindings

$incr is a nonlocal variable that is available within the function because its variable binding has been added to the variable values of the function. Even though the parameter and return type of this function are both xs:decimal, the more specific type xs:integer is preserved in both cases.

let $incr := 1
let $f := function($i as xs:decimal) as xs:decimal { $i + $incr }
return $f(5)

 

Example: Using the Context Value in an Anonymous Function

The following example will raise a type error [err:XPDY0002]:

let $vat := function() { @vat + @price }
return doc('wares.xml')/shop/article/$vat()

Instead, the context value can be used as an argument to the anonymous function:

let $vat := function($art) { $art/@vat + $art/@price }
return doc('wares.xml')/shop/article/$vat(.)

Alternatively, the value can be referenced as a nonlocal variable binding:

let $ctx := doc('wares.xml')/shop/article
let $vat := function() { for $a in $ctx return $a/@vat + $a/@price }
return $vat()

Finally, a focus function can be used. This binds the value of the argument to the context value within the function body:

let $vat := function { @vat + @price }
return $vat(doc('wares.xml')/shop/article)

 

Example: Applying multiple functions

A dynamic function call can call zero or more functions with the same arguments, returning the sequence concatenation of the result. For example:

(abs#1, round#1, floor#1, ceiling#1)(3.2)

returns the sequence (3.2, 3, 3, 4).

A common case for supplying a sequence of functions arises when the functions are arrays. For example:

csv-to-arrays( string-join(("a,b,c", "p,q,r", "x,y,z"), char(10)) ) (2)

returns the sequence ("b", "q", "y").

If the base expression evaluates to anthe empty sequence, the result is anthe empty sequence.

Note:

Keyword arguments are not allowed in a dynamic function call.

4.7 Path Expressions

Changes in 4.0 (next | previous)

  1. Path expressions are extended to handle JNodes (found in trees of maps and arrays) as well as XNodes (found in trees representing parsed XML).   [Issue 2054 ]

PathExpr::=AbsolutePathExpr
| RelativePathExpr
/* xgc: leading-lone-slash */
AbsolutePathExpr::=("/" RelativePathExpr?) | ("//" RelativePathExpr)
RelativePathExpr::=StepExpr (("/" | "//") StepExpr)*

[Definition: A path expression is either an absolute path expression or a relative path expression ]

[Definition: An absolute path expression is an instance of the production AbsolutePathExpr: it consists of either (a) the operator / followed by zero or more operands separated by / or // operators, or (b) the operator // followed by one or more operands separated by / or // operators.]

[Definition: A relative path expression is a non-trivial instance of the production RelativePathExpr: it consists of two or more operand expressions separated by / or // operators.]

[Definition: The operands of a path expression are conventionally referred to as steps.]

Note:

The term step must not be confused with axis step. A step can be any kind of expression, often but not necessarily an axis step, while an axis step can be used in any expression context, not necessarily as a step in a path expression.

A path expression is typically used to locate GNodes within GTrees.

Note:

Note the terminology:

The following definitions are copied from the data model specification, for convenience:

  • [Definition: A tree that is rooted at a parentless JNode is referred to as a JTree.]

  • [Definition: A tree that is rooted at a parentless XNode is referred to as an XTree.]

  • [Definition: The term generic node or GNode is a collective term for XNodes (more commonly called simply nodes) representing the parts of an XML document, and JNodes, often used to represent the parts of a JSON document.]

    [Definition: The term GTree means JTree or XTree.]

  • [Definition: A JNode is a kind of item used to represent a value within the context of a tree of maps and arrays. A root JNode represents a map or array; a non-root JNode represents a member of an array or an entry in a map.]

[Definition: The term GTree means JTree or XTree.]

Absolute path expressions (those starting with an initial / or //), start their selection from the root GNode of a GTree; relative path expressions (those without a leading / or //) start from the context value.

4.7.5 Axis Steps

AxisStep::=(AbbreviatedStep | FullStep) Predicate*
AbbreviatedStep::=".." | ("@" NodeTest) | SimpleNodeTest
FullStep::=AxisNodeTest
Axis::=("ancestor" | "ancestor-or-self" | "attribute" | "child" | "descendant" | "descendant-or-self" | "following" | "following-or-self" | "following-sibling" | "following-sibling-or-self" | "namespace" | "parent" | "preceding" | "preceding-or-self" | "preceding-sibling" | "preceding-sibling-or-self" | "self") "::"
NodeTest::=UnionNodeTest | SimpleNodeTest
Predicate::="[" Expr "]"

[Definition: An axis step is an instance of the production AxisStep: it is an expression that returns a sequence of GNodes that are reachable from a starting GNode via a specified axis. An axis step has three parts: an axis, which defines the direction of movement for the step, a node test, which selects GNodes based on their properties, and zero or more predicates which are used to filter the results.]

Note:

An axis step is an expression in its own right. While axis steps are often used as the operands of path expressions, they can also appear in other contexts (without a / or // operator); equally, the operands of a path expression can be any expression, not restricted to an axis step.

If the context value for an axis step includes a map or array, this is implicitly converted to a JNode as if by applying the fn:jtree function. If, after this conversion, the sequence contains a value that is not a GNode, a type error is raised [err:XPTY0020]. The result of evaluating the axis step is a sequence of zero or more GNodes.

The axis stepS is equivalent to ./S. Thus, if the context value is a sequence containing multiple GNodes, the semantics of a axis step are equivalent to a path expression in which the step is always applied to a single GNode. The following description therefore explains the semantics for the case where the context value is a single GNode, called the origin.

Note:

The equivalence of a axis stepS to the path expression./S means that the resulting GNode sequence is returned in document order.

In the abbreviated syntax for a step, the axis can be omitted and other shorthand notations can be used as described in 4.7.8 Abbreviated Syntax.

The unabbreviated syntax for an axis step consists of the axis name and node test separated by a double colon. The result of the step consists of the GNodes reachable from the origin via the specified axis that match the node test. For example, the step child::para selects the para element children of the origin XNode: child is the name of the axis, and para is the name of the element nodes to be selected on this axis. The available axes are described in 4.7.5.1 Axes. The available node tests are described in 4.7.5.2 Node Tests. Examples of steps are provided in 4.7.7 Unabbreviated Syntax and 4.7.8 Abbreviated Syntax.

4.7.5.1 Axes

Changes in 4.0 (next | previous)

  1. Four new axes have been defined: preceding-or-self, preceding-sibling-or-self, following-or-self, and following-sibling-or-self.   [Issue 1519 PR 1532 29 October 2024]

Axis::=("ancestor" | "ancestor-or-self" | "attribute" | "child" | "descendant" | "descendant-or-self" | "following" | "following-or-self" | "following-sibling" | "following-sibling-or-self" | "namespace" | "parent" | "preceding" | "preceding-or-self" | "preceding-sibling" | "preceding-sibling-or-self" | "self") "::"

An axis is essentially a function that takes a GNode (the origin) as input, and delivers a sequence of GNodes (always from within the same GTree as the origin) as its result.

XPath defines a set of axes for traversing documents, but a host language may define a subset of these axes. The following axes are defined:

  • The child axis contains the children of the origin.

    If the origin is an XNode, these are the XNodes returned by the [XDM 4.0] section 7.6.3 children Accessor accessor.

    Note:

    In an XTree, only document nodes and element nodes have children. If the origin is any other kind of XNode, or if the origin is an empty document or element node, then the child axis returns anthe empty sequence. The children of a document node or element node may be element, processing instruction, comment, or text nodes. Attribute, namespace, and document nodes can never appear as children.

    If the origin is a JNode, these are the JNodes returned by the j-childrenDM accessor.

  • The descendant axis is defined as the transitive closure of the child axis; it contains the descendants of the origin (the children, the children of the children, and so on).

    More formally, $node/descendant::gnode() delivers the result of fn:transitive-closure($node, fn { child::gnode() }).

  • The descendant-or-self axis contains the origin and the descendants of the origin.

    More formally, $node/descendant-or-self::gnode() delivers the result of $node/(. | descendant::gnode()).

  • The parent axis returns the parent of the origin.

    If the origin is an XNode, this is the result of the [XDM 4.0] section 7.6.11 parent Accessor accessor.

    If the origin is a JNode, this is the value of the ·parent· property of the origin.

    If the GNode has no parent, the axis returns anthe empty sequence.

    Note:

    An attribute node may have an element node as its parent, even though the attribute node is not a child of the element node.

  • The ancestor axis is defined as the transitive closure of the parent axis; it contains the ancestors of the origin (the parent, the parent of the parent, and so on).

    More formally, $node/ancestor::gnode() delivers the result of fn:transitive-closure($node, fn { parent::gnode() }).

    Note:

    The ancestor axis includes the root GNode of the GTree in which the origin is found, unless the origin is itself the root GNode.

  • The ancestor-or-self axis contains the origin and the ancestors of the origin; thus, the ancestor-or-self axis will always include the root.

    More formally, $node/ancestor-or-self::gnode() delivers the result of $node/(. | ancestor::gnode()).

  • The following-sibling axis returns the origin’s following siblings, that is, those children of the origin’s parent that occur after the origin in document order. If the origin is an attribute or namespace node, the following-sibling axis is empty.

    More formally, $node/following-sibling::gnode() delivers the result of fn:siblings($node)[. >> $node]).

  • The following-sibling-or-self axis contains the origin, together with the contents of the following-sibling axis.

    More formally, $node/following-sibling-or-self::gnode() delivers the result of fn:siblings($node)[not(. << $node)]

  • The preceding-sibling axis returns the origin’s preceding siblings, that is, those children of the origin’s parent that occur before the context node in document order. If the origin is an attribute or namespace node, the preceding-sibling axis is empty.

    More formally, $node/preceding-sibling::gnode() delivers the result of fn:siblings($node)[. << $node].

  • The preceding-sibling-or-self axis contains the origin, together with the contents of the preceding-sibling axis.

    More formally, $node/preceding-sibling-or-self::gnode() delivers the result of fn:siblings($node)[not(. >> $node).

  • The following axis contains all descendants of the root of the GTree in which the origin is found, are not descendants of the origin, and occur after the origin in document order.

    More formally, $node/following::gnode() delivers the result of $node/ancestor-or-self::gnode()/following-sibling::gnode()/descendant-or-self::gnode()

  • The following-or-self axis contains the origin, together with the contents of the following axis.

    More formally, $node/following-or-self::gnode() delivers the result of $node/(. | following::gnode()).

  • The preceding axis returns all descendants of the root of the GTree in which the origin is found, are not ancestors of the origin, and occur before the origin in document order.

    More formally, $node/preceding::gnode() delivers the result of $node/ancestor-or-self::gnode()/preceding-sibling::gnode()/descendant-or-self::gnode().

  • The preceding-or-self axis returns the origin, together with the contents of the preceding axis.

    More formally, $node/preceding-or-self::gnode() delivers the result of $node/(. | preceding::gnode()).

  • The attribute axis is defined only for XNodes. It returns the attributes of the origin, which are the nodes returned by the [XDM 4.0] section 7.6.1 attributes Accessor; the axis will be empty unless the context node is an element.

    If the attribute axis is applied to a JNode, a type error [err:XPTY0004] is raised.

  • The self axis contains just the origin itself.

    The self axis is primarily useful when testing whether the origin satisfies particular conditions, for example if ($x[self::chapter]).

    More formally, $node/self::gnode() delivers the result of $node.

  • The namespace axis is defined only for XNodes. It returns the namespace nodes of the origin, which are the nodes returned by the [XDM 4.0] section 7.6.7 namespace-nodes Accessor; this axis is empty unless the origin is an element node. The namespace axis is deprecated as of XPath 2.0. If XPath 1.0 compatibility mode is true, the namespace axis must be supported. If XPath 1.0 compatibility mode is false, then support for the namespace axis is implementation-defined. An implementation that does not support the namespace axis when XPath 1.0 compatibility mode is false must raise a static error [err:XPST0010] if it is used. Applications needing information about the in-scope namespaces of an element should use the function fn:in-scope-namespaces.

    If the namespace axis is applied to a JNode, a type error [err:XPTY0004] is raised.

Axes can be categorized as forward axes and reverse axes. An axis that only ever contains the origin or nodes that are after the context node in document order is a forward axis. An axis that only ever contains the context node or nodes that are before the context node in document order is a reverse axis.

The parent, ancestor, ancestor-or-self, preceding, preceding-or-self, preceding-sibling, and preceding-sibling-or-self axes are reverse axes; all other axes are forward axes.

The ancestor, descendant, following, preceding and self axes partition a GTree (ignoring attribute and namespace nodes): they do not overlap and together they contain all the GNodes in the GTree.

[Definition: Every axis has a principal node kind. If an axis can contain elements, then the principal node kind is element; otherwise, it is the kind of nodes that the axis can contain.] Thus:

  • For the attribute axis, the principal node kind is attribute.

  • For the namespace axis, the principal node kind is namespace.

  • For all other axes, the principal node kind is element.

4.7.5.5 Type Tests

A type test is a node test that selects JNodes or XNodes based on their type.

TypeTest::=NodeKindTest | JNodeType
NodeKindTest::=DocumentTest
| ElementTest
| AttributeTest
| SchemaElementTest
| SchemaAttributeTest
| PITest
| CommentTest
| TextTest
| NamespaceNodeTest
| AnyNodeKindTest
DocumentTest::="document-node" "(" (ElementTest | SchemaElementTest | NameTestUnion)? ")"
ElementTest::="element" "(" (NameTestUnion ("," TypeName "?"?)?)? ")"
SchemaElementTest::="schema-element" "(" ElementName ")"
NameTestUnion::=(NameTest ++ "|")
NameTest::=EQName | Wildcard
EQName::=QName | URIQualifiedName
Wildcard::="*"
| (NCName ":*")
| ("*:" NCName)
| (BracedURILiteral "*")
/* ws: explicit */
AttributeTest::="attribute" "(" (NameTestUnion ("," TypeName)?)? ")"
SchemaAttributeTest::="schema-attribute" "(" AttributeName ")"
PITest::="processing-instruction" "(" (NCName | StringLiteral)? ")"
StringLiteral::=AposStringLiteral | QuotStringLiteral
/* ws: explicit */
CommentTest::="comment" "(" ")"
TextTest::="text" "(" ")"
NamespaceNodeTest::="namespace-node" "(" ")"
AnyNodeKindTest::="node" "(" ")"
JNodeType::="jnode" "(" (("*" | NCName | Constant) ("," ("*" | SequenceType))?)? ")"

For example:

  • element(N) (short for child::element(N)) selects elements named N.

  • attribute(*, xs:integer)selects attribute nodes whose type annotation is xs:integer.

  • text() selects text nodes.

  • jnode("id") selects JNodes having the ·selector· property "id".

  • jnode(*, map(*)) selects JNodes whose ·content· property is an instance of the type map(*).

The syntax and semantics of NodeKindTest and JNodeType are described in 3.1 Sequence Types and 3.1.2 Sequence Type Matching.

Shown below are further examples of type tests that might be used in path expressions selecting within an XTree:

  • node() matches any XNode.

  • text() matches any text node.

  • comment() matches any comment node.

  • namespace-node() matches any namespace node.

  • element() matches any element node.

  • schema-element(person) matches any element node whose name is person (or is in the substitution group headed by person), and whose type annotation is the same as (or is derived from) the declared type of the person element in the in-scope element declarations.

  • element(person) matches any element node whose name is person, regardless of its type annotation.

  • element(doctor|nurse) matches any element node whose name is doctor or nurse, regardless of its type annotation.

  • element(person, surgeon) matches any non-nilled element node whose name is person, and whose type annotation is surgeon or is derived from surgeon.

  • element(doctor|nurse, medical-staff) matches any non-nilled element node whose name is doctor or nurse, and whose type annotation is medical-staff or is derived from medical-staff.

  • element(*, surgeon) matches any non-nilled element node whose type annotation is surgeon (or is derived from surgeon), regardless of its name.

  • attribute() matches any attribute node.

  • attribute(price) matches any attribute whose name is price, regardless of its type annotation.

  • attribute(*, xs:decimal) matches any attribute whose type annotation is xs:decimal (or is derived from xs:decimal), regardless of its name.

  • document-node() matches any document node.

  • document-node(element(book)) matches any document node whose children consist of a single element node that satisfies the ElementTestelement(book), interleaved with zero or more comments and processing instructions, and no text nodes.

  • document-node(book) is an abbreviation for document-node(element(book)).

The following examples show type type tests that might be used in path expressions selecting within a JTree:

  • jnode(*, array(*)) matches any JNode whose ·content· is an array.

  • jnode(*, record(longitude, latitude, *)) matches any JNode whose ·content· is a map having entries with keys "longitude" and "latitude".

  • jnode(*, empty-sequence()) matches any JNode whose ·content· is anthe empty sequence.

  • jnode(*, xs:date) matches any JNode whose ·content· is an instance of xs:date.

4.7.5.6 Implausible Axis Steps

Changes in 4.0 (next | previous)

  1. The rules for reporting type errors during static analysis have been changed so that a processor has more freedom to report errors in respect of constructs that are evidently wrong, such as @price/@value, even though dynamic evaluation is defined to return anthe empty sequence rather than an error.   [Issue 602 PR 603 25 July 2023]

Certain axis steps, given an inferred type for the context value, are classified as implausible. During the static analysis phase, a processor may (subject to the rules in 2.5.6 Implausible Expressions) report a static error when such axis steps are encountered: [err:XPTY0144].

More specifically, an axis step is classified as implausible if any of the following conditions applies:

  1. The inferred item type of the context value is a node kind for which the specified axis is always empty: for example, the inferred item type of the context value is attribute() and the axis is child.

  2. The node test exclusively selects node kinds that cannot appear on the specified axis: for example, the axis is child and the node test is document-node().

  3. In a schema-aware environment, when using the child, descendant, descendant-or-self, or attribute axes, the inferred item type of the context value has a content type that does not allow any node matching the node test to be present on the relevant axis. For example, if the inferred item type of the context value is schema-element(list) and the relevant element declaration (taking into account substitution group membership and wildcards) only allows item children, the axis step child::li will never select anything and is therefore classified as implausible.

Examples of implausible axis steps include the following:

  • @code/text(): attributes cannot have text node children.

  • /@code: document nodes cannot have attributes.

  • ancestor::text(): the ancestor axis never returns text nodes.

  • element(*)/child::map: the child axis starting at an element node will never select a map.

Note:

Processors may choose not to classify the expression /.. as implausible, since XSLT 1.0 users were sometimes advised to use this construct as an explicit way of denoting the empty sequence.

4.7.7 Unabbreviated Syntax

This section provides a number of examples of path expressions in which the axis is explicitly specified in each step. The syntax used in these examples is called the unabbreviated syntax. In many common cases, it is possible to write path expressions more concisely using an abbreviated syntax, as explained in 4.7.8 Abbreviated Syntax.

These examples assume that the context value is a single node, referred to as the context node.

  • child::para selects the para element children of the context node.

  • child::(para|bullet) selects the para and bullet element children of the context node.

  • child::* selects all element children of the context node.

  • child::text() selects all text node children of the context node.

  • child::(text()|comment()) selects all text node and comment node children of the context node.

  • child::node() selects all the children of the context node. Note that no attribute nodes are returned, because attributes are not children.

  • attribute::name selects the name attribute of the context node.

  • attribute::* selects all the attributes of the context node.

  • parent::node() selects the parent of the context node. If the context node is an attribute node, this expression returns the element node (if any) to which the attribute node is attached.

  • descendant::para selects the para element descendants of the context node.

  • ancestor::div selects all div ancestors of the context node.

  • ancestor-or-self::div selects the div ancestors of the context node and, if the context node is a div element, the context node as well.

  • descendant-or-self::para selects the para element descendants of the context node and, if the context node is a para element, the context node as well.

  • self::para selects the context node if it is a para element, and otherwise returns anthe empty sequence.

  • self::(chapter|appendix) selects the context node if it is a chapter or appendix element, and otherwise returns anthe empty sequence.

  • child::chapter/descendant::para selects the para element descendants of the chapter element children of the context node.

  • child::*/child::para selects all para grandchildren of the context node.

  • / selects the root of the tree that contains the context node, but raises a dynamic error if this root is not a document node.

  • /descendant::para selects all the para elements in the same document as the context node.

  • /descendant::list/child::member selects all the member elements that have a list parent and that are in the same document as the context node.

  • child::para[position() = 1] selects the first para child of the context node.

  • child::para[position() = last()] selects the last para child of the context node.

  • child::para[position() = last()-1] selects the last but one para child of the context node.

  • child::para[position() > 1] selects all the para children of the context node other than the first para child of the context node.

  • following-sibling::chapter[position() = 1] selects the next chapter sibling of the context node.

  • following-sibling::(chapter|appendix)[position() = 1] selects the next sibling of the context node that is either a chapter or an appendix.

  • preceding-sibling::chapter[position() = 1] selects the previous chapter sibling of the context node.

  • /descendant::figure[position() = 42] selects the forty-second figure element in the document containing the context node.

  • /child::book/child::chapter[position() = 5]/child::section[position() = 2] selects the second section of the fifth chapter of the book whose parent is the document node that contains the context node.

  • child::para[attribute::type eq "warning"] selects all para children of the context node that have a type attribute with value warning.

  • child::para[attribute::type eq 'warning'][position() = 5] selects the fifth para child of the context node that has a type attribute with value warning.

  • child::para[position() = 5][attribute::type eq "warning"] selects the fifth para child of the context node if that child has a type attribute with value warning.

  • child::chapter[child::title = 'Introduction'] selects the chapter children of the context node that have one or more title children whose typed value is equal to the string Introduction.

  • child::chapter[child::title] selects the chapter children of the context node that have one or more title children.

  • child::*[self::chapter or self::appendix] selects the chapter and appendix children of the context node.

  • child::*[self::(chapter|appendix)][position() = last()] selects the last chapter or appendix child of the context node.

4.7.8 Abbreviated Syntax

AbbreviatedStep::=".." | ("@" NodeTest) | SimpleNodeTest
NodeTest::=UnionNodeTest | SimpleNodeTest
SimpleNodeTest::=TypeTest | Selector
TypeTest::=NodeKindTest | JNodeType
Selector::=EQName | Wildcard | ("get" "(" ExprSingle ")")
EQName::=QName | URIQualifiedName
Wildcard::="*"
| (NCName ":*")
| ("*:" NCName)
| (BracedURILiteral "*")
/* ws: explicit */
ExprSingle::=ForExpr
| LetExpr
| QuantifiedExpr
| IfExpr
| OrExpr

The abbreviated syntax for a step permits the following abbreviations:

  1. The attribute axis attribute:: can be abbreviated by @. For example, the expression para[@type = "warning"] is short for child::para[attribute::type = "warning"] and so selects para children with a type attribute with value equal to warning.

  2. If the axis name is omitted from an axis step, the default axis is child, with two exceptions: (1) if the NodeTest in an axis step contains an AttributeTest or SchemaAttributeTest then the default axis is attribute; (2) if the NodeTest in an axis step is a NamespaceNodeTestthen the default axis is namespace, but in an implementation that does not support the namespace axis, an error is raised [err:XQST0134].

    Note:

    The namespace axis is deprecated as of XPath 2.0, but is required in some languages that use XPath, including XSLT.

    For example, the path expression section/para is an abbreviation for child::section/child::para, and the path expression section/@id is an abbreviation for child::section/attribute::id. Similarly, section/attribute(id) is an abbreviation for child::section/attribute::attribute(id). Note that the latter expression contains both an axis specification and a node test.

    Similarly, within a JTree rooted at an array, the expression get(1)/parts/get(2)/part-no gets the first member of the top-level array (presumably a map), then the "parts" entry within this map (presumably an array), then the second member of this array (presumably a map), and finally the part-no entry within this map.

    Note:

    The same selection could be made using the lookup expression ?1?parts?2?part-no. The main difference is that path expressions offer more flexibility in being able to navigate around the containing JTree. Also, the lookup expression $a?1 fails if the array index is out of bounds; the path expression $a/get(1) (or $a/*[1]) instead returns anthe empty sequence.

    Note:

    An abbreviated axis step that omits the axis name must use a SimpleNodeTest rather than a UnionNodeTest. This means that a construct such as (ul|ol) is treated as an abbreviation for (child::ul|child::ol) rather than child::(ul|ol). Since the two constructs have exactly the same semantics, this is not actually a restriction.

  3. A step consisting of .. is short for parent::gnode(). For example (assuming the context item is an XNode), ../title is short for parent::gnode()/child::title and so will select the title children of the parent of the context node.

    Similarly, if $dateOfBirth is a JNode resulting from the expression $map/get("date of birth"), then $dateOfBirth/../gender will select the entry having key "gender" within $map.

    Note:

    The expression ., known as a context value reference, is a primary expression, and is described in 4.3.3 Context Value References.

Here are some examples of path expressions that use the abbreviated syntax. These examples assume that the context value is a single XNode, referred to as the context node:

  • para selects the para element children of the context node.

  • * selects all element children of the context node.

  • text() selects all text node children of the context node.

  • @name selects the name attribute of the context node.

  • @(id|name) selects the id and name attributes of the context node.

  • @* selects all the attributes of the context node.

  • para[1] selects the first para child of the context node.

  • para[last()] selects the last para child of the context node.

  • */para selects all para grandchildren of the context node.

  • /book/chapter[5]/section[2] selects the second section of the fifth chapter of the book whose parent is the document node that contains the context node.

  • chapter//para selects the para element descendants of the chapter element children of the context node.

  • //para selects all the para descendants of the root document node and thus selects all para elements in the same document as the context node.

  • //@version selects all the version attribute nodes that are in the same document as the context node.

  • //list/member selects all the member elements in the same document as the context node that have a list parent.

  • .//para selects the para element descendants of the context node.

  • .. selects the parent of the context node.

  • ../@lang selects the lang attribute of the parent of the context node.

  • para[@type = "warning"] selects all para children of the context node that have a type attribute with value warning.

  • para[@type = "warning"][5] selects the fifth para child of the context node that has a type attribute with value warning.

  • para[5][@type = "warning"] selects the fifth para child of the context node if that child has a type attribute with value warning.

  • chapter[title = "Introduction"] selects the chapter children of the context node that have one or more title children whose typed value is equal to the string Introduction.

  • chapter[title] selects the chapter children of the context node that have one or more title children.

  • employee[@secretary and @assistant] selects all the employee children of the context node that have both a secretary attribute and an assistant attribute.

  • book/(chapter|appendix)/section selects every section element that has a parent that is either a chapter or an appendix element, that in turn is a child of a book element that is a child of the context node.

  • If E is any expression that returns a sequence of nodes, then the expression E/. returns the same nodes in document order, with duplicates eliminated based on node identity.

The following examples use abbreviated paths to access data within the JTree obtained by parsing the JSON text:

[
  { "first": "John", 
    "last": "Baker", 
    "date of birth": "2003-04-19", 
    "occupation": "cook"}, 
  { "first": "Mary", 
    "last": "Smith", 
    "date of birth": "2006-08-12", 
    "occupation": "teacher"},                 
]
  • get(1)/first returns a JNode whose ·content· is the string "John".

  • //first[. = "Mary"]/../last returns a JNode whose ·content· is the string "Smith".

  • //first[. = "Mary"]/../get("date of birth") returns a JNode whose ·content· is the string "2006-08-12".

  • //*[occupation = "cook"]!`{first} {last}` returns the string "John Baker".

  • //*[occupation = "cook"]/following-sibling::*[1]!`{first} {last}` returns the string "Mary Smith".

  • //*[last = "Smith"]/../get(1)/last returns the string "Baker".

  • //record(first, last, *) ! string(last) returns the sequence of two strings "Baker", "Smith".

4.8 Sequence Expressions

XPath 4.0 supports operators to construct, filter, and combine sequences of items. Sequences are never nested—for example, combining the values 1, (2, 3), and ( ) into a single sequence results in the sequence (1, 2, 3).

4.8.1 Sequence Concatenation

Expr::=(ExprSingle ++ ",")
ExprSingle::=ForExpr
| LetExpr
| QuantifiedExpr
| IfExpr
| OrExpr

[Definition: A sequence expression is a non-trivial instance of the production rule Expr, that is, an expression containing two or more instances of the production ExprSingle separated by the comma operator.]

The result of a sequence expression is the sequence concatenation of the values of its operands. See

[Definition: A comma operator is a comma used specifically as the operator in a sequence expression.]

Empty parentheses can be used to denote anthe empty sequence.

A sequence may contain duplicate items, but a sequence is never an item in another sequence. When a new sequence is created by concatenating two or more input sequences, the new sequence contains all the items of the input sequences and its length is the sum of the lengths of the input sequences.

[Definition: The sequence concatenation of a number of sequences S1, S2, ... Sn is defined to be the sequence formed from the items of S1, followed by the items from S2, and so on, retaining order.] The comma operator returns the sequence concatenation of its two operands; repeated application (for example $s1, $s2, $s3, $s4) delivers the sequence concatenation of multiple sequences.

Note:

In places where the grammar calls for ExprSingle, such as the arguments of a function call, any expression that contains a top-level comma operator must be enclosed in parentheses.

Here are some examples of expressions that construct sequences:

  • The result of this expression is a sequence of five integers:

    (10, 1, 2, 3, 4)
  • This expression combines four sequences of length one, two, zero, and two, respectively, into a single sequence of length five. The result of this expression is the sequence 10, 1, 2, 3, 4.

    (10, (1, 2), (), (3, 4))
  • The result of this expression is a sequence containing all salary children of the context node followed by all bonus children.

    (salary, bonus)
  • Assuming that $price is bound to the value 10.50, the result of this expression is the sequence 10.50, 10.50.

    ($price, $price)

4.8.2 Range Expressions

RangeExpr::=AdditiveExpr ("to" AdditiveExpr)?
AdditiveExpr::=MultiplicativeExpr (("+" | "-") MultiplicativeExpr)*

[Definition: A range expression is a non-trivial instance of the production RangeExpr. A range expression is used to construct a sequence of integers.] Each of the operands is converted as though it was an argument of a function with the expected parameter type xs:integer?. If either operand is anthe empty sequence, or if the integer derived from the first operand is greater than the integer derived from the second operand, the result of the range expression is anthe empty sequence. If the two operands convert to the same integer, the result of the range expression is that integer. Otherwise, the result is a sequence containing the two integer operands and every integer between the two operands, in increasing order.

The following examples illustrate the semantics:

  • 1 to 4 returns the sequence 1, 2, 3, 4

  • 10 to 10 returns the singleton sequence 10

  • 10 to 1 returns the empty sequence

  • -13 to -10 returns the sequence -13, -12, -11, -10

More formally, a range expression is evaluated as follows:

  1. Each of the operands of the to operator is converted as though it was an argument of a function with the expected parameter type xs:integer?.

  2. If either operand is anthe empty sequence, or if the integer derived from the first operand is greater than the integer derived from the second operand, the result of the range expression is anthe empty sequence.

  3. If the two operands convert to the same integer, the result of the range expression is that integer.

  4. Otherwise, the result is a sequence containing the two integer operands and every integer between the two operands, in increasing order.

The following examples illustrate the use of range expressions.

This example uses a range expression as one operand in constructing a sequence. It evaluates to the sequence 10, 1, 2, 3, 4.

(10, 1 to 4)

This example selects the first four items from an input sequence:

$input[1 to 4]

This example returns the sequence (0, 0.1, 0.2, 0.3, 0.5):

$x = (1 to 5) ! . * 0.1

This example constructs a sequence of length one containing the single integer 10.

10 to 10

The result of this example is a sequence of length zero.

15 to 10

This example uses the fn:reverse function to construct a sequence of six integers in decreasing order. It evaluates to the sequence 15, 14, 13, 12, 11, 10.

reverse(10 to 15)

Note:

To construct a sequence of integers based on steps other than 1, use the fn:slice function, as defined in 14.1 General functions and operators on sequences FO31.

4.9 Arithmetic Expressions

Changes in 4.0 (next | previous)

  1. The symbols × and ÷ can be used for multiplication and division.

XPath 4.0 provides binary arithmetic operators for addition, subtraction, multiplication, division, and modulus:

AdditiveExpr::=MultiplicativeExpr (("+" | "-") MultiplicativeExpr)*
MultiplicativeExpr::=UnionExpr (("*" | "×" | "div" | "÷" | "idiv" | "mod") UnionExpr)*
UnionExpr::=IntersectExceptExpr (("union" | "|") IntersectExceptExpr)*

In addition, unary operators are provided for addition and subtraction:

UnaryExpr::=("-" | "+")* ValueExpr
ValueExpr::=SimpleMapExpr
SimpleMapExpr::=PathExpr ("!" PathExpr)*

A subtraction operator must be preceded by whitespace if it could otherwise be interpreted as part of the previous token. For example, a-b will be interpreted as a name, but a - b and a -b will be interpreted as arithmetic expressions. (See A.3.4 Whitespace Rules for further details on whitespace handling.)

The arithmetic operator symbols * and U+00D7 (MULTIPLICATION SIGN, ×) are interchangeable, and denote multiplication.

The arithmetic operator symbols div and U+00F7 (DIVISION SIGN, ÷) are interchangeable, and denote division.

If an AdditiveExpr contains more than two MultiplicativeExprs, they are grouped from left to right. So, for instance,

A - B + C - D

is equivalent to

((A - B) + C) - D

Similarly, the operands of a MultiplicativeExpr are grouped from left to right.

The first step in evaluating an arithmetic expression is to evaluate its operand (for a unary operator) or operands (for a binary operator). The order in which the operands are evaluated is implementation-dependent.

If XPath 1.0 compatibility mode is true, each operand is evaluated by applying the following steps, in order:

  1. Atomization is applied to the operand. The result of this operation is called the atomized operand.

  2. If the atomized operand is anthe empty sequence, the result of the arithmetic expression is the xs:double value NaN, and the implementation need not evaluate the other operand or apply the operator. However, an implementation may choose to evaluate the other operand in order to determine whether it raises an error.

  3. If the atomized operand is a sequence of length greater than one, any items after the first item in the sequence are discarded.

  4. If the atomized operand is now an instance of type xs:boolean, xs:string, xs:decimal (including xs:integer), xs:float, or xs:untypedAtomic, then it is converted to the type xs:double by applying the fn:number function. (Note that fn:number returns the value NaN if its operand cannot be converted to a number.)

If XPath 1.0 compatibility mode is false, each operand is evaluated by applying the following steps, in order:

  1. Atomization is applied to the operand. The result of this operation is called the atomized operand.

  2. If the atomized operand is anthe empty sequence, the result of the arithmetic expression is anthe empty sequence, and the implementation need not evaluate the other operand or apply the operator. However, an implementation may choose to evaluate the other operand in order to determine whether it raises an error.

  3. If the atomized operand is a sequence of length greater than one, a type error is raised [err:XPTY0004].

  4. If the atomized operand is of type xs:untypedAtomic, it is cast to xs:double. If the cast fails, a dynamic error is raised. [err:FORG0001]FO40

If, after this process, both operands of a binary arithmetic operator are instances of xs:numeric but have different primitive types, they are coerced to a common type by applying the following rules:

  1. If either of the items is of type xs:double, then both the values are cast to type xs:double.

  2. Otherwise, if either of the items is of type xs:float, then both the values are cast to type xs:float.

  3. Otherwise, no casting takes place: the values remain as xs:decimal.

After this preparation, the arithmetic expression is evaluated by applying the appropriate function listed in the table below. The definitions of these functions are found in [Functions and Operators 4.0].

Unary Arithmetic Operators
ExpressionType of AFunctionResult type
+ Axs:numericop:numeric-unary-plus(A)xs:numeric
- Axs:numericop:numeric-unary-minus(A)xs:numeric
Binary Arithmetic Operators
ExpressionType of AType of BFunctionResult type
A + Bxs:numericxs:numericop:numeric-add(A, B)xs:numeric
A + Bxs:datexs:yearMonthDurationop:add-yearMonthDuration-to-date(A, B)xs:date
A + Bxs:yearMonthDurationxs:dateop:add-yearMonthDuration-to-date(B, A)xs:date
A + Bxs:datexs:dayTimeDurationop:add-dayTimeDuration-to-date(A, B)xs:date
A + Bxs:dayTimeDurationxs:dateop:add-dayTimeDuration-to-date(B, A)xs:date
A + Bxs:timexs:dayTimeDurationop:add-dayTimeDuration-to-time(A, B)xs:time
A + Bxs:dayTimeDurationxs:timeop:add-dayTimeDuration-to-time(B, A)xs:time
A + Bxs:dateTimexs:yearMonthDurationop:add-yearMonthDuration-to-dateTime(A, B)xs:dateTime
A + Bxs:yearMonthDurationxs:dateTimeop:add-yearMonthDuration-to-dateTime(B, A)xs:dateTime
A + Bxs:dateTimexs:dayTimeDurationop:add-dayTimeDuration-to-dateTime(A, B)xs:dateTime
A + Bxs:dayTimeDurationxs:dateTimeop:add-dayTimeDuration-to-dateTime(B, A)xs:dateTime
A + Bxs:yearMonthDurationxs:yearMonthDurationop:add-yearMonthDurations(A, B)xs:yearMonthDuration
A + Bxs:dayTimeDurationxs:dayTimeDurationop:add-dayTimeDurations(A, B)xs:dayTimeDuration
A - Bxs:numericxs:numericop:numeric-subtract(A, B)xs:numeric
A - Bxs:datexs:dateop:subtract-dates(A, B)xs:dayTimeDuration
A - Bxs:datexs:yearMonthDurationop:subtract-yearMonthDuration-from-date(A, B)xs:date
A - Bxs:datexs:dayTimeDurationop:subtract-dayTimeDuration-from-date(A, B)xs:date
A - Bxs:timexs:timeop:subtract-times(A, B)xs:dayTimeDuration
A - Bxs:timexs:dayTimeDurationop:subtract-dayTimeDuration-from-time(A, B)xs:time
A - Bxs:dateTimexs:dateTimeop:subtract-dateTimes(A, B)xs:dayTimeDuration
A - Bxs:dateTimexs:yearMonthDurationop:subtract-yearMonthDuration-from-dateTime(A, B)xs:dateTime
A - Bxs:dateTimexs:dayTimeDurationop:subtract-dayTimeDuration-from-dateTime(A, B)xs:dateTime
A - Bxs:yearMonthDurationxs:yearMonthDurationop:subtract-yearMonthDurations(A, B)xs:yearMonthDuration
A - Bxs:dayTimeDurationxs:dayTimeDurationop:subtract-dayTimeDurations(A, B)xs:dayTimeDuration
A * Bxs:numericxs:numericop:numeric-multiply(A, B)xs:numeric
A * Bxs:yearMonthDurationxs:numericop:multiply-yearMonthDuration(A, B)xs:yearMonthDuration
A * Bxs:numericxs:yearMonthDurationop:multiply-yearMonthDuration(B, A)xs:yearMonthDuration
A * Bxs:dayTimeDurationxs:numericop:multiply-dayTimeDuration(A, B)xs:dayTimeDuration
A * Bxs:numericxs:dayTimeDurationop:multiply-dayTimeDuration(B, A)xs:dayTimeDuration
A idiv Bxs:numericxs:numericop:numeric-integer-divide(A, B)xs:integer
A div Bxs:numericxs:numericop:numeric-divide(A, B)numeric; but xs:decimal if both operands are xs:integer
A div Bxs:yearMonthDurationxs:numericop:divide-yearMonthDuration(A, B)xs:yearMonthDuration
A div Bxs:dayTimeDurationxs:numericop:divide-dayTimeDuration(A, B)xs:dayTimeDuration
A div Bxs:yearMonthDurationxs:yearMonthDurationop:divide-yearMonthDuration-by-yearMonthDuration(A, B)xs:decimal
A div Bxs:dayTimeDurationxs:dayTimeDurationop:divide-dayTimeDuration-by-dayTimeDuration(A, B)xs:decimal
A mod Bxs:numericxs:numericop:numeric-mod(A, B)xs:numeric

Note:

The operator symbol × is a synonym of *, while ÷ is a synonym of div.

If there is no entry in the table for the combination of operator and operands, then a type error is raised [err:XPTY0004].

Errors may also occur during coercion of the operands, or during evaluation of the identified function (for example, an error might result from dividing by zero).

Note:

XPath 4.0 provides three division operators:

Here are some examples of arithmetic expressions:

  • The first expression below returns the xs:decimal value -1.5, and the second expression returns the xs:integer value -1:

    -3 div 2
    -3 idiv 2
  • Subtraction of two date values results in a value of type xs:dayTimeDuration:

    $emp/hiredate - $emp/birthdate
  • This example illustrates the difference between a subtraction operator and a hyphen:

    $unit-price - $unit-discount
  • Unary operators have higher precedence than binary operators (other than !, /, and []), subject of course to the use of parentheses. Therefore, the following two examples have different meanings:

    -$bellcost + $whistlecost
    -($bellcost + $whistlecost)

Note:

Multiple consecutive unary arithmetic operators are permitted (though not useful).

Note:

Negation is not the same as subtraction from zero: if $x is positive zero, then -$x returns negative zero, wheras 0 - $x returns positive zero.

4.10 String Expressions

This section describes several ways of constructing strings.

4.10.2 String Templates

Changes in 4.0 (next | previous)

  1. String templates provide a new way of constructing strings: for example `{$greeting}, {$planet}!` is equivalent to $greeting || ', ' || $planet || '!'  [Issue 58 PR 324 29 January 2023]

StringTemplate::="`" (StringTemplateFixedPart | StringTemplateVariablePart)* "`"
/* ws: explicit */
StringTemplateFixedPart::=((Char - ('{' | '}' | '`')) | "{{" | "}}" | "``")+
/* ws: explicit */
Char::=[http://www.w3.org/TR/REC-xml#NT-Char]XML
/* xgc: xml-version */
StringTemplateVariablePart::=EnclosedExpr
EnclosedExpr::="{" Expr? "}"

String templates provide an alternative way of constructing strings. For example, the expression `Pi is { round(math:pi(), 4) }` returns the string "Pi is 3.1416".

A string template starts and ends with U+0060 (GRAVE ACCENT, BACKTICK, `) , popularly known as a back-tick. Between the back-ticks is a string consisting of an sequence of fixed parts and variable parts:

  • A variable part consists of an optional XPath expression enclosed in curly brackets ({}): more specifically, a string conforming to the XPath production Expr?.

    Note:

    An expression within a variable part may contain an unescaped U+007B (LEFT CURLY BRACKET, {) or U+007D (RIGHT CURLY BRACKET, }) within a StringLiteral or within a comment.

    The fact that the expression is optional means that the string contained between the curly brackets may be zero-length, may comprise whitespace only, or may contain XPath comments. The effective value in this case is a zero-length string, which is equivalent to omitting the variable part entirely, together with its curly-bracket delimiters.

  • A fixed part may contain any characters, except that:

    • The character U+007B (LEFT CURLY BRACKET, {) must be written as {{.

    • The character U+007D (RIGHT CURLY BRACKET, }) must be written as }}.

    • The character U+0060 (GRAVE ACCENT, BACKTICK, `) must be written as ``.

    Following the principles of the “longest token” rule, any occurrence of {{ within the fixed part is interpreted as an escaped left curly bracket. This means that the enclosed expression must not start with U+007B (LEFT CURLY BRACKET, {) : if this is required, the two left curly brackets can be separated by whitespace. For example the string template `{{"key":"{ {1:"yes", 0:"no"}?$condition}"}}` evaluates to the string {"key":"yes"} or {"key":"no"} depending on the value of $condition.

    By contrast, if the enclosed expression ends with U+007D (RIGHT CURLY BRACKET, }) , this can be immediately followed by the closing U+007D (RIGHT CURLY BRACKET, }) delimiter without intervening whitespace.

The result of evaluating a string template is the string obtained by concatenating the expansions of the fixed and variable parts:

  • The expansion of a fixed part is obtained by replacing any double curly brackets ({{ or }}) by the corresponding single curly bracket, and replacing doubled back-ticks (``) by a single back-tick.

  • The expansion of a variable part containing an expression is as follows:

    1. Atomization is applied to the value of the enclosed expression, converting it to a sequence of atomic items.

    2. If the result of atomization is anthe empty sequence, the result is the zero-length string. Otherwise, each atomic item in the atomized sequence is cast into a string.

    3. The individual strings resulting from the previous step are merged into a single string by concatenating them with a single space character between each pair.

  • The expansion of anthe empty variable part (one that contains no expression) is a zero-length string.

For example:

let $greeting := "Hello", $planet := "Mars"
return `{ $greeting }, { $planet }!`

returns "Hello, Mars!".

The expression:

let $long-months := (1, 3, 5, 7, 8, 10, 12)
return `The months with 31 days are: { $long-months }.`

returns "The months with 31 days are: 1 3 5 7 8 10 12.".

Note:

The rules for processing an enclosed expression are identical to the rules for attributes in XQuery direct element constructors. These rules differ slightly from the rules in XSLT attribute value templates, where adjacent text nodes are concatenated with no separator, prior to atomization.

Note:

A string template containing no variable parts is effectively just another way of writing a string literal: "Goethe", 'Goethe', and `Goethe` are interchangeable. This means that back-ticks can sometimes be a useful way of delimiting a string that contains both single and double quotes: `He said: "I didn't."`.

It is sometimes useful to use string templates in conjunction with the fn:char function to build strings containing special characters, for example `Chapter{ fn:char("nbsp") }{ $chapNr }`.

Note:

String literals containing an ampersand behave differently between XPath and XQuery: in XPath (unless first expanded by an XML parser) the string literal "Bacon & Eggs" represents a string containing an ampersand, while in XQuery it is an error, because an ampersand is taken as introducing a character reference. This difference does not arise for string templates, since neither XPath nor XQuery recognizes entity or character references in a string template. This means that back-tick delimited strings (such as `Bacon & Eggs`) may be useful in contexts where an XPath expression is required to have the same effect whether it is evaluated using an XPath or an XQuery processor.

In XQuery, the token ``[ is recognized as the start of a StringConstructor, under the “longest token” rule (see A.3 Lexical structure). This means that the construct ``[1] is not recognized as a StringTemplate followed by a predicate. Although the token ``[ is not used in XPath, it is reserved for compatibility reasons, and must be rejected as syntactically invalid. In the unlikely event that an empty StringTemplate followed by a predicate is wanted, whitespace or parentheses can be used to avoid the tokenization problem.

4.11 Comparison Expressions

Comparison expressions allow two values to be compared. XPath 4.0 provides three kinds of comparison expressions, called value comparisons, general comparisons, and GNode comparisons.

ComparisonExpr::=OtherwiseExpr ((ValueComp | GeneralComp | NodeComp) OtherwiseExpr)?
OtherwiseExpr::=StringConcatExpr ("otherwise" StringConcatExpr)*
ValueComp::="eq" | "ne" | "lt" | "le" | "gt" | "ge"
GeneralComp::="=" | "!=" | "<" | "<=" | ">" | ">="
NodeComp::="is" | "is-not" | NodePrecedes | NodeFollows | "precedes-or-is" | "follows-or-is"
NodePrecedes::="<<" | "precedes"
NodeFollows::=">>" | "follows"

Note:

When an XPath expression is written within an XML document, the XML escaping rules for special characters must be followed; thus < must be written as &lt;.

For a summary of the differences between different ways of comparing atomic items in XPath 4.0, see G Atomic Comparisons: An Overview.

4.11.1 Value Comparisons

Changes in 4.0 (next | previous)

  1. The rules for value comparisons when comparing values of different types (for example, decimal and double) have changed to be transitive. A decimal value is no longer converted to double, instead the double is converted to a decimal without loss of precision. This may affect compatibility in edge cases involving comparison of values that are numerically very close.   [Issue 986 PR 2218 29 September 2025]

  2. An ordering is now defined for all data types.   [Issue 2216 PR 2256 1 December 2025]

The value comparison operators are eq, ne, lt, le, gt, and ge. Value comparisons are used for comparing single atomic items.

The first step in evaluating a value comparison is to evaluate its operands. The order in which the operands are evaluated is implementation-dependent. Each operand is evaluated by applying the following steps, in order:

  1. Atomization is applied to each operand. The result of this operation is called the atomized operand.

  2. If either or both of the atomized operands is anthe empty sequence, the result of the value comparison is anthe empty sequence, and the implementation need not evaluate the other operand or apply the operator. However, an implementation may choose to evaluate the other operand and may raise an error if evaluation fails.

  3. If an atomized operand is a sequence of length greater than one, a type error is raised [err:XPTY0004].

  4. If both operands are instances of xs:numeric, and if either or both of the atomized operands is NaN, then the result is false if the operator is eq, lt, gt, le, or ge, but true if the operator is ne.

    Note:

    When an operand is NaN, the effect of a value comparison expression differs from the result of the fn:compare function.

  5. The function fn:compare is then called, supplying the two atomized operands as the first two arguments. The collation used by fn:compare is the default collation from the static context, and the implicit timezone used by the function is the implicit timezone from the dynamic context.

    Note:

    The effect of this rule is that xs:untypedAtomic values (which typically result from atomizing a node) are treated as strings.

  6. If fn:compare raises an error (typically because the two operands belong to different type familiesDM), then the value comparison fails with that error.

  7. The result of the fn:compare function determines the result of the value comparison, according to the following table:

    Result of a Value Comparison
    Result of fn:compareeqneltlegtge
    -1falsetruetruetruefalsefalse
    0truefalsefalsetruefalsetrue
    +1falsetruefalsefalsetruetrue

Here are some examples of value comparisons:

  • The following comparison atomizes the node(s) that are returned by the expression $book/author. The comparison is true only if the result of atomization is the value "Kennedy" as an instance of xs:string or xs:untypedAtomic. If the result of atomization is anthe empty sequence, the result of the comparison is anthe empty sequence. If the result of atomization is a sequence containing more than one value, a type error is raised [err:XPTY0004].

    $book1/author eq "Kennedy"
  • The following comparison is true because atomization converts an array to its member sequence:

    [ "Kennedy" ] eq "Kennedy"
  • The following path expression contains a predicate that selects products whose weight is greater than 100. For any product that does not have a weight subelement, the value of the predicate is the empty sequence, and the product is not selected. This example assumes that weight is a validated element with a numeric type.

    //product[weight gt 100]
  • The following comparison is true if my:hatsize and my:shoesize are both user-defined types that are derived by restriction from a primitive numeric type:

    my:hatsize(5) eq my:shoesize(5)
  • The following comparison is true. The eq operator compares two QNames by performing codepoint-comparisons of their namespace URIs and their local names, ignoring their namespace prefixes.

    QName("http://example.com/ns1", "this:color") eq
    QName("http://example.com/ns1", "that:color")
  • The following comparison is false. The xs:double value 1.1e0 is converted to type xs:decimal, giving the result 1.100000000000000088817841970012523233890533447265625, which is not equal to the xs:decimal value 1.1.

    1.1 eq 1.1e0

    Note:

    This is incompatible with previous versions, which converted both operands to xs:double before comparing them. This change has been made because there are contexts (such as sorting and grouping) where it is important that comparison results should be transitive, and this was not previously the case.

4.11.3 GNode Comparisons

Changes in 4.0 (next | previous)

  1. Operator is-not is introduced, as a complement to the operator is.   [ PR 2130 28 July 2025]

  2. Operators precedes and follows are introduced as synonyms for operators << and >>.   [ PR 2130 28 July 2025]

  3. Operators precedes-or-is and follows-or-is are introduced as synonyms for the union of operators << and is and for the union of operators >> and is, respectively.   [ PR 2176 22 August 2025]

GNode comparisons are used to compare two GNodes (that is, XNodes or JNodesDM), by their identity or by their document order. The result of a GNode comparison is defined by the following rules:

  1. The operands of a GNode comparison are evaluated in implementation-dependent order.

  2. If either operand is anthe empty sequence, the result of the comparison is anthe empty sequence, and the implementation need not evaluate the other operand or apply the operator. However, an implementation may choose to evaluate the other operand in order to determine whether it raises an error.

  3. Each operand must be either a single GNode or anthe empty sequence; otherwise a type error is raised [err:XPTY0004].

  4. A comparison with the is operator is true if the values of two operands are the same GNode; otherwise it is false. See [XDM 4.0] for the definition of GNode identity.

  5. A comparison with the is-not operator is false if the values of two operands are the same GNode; otherwise it is true. See [XDM 4.0] for the definition of GNode identity.

  6. A comparison with the << or precedes operator returns true if the left operand GNode precedes the right operand GNode in document order; otherwise it returns false.

  7. A comparison with the >> or follows operator returns true if the left operand GNode follows the right operand GNode in document order; otherwise it returns false.

  8. A comparison with the precedes-or-is operator returns true if the left operand GNode precedes the right operand GNode in document order or if the values of two operands are the same GNode; otherwise it returns false.

  9. A comparison with the follows-or-is operator returns true if the left operand GNode follows the right operand GNode in document order or if the values of two operands are the same GNode; otherwise it returns false.

Here are some examples of GNode comparisons:

  • The following comparison is true only if the left and right sides each evaluate to exactly the same single node:

    /books/book[isbn = "1558604820"] is /books/book[call = "QA76.9 C3845"]
  • The following comparison is true only if the node identified by the left side occurs before the node identified by the right side in document order:

    /transactions/purchase[parcel = "28-451"] << /transactions/sale[parcel = "33-870"]
  • The following comparison is true only if the first integer among the members of an array precedes the first string. This expression compares two JNodes:

    let $A := ["Q", 3, "E", "R", "T", 5, "Y"]
    return $A ? child::type(xs:integer)[1] precedes $A ? child::type(xs:string)[1]

4.13 For and Let Expressions

XPath provides two closely-related expressions, called For and Let expressions, that can be used to bind variables to values. These are described in the following sections.

4.13.2 Let Expressions

Changes in 4.0 (next | previous)

  1. Multiple for and let clauses can be combined in an expression without an intervening return keyword.   [Issue 22 PR 28 18 December 2020]

  2. The type of a variable used in a let expression can be declared.   [Issue 796 PR 1131 1 April 2024]

  3. Sequences, arrays, and maps can be destructured in a let expression to extract their components into multiple variables.   [Issue 37 PR 2055 17 June 2025]

XPath allows a variable to be declared and bound to a value using a let expression.

LetExpr::=LetClauseForLetReturn
LetClause::="let" (LetBinding ++ ",")
LetBinding::=LetValueBinding | LetSequenceBinding | LetArrayBinding | LetMapBinding
LetValueBinding::=VarNameAndType ":=" ExprSingle
VarNameAndType::="$" EQNameTypeDeclaration?
EQName::=QName | URIQualifiedName
TypeDeclaration::="as" SequenceType
ExprSingle::=ForExpr
| LetExpr
| QuantifiedExpr
| IfExpr
| OrExpr
LetSequenceBinding::="$" "(" (VarNameAndType ++ ",") ")" TypeDeclaration? ":=" ExprSingle
SequenceType::=("empty-sequence" "(" ")")
| (ItemTypeOccurrenceIndicator?)
LetArrayBinding::="$" "[" (VarNameAndType ++ ",") "]" TypeDeclaration? ":=" ExprSingle
LetMapBinding::="$" "{" (VarNameAndType ++ ",") "}" TypeDeclaration? ":=" ExprSingle
ForLetReturn::=ForExpr | LetExpr | ("return" ExprSingle)
ForExpr::=ForClauseForLetReturn

A let expression is evaluated as follows:

  1. If the let expression uses multiple variables, it is first expanded to a set of nested let expressions, each of which uses only one variable. Specifically, any separating comma is replaced by let.

    Example:

    The expression:

    let $x := 4, $y := 3 return $x + $y

    is expanded to:

    let $x := 4 let $y := 3 return $x + $y
  2. In a LetValueBinding such as let $V as T := EXPR:

    1. The variable V is called the range variable.

    2. The sequence type T is called the declared type. If there is no declared type, then item()* is assumed.

    3. The expression EXPR is evaluated, and its value is converted to the declared type by applying the coercion rules. The resulting value is called the binding sequence.

  3. In a LetSequenceBinding such as let $( $A1 as T1, $A2 as T2, ... , $An as Tn ) as ST := EXPR:

    1. The sequence type ST is called the declared sequence type. If there is no declared sequence type, then item()* is assumed.

    2. The expression EXPR is evaluated, and its value is converted to the declared sequence type ST by applying the coercion rules. Call the resulting (coerced) value V.

    3. Each variable Ai (for i in 1 to n-1) is effectively replaced by a LetValueBinding of the form let Ai as Ti := items-at(V, i). That is, a range variable named Ai is declared, whose binding sequence is the item V[ i ], after coercion to the type Ti if specified. If Ti is absent, no further coercion takes place (the default is effectively item()?).

    4. The last variable An is effectively replaced by a LetValueBinding of the form let An as Tn := subsequence(V, n). That is, the last variable is bound to the rest of the binding sequence (or to the empty sequence if the binding sequence has fewer items than the number of variables).

    Note:

    If i exceeds the length of the sequence V, then Ai is bound to anthe empty sequence. This will cause a type error if type Ti does not permit anthe empty sequence.

    Note:

    It is permissible to bind several variables with the same name; all but the last are occluded. A useful convention is therefore to bind items in the sequence that are of no interest to the variable $_: for example let $( $_, $_, $x ) := EXPR effectively binds $x to the third item in the sequence and causes the first two items to be ignored.

    Example:

    The expression:

    let $( $a, $b as xs:integer, $local:c ) := (2, 4, 6)
    return $a + $b + $local:c

    is expanded to:

    let $temp := (2, 4, 6)
    let $a := fn:items-at($temp, 1)
    let $b as xs:integer := fn:items-at($temp, 2)
    let $local:c := fn:subsequence($temp, 3)
    return $a + $b + $local:c

    where $temp is some variable name that is otherwise unused.

     

    Example:

    Consider the element $E := <e A="p q r" B="x y z"/>.

    Then consider the expression:

    let $( $a, $b ) := $E!(@A, @B)

    Here the binding sequence is a sequence of two attribute nodes, so $a is bound to the attribute @A, and $b is bound to the attribute node @B.

    If the operator "!" were replaced by "/", or if "," were replaced by "|", then the binding sequence would be sorted into document order, and since the order of attributes is not defined, this would make it unpredictable which variable is bound to which attribute node.

    Now consider what happens when a declared sequence type is added:

    let $( $a, $b ) as xs:string* := $E!(@A, @B)

    The sequence of two attribute nodes is now atomized to form a sequence of strings. The first string in this sequence is bound to $a, and the remainder of the sequence is bound to $b. If the element $E is untyped, this will result in $a being bound to the xs:untypedAtomic value "p q r", while $b is bound to the xs:untypedAtomic value "x y z".

    However, suppose that the element $E has been validated against a schema that defines both attributes @A and @B as list types with item type xs:string. In this case, the atomized value of $E will be a sequence of six strings. The variable $a is bound to the first of these strings (that is, "p"), while $b is bound to a sequence containing the remaining five strings (that is, ("q", "r", "x", "y", "z")).

    By contrast, if the expression is written as:

    let $( $a as xs:string*, $b as xs:string* ) := $E!(@A, @B)

    then $a is bound to the result of atomizing the first attribute (the untypedAtomic value "p q r" in the untyped case, or the sequence of three strings ("p", "q", "r") in the schema-validated case), while $b is similarly bound to the result of atomizing the second attribute.

  4. In a LetArrayBinding such as let $[ $A1 as T1, $A2 as T2, ... , $An as Tn ] as AT := EXPR:

    1. The sequence type AT is called the declared array type. If there is no declared array type, then array(*) is assumed.

    2. The expression EXPR is evaluated, and its value is converted to the declared array type AT by applying the coercion rules. A type error [err:XPTY0004] is raised if the result is not a singleton array. Call the resulting (coerced) value V.

    3. Each variable Ai (for i in 1 to n) is effectively replaced by a LetValueBinding of the form let Ai as Ti := array:get(V, i). That is, a range variable named Ai is declared, whose binding sequence is the array member V ? i, after coercion to the type Ti if specified. If Ti is absent, no further coercion takes place (the default is effectively item()*).

      Note:

      If i exceeds the length of the array V, then a dynamic error [err:FOAR0001]FO is raised.

      Note:

      It is permissible to bind several variables with the same name; all but the last are occluded. A useful convention is therefore to bind items in the sequence that are of no interest to the variable $_: for example let $( $_, $_, $x ) := EXPR effectively binds $x to the third item in the sequence and causes the first two items to be ignored.

      Example:

      The expression:

      let $[ $a, $b as xs:integer, $local:c ] := [ 2, 4, 6 ]
      return $a + $b + $local:c

      is expanded to:

      let $temp := [ 2, 4, 6 ]
      let $a := array:get($temp, 1, ())
      let $b as xs:integer := array:get($temp, 2, ())
      let $local:c := array:get($temp, 3, ())
      return $a + $b + $local:c

      where $temp is some variable name that is otherwise unused.

  5. In a LetMapBinding such as let ${ $A1 as T1, $A2 as T2, ... , $An as Tn } as MT := EXPR:

    1. The sequence type MT is called the declared map type. If there is no declared map type, then map(*) is assumed.

    2. The expression EXPR is evaluated, and its value is converted to the declared map type MT by applying the coercion rules. A type error [err:XPTY0004] is raised if the result is not a singleton map. Call the resulting (coerced) value V.

    3. Each variable Ai (for i in 1 to n) is effectively replaced by a LetValueBinding of the form let Ai as Ti := map:get(V, "Ni", ()), where Ni is the local part of the name of the variable Ai. That is, a range variable named Ai is declared, whose binding sequence is the value of the map entry in V whose key is an xs:string (or xs:anyURI or xs:untypedAtomic) equal to the local part of the variable name, after coercion to the type Ti if specified. If Ti is absent, no further coercion takes place (the default is effectively item()*).

      Note:

      If there is no entry in the map with a key corresponding to the variable name, then the variable Ai is bound to anthe empty sequence. This will cause a type error if type Ti does not permit anthe empty sequence.

      Note:

      It is not possible to use this mechanism to bind variables to values in a map unless the keys in the map are strings in the form of NCNames.

      Example:

      The expression:

      let ${ $a, $b as xs:integer, $local:c } := { "a": 2, "b": 4, "c": 6, "d": 8 }
      return $a + $b + $local:c

      is expanded to:

      let $temp := { "a": 2, "b": 4, "c": 6 }
      let $a := map:get($temp, "a", ())
      let $b as xs:integer := map:get($temp, "b", ())
      let $local:c := map:get($temp, "c", ())
      return $a + $b + $local:c

      where $temp is some variable name that is otherwise unused.

  6. The expression in the ForLetReturn part (that is, the following LetExpr or ForExpr, or the ExprSingle that follows the return keyword) is called the return expression. The result of the let expression is obtained by evaluating the return expression with a dynamic context in which each range variable is bound to the corresponding binding sequence.

The scope of a variable bound in a let expression is the return expression. The scope does not include the expression to which the variable is bound. The following example illustrates how a variable binding may reference another variable bound earlier in the same let expression:

let $x := doc('a.xml')/*, $y := $x//*
return $y[@value gt $x/@min]

Note:

It is not required that the variables should have distinct names. It is permitted, for example, to write:

let $x := "[A fine romance]"
let $x := substring-after($x, "[")
let $x := substring-before($x, "]")
return upper-case($x)

which returns the result "A FINE ROMANCE". Note that this expression declares three separate variables which happen to have the same name; it should not be read as declaring a single variable and binding it successively to different values.

4.14 Maps and Arrays

Most modern programming languages have support for collections of key/value pairs, which may be called maps, dictionaries, associative arrays, hash tables, keyed lists, or objects (these are not the same thing as objects in object-oriented systems). In XPath 4.0, we call these maps. Most modern programming languages also support ordered lists of values, which may be called arrays, vectors, or sequences. In XPath 4.0, we have both sequences and arrays. Unlike sequences, an array is an item, and can appear as an item in a sequence.

Note:

The XPath 4.0 specification focuses on syntax provided for maps and arrays, especially constructors and lookup.

Some of the functionality typically needed for maps and arrays is provided by functions defined in [Functions and Operators 4.0] section 14 Processing maps and [Functions and Operators 4.0] section 15 Processing arrays, including functions used to read JSON to create maps and arrays, serialize maps and arrays to JSON, combine maps to create a new map, remove map entries to create a new map, iterate over the keys of a map, convert an array to create a sequence, combine arrays to form a new array, and iterate over arrays in various ways.

4.14.3 Lookup Expressions

Changes in 4.0 (next | previous)

  1. The lookup operator ? can now be followed by an arbitrary literal, for cases where keys are items other than integers or NCNames. It can also be followed by a variable reference or a context value reference.   [Issue 1996 PR 2134 29 July 2025]

The operator "?", known as the lookup operator, returns values found in the operand map or array.

4.14.3.3 Comparing Lookup and Path Expressions

Lookup expressions are retained in this specification with only minor changes from the previous version 3.1. They remain a convenient solution for simple lookups of entries in maps and arrays.

For more complex queries into trees of maps and arrays, XPath 4.0 introduces a generalization of path expressions (see 4.7 Path Expressions) which can now handle JTrees as well as XTrees.

For simple expressions, the capabilities of the two constructs overlap. For example, if $m is a map, then the expressions $m?code = 3 and $m/code = 3 have the same effect. Path expressions, however, have more power, and with it, more complexity. The expression $m/code = 3 (unless simplified by an optimizer) effectively expands the expression to (jtree($m)/child::get("code") => jnode-content()) = 3: that is, the supplied map is wrapped in a JNode, the child axis returns a sequence of JNodes, and the ·content· properties of these JNodes are compared with the supplied value 3.

Whereas simple lookups of specific entries in maps and arrays work well, experience has shown that the ?* wildcard lookup can be problematic. This is because of the flattening effect: for example, given the array let $A := [(1,2), (3,4), (), 5] the result of the expression $A?* is the sequence (1, 2, 3, 4, 5) which loses information that might be needed for further processing. By contrast, the path expression $A/* (or $A/child::*) returns a sequence of four JNodes, whose ·content· properties are respectively (1,2), (3,4), (), and 5.

The result of a lookup expression is a simple value (the value of an entry in a map or a member of an array, or the sequence concatenation of several such values). By contrast, the result of a path expression applied to maps or arrays is always a sequence of JNodes. These JNodes can be used for further navigation. If only the ·content· properties of the JNodes are needed, these will usually be extracted automatically by virtue of the coercion rules: for example if the value is used in an arithmetic expression or a value comparison, atomization of the JNode automatically extracts its ·content·. In other cases the value can be extracted explicitly by a call of the jnode-content function.

Lookup expressions on arrays result in a dynamic error if the subscript is out of bounds, whereas the equivalent path expression succeeds, returning anthe empty sequence. For example array{1 to 5}?10 raises [err:FOAY0001]FO40, whereas array{1 to 5}/get(10) returns a empty sequence.

4.14.5 Filter Expressions for Maps and Arrays

Changes in 4.0 (next | previous)

  1. Filter expressions for maps and arrays are introduced.   [Issue 1159 PR 1163 20 April 2024]

  2. Predicates in filter expressions for maps and arrays can now be numeric.   [Issue 1207 PR 1217 15 May 2024]

  3. The group is considering removing or substantially changing this feature, it is considered at risk.   [Issue 2351 ]

FilterExprAM::=PostfixExpr "?[" Expr "]"
PostfixExpr::=PrimaryExpr | FilterExpr | DynamicFunctionCall | LookupExpr | MethodCall | FilterExprAM
Expr::=(ExprSingle ++ ",")

Maps and arrays can be filtered using the construct INPUT?[FILTER]. For example, $array?[count(.)=1] filters an array to retain only those members that are single items.

Note:

The character-pair ?[ forms a single token; no intervening whitespace or comment is allowed.

The required type of the left-hand operand INPUT is (map(*)|array(*))?: that is, it must be either anthe empty sequence, a single map, or a single array [err:XPTY0004]. However, the coercion rules also allow a JNode whose ·content· is a map or array to be supplied. If the value is anthe empty sequence, the result of the expression is anthe empty sequence.

If the value of INPUT is an array, then the FILTER expression is evaluated for each member of the array, with that member as the context value, with its position in the array as the context position, and with the size of the array as the context size. The result of the expression is an array containing those members of the input array for which the predicate truth value of the FILTER expression is true. The order of retained members is preserved.

For example, the following expression:

let $array := [ (), 1, (2, 3), (4, 5, 6) ]
return $array?[count(.) ge 2]

returns:

[ (2, 3), (4, 5, 6) ]

Note:

Numeric predicates are handled in the same way as with filter expressions for sequences. However, the result is always an array, even if only one member is selected. For example, given the $array shown above, the result of $array?[3] is the single-member arrayDM[ (2, 3) ]. Contrast this with $array?3 which delivers the sequence 2, 3.

If the value of INPUT is a map, then the FILTER expression is evaluated for each entry in the map, with the context value set to an item of type record(key as xs:anyAtomicType, value as item()*), in which the key and value fields represent the key and value of the map entry. The context position is the position of the entry in the map (in entry orderDM), and the context size is the number of entries in the map. The result of the expression is a map containing those entries of the input map for which the predicate truth value of the FILTER expression is true. The relative order of entries in the result retains the relative order of entries in the input.

For example, the following expression:

let $map := { 1: "alpha", 2: "beta", 3: "gamma" }
return $map?[?key ge 2]

returns:

{ 2: "beta", 3: "gamma" }

Note:

A filter expression such as $map?[last()-1, last()] might be used to return the last two entries of a map in entry orderDM.

4.16 Otherwise Expressions

Changes in 4.0 (next | previous)

  1. An otherwise operator is introduced: A otherwise B returns the value of A, unless it is anthe empty sequence, in which case it returns the value of B.   [Issue 1024 PR 1031 27 February 2024]

OtherwiseExpr::=StringConcatExpr ("otherwise" StringConcatExpr)*
StringConcatExpr::=RangeExpr ("||" RangeExpr)*

The otherwise expression returns the value of its first operand, unless this is anthe empty sequence, in which case it returns the value of its second operand.

For example, @price - (@discount otherwise 0) returns the value of @price - @discount, if the attribute @discount exists, or the value of @price if the @discount attribute is absent.

To prevent spurious errors, the right hand operand is guarded: it cannot throw any dynamic error unless the left-hand operand returns anthe empty sequence.

Note:

The operator is associative (even under error conditions): A otherwise (B otherwise C) returns the same result as (A otherwise B) otherwise C.

The otherwise operator binds more tightly than comparison operators such as =, but less tightly than string concatenation (||) or arithemetic operators. The expression $a = @x otherwise @y + 1 parses as $a = (@x otherwise (@y + 1)).

4.17 Quantified Expressions

Changes in 4.0 (next | previous)

  1. If a type declaration is present, the supplied values in the input sequence are now coerced to the required type. Type declarations are now permitted in XPath as well as XQuery.   [Issue 1316 PR 1384 13 August 2024]

Quantified expressions support existential and universal quantification. The value of a quantified expression is always true or false.

QuantifiedExpr::=("some" | "every") (QuantifierBinding ++ ",") "satisfies" ExprSingle
QuantifierBinding::=VarNameAndType "in" ExprSingle
VarNameAndType::="$" EQNameTypeDeclaration?
EQName::=QName | URIQualifiedName
TypeDeclaration::="as" SequenceType
SequenceType::=("empty-sequence" "(" ")")
| (ItemTypeOccurrenceIndicator?)
ExprSingle::=ForExpr
| LetExpr
| QuantifiedExpr
| IfExpr
| OrExpr

A quantified expression begins with a quantifier, which is the keyword some or every, followed by one or more in-clauses that are used to bind variables, followed by the keyword satisfies and a test expression. Each in-clause associates a variable with an expression that returns a sequence of items, called the binding sequence for that variable. The value of the quantified expression is defined by the following rules:

  1. If the QuantifiedExpr contains more than one QuantifierBinding, then it is equivalent to the expression obtained by replacing each comma with satisfies some or satisfies every respectively. For example, the expression some $x in X, $y in Y satisfies $x = $y is equivalent to some $x in X satisfies some $y in Y satisfies $x = $y, while the expression every $x in X, $y in Y satisfies $x lt $y is equivalent to every $x in X satisfies every $y in Y satisfies $x lt $y

  2. If the quantifier is some, the QuantifiedExpr returns true if at least one evaluation of the test expression has the effective boolean valuetrue; otherwise it returns false. In consequence, if the binding sequence is empty, the result of the QuantifiedExpr is false.

  3. If the quantifier is every, the QuantifiedExpr returns true if every evaluation of the test expression has the effective boolean valuetrue; otherwise it returns false. In consequence, if the binding sequence is empty, the result of the QuantifiedExpr is true.

The scope of a variable bound in a quantified expression comprises all subexpressions of the quantified expression that appear after the variable binding. The scope does not include the expression to which the variable is bound.

Each variable binding may be accompanied by a type declaration, which consists of the keyword as followed by the static type of the variable, declared using the syntax in 3.1 Sequence Types. The type declaration defines a required type for the value. At run-time, the supplied value for the variable is converted to the required type by applying the coercion rules. If conversion is not possible, a type error is raised [err:XPTY0004].

The order in which test expressions are evaluated for the various items in the binding sequence is implementation-dependent. If the quantifier is some, an implementation may return true as soon as it finds one item for which the test expression has an effective boolean value of true, and it may raise a dynamic error as soon as it finds one item for which the test expression raises an error. Similarly, if the quantifier is every, an implementation may return false as soon as it finds one item for which the test expression has an effective boolean value of false, and it may raise a dynamic error as soon as it finds one item for which the test expression raises an error. As a result of these rules, the value of a quantified expression is not deterministic in the presence of errors, as illustrated in the examples below.

Here are some examples of quantified expressions:

  • This expression is true if every part element has a discounted attribute (regardless of the values of these attributes):

    every $part in /parts/part satisfies $part/@discounted
  • This expression is true if at least one employee element satisfies the given comparison expression:

    some $emp in /emps/employee satisfies $emp/bonus > 0.25 * $emp/salary
  • This expression is true if every employee element has at least one salary child with the attribute current="true":

    every $emp in /emps/employee satisfies (
      some $sal in $emp/salary satisfies $sal/@current = 'true'
    )

    Note:

    Like many quantified expressions, this can be simplified. This example can be written every $emp in /emps/employee satisfies $emp/salary[@current = 'true'], or even more concisely as empty(/emps/employee[not(salary/@current = 'true')].

    Another alternative in XPath 4.0 is to use the higher-order functions fn:some and fn:every. This example can be written every(/emps/employee, fn { salary/@current = 'true' })

  • In the following examples, each quantified expression evaluates its test expression over nine pairs of items, formed from the Cartesian product of the sequences (1, 2, 3) and (2, 3, 4). The expression beginning with some evaluates to true, and the expression beginning with every evaluates to false.

    some $x in (1, 2, 3), $y in (2, 3, 4) satisfies $x + $y = 4
    every $x in (1, 2, 3), $y in (2, 3, 4) satisfies $x + $y = 4
  • This quantified expression may either return true or raise a type error, since its test expression returns true for one item and raises a type error for another:

    some $x in (1, 2, "cat") satisfies $x * 2 = 4
  • This quantified expression may either return false or raise a type error, since its test expression returns false for one item and raises a type error for another:

    every $x in (1, 2, "cat") satisfies $x * 2 = 4
  • This quantified expression returns true, because the binding sequence is empty, despite the fact that the condition can never be satisfied:

    every $x in () satisfies ($x lt 0 and $x gt 0)
  • This quantified expression is implausible because it will always fail with a type error except in the case where $input is anthe empty sequence. If $input contains one or more xs:date values, a processor must raise a type error on the grounds that an xs:date cannot be compared to an xs:integer. If $input is empty, the processor may (or may not) report this error:

    every $x as xs:date in $input satisfies ($x lt 0)
  • This quantified expression contains a type declaration that is not satisfied by every item in the test expression. The expression may either return true or raise a type error.

    some $x as xs:integer in (1, 2, "cat") satisfies $x * 2 = 4

4.18 Expressions on SequenceTypes

The instance of, cast, castable, and treat expressions are used to test whether a value conforms to a given type or to convert it to an instance of a given type.

4.18.2 Cast

CastExpr::=PipelineExpr ("cast" "as" CastTarget "?"?)?
PipelineExpr::=ArrowExpr ("->" ArrowExpr)*
CastTarget::=TypeName | ChoiceItemType | EnumerationType
TypeName::=EQName
EQName::=QName | URIQualifiedName
ChoiceItemType::="(" (ItemType ++ "|") ")"
ItemType::=RegularItemType | FunctionType | TypeName | ChoiceItemType
EnumerationType::="enum" "(" (StringLiteral ++ ",") ")"

Sometimes it is necessary to convert a value to a specific datatype. For this purpose, XPath 4.0 provides a cast expression that creates a new value of a specific type based on an existing value. A cast expression takes two operands: an input expression and a target type. The type of the atomized value of the input expression is called the input type. The target type must be a generalized atomic type. In practice this means it may be any of:

  • The name of an named item type defined in the static context, which in turn must refer to an item type in one of the following categories.

  • The name of a type defined in the in-scope schema types, which must be a simple type (of variety atomic, list or union) [err:XQST0052] . In addition, the target type cannot be xs:NOTATION, xs:anySimpleType, or xs:anyAtomicType

  • A ChoiceItemType representing a generalized atomic type (such as (xs:date | xs:dateTime)).

  • An EnumerationType such as enum("red", "green", "blue").

Otherwise, a static error is raised [err:XPST0080].

The optional occurrence indicator ? denotes that anthe empty sequence is permitted.

Casting a node to xs:QName can cause surprises because it uses the static context of the cast expression to provide the namespace bindings for this operation. Instead of casting to xs:QName, it is generally preferable to use the fn:QName function, which allows the namespace context to be taken from the document containing the QName.

The semantics of the cast expression are as follows:

  1. The input expression is evaluated.

  2. The result of the first step is atomized.

  3. If the result of atomization is a sequence of more than one atomic item, a type error is raised [err:XPTY0004].

  4. If the result of atomization is anthe empty sequence:

    1. If ? is specified after the target type, the result of the cast expression is anthe empty sequence.

    2. If ? is not specified after the target type, a type error is raised [err:XPTY0004].

  5. If the result of atomization is a single atomic item, the result of the cast expression is determined by casting to the target type as described in [Functions and Operators 4.0] section 23 Casting. When casting, an implementation may need to determine whether one type is derived by restriction from another. An implementation can determine this either by examining the in-scope schema definitions or by using an alternative, implementation-dependent mechanism such as a data dictionary. The result of a cast expression is one of the following:

    1. A value of the target type (or, in the case of list types, a sequence of values that are instances of the item type of the list type).

    2. A type error, if casting from the source type to the target type is not supported (for example attempting to convert an integer to a date).

    3. A dynamic error, if the particular input value cannot be converted to the target type (for example, attempting to convert the string "three" to an integer).

    Note:

    Casting to an enumeration type relies on the fact that an enumeration type is a generalized atomic type. So the expression cast $x as enum("red", "green") has the following effect:

    • If $x is an instance of xs:string, the expression returns $x unchanged if it is one of the permitted strings, and raises a dynamic error otherwise;

    • In other cases, the expression first casts $x to xs:string, and then proceeds as above.

F Glossary (Non-Normative)

absolute path expression

An absolute path expression is an instance of the production AbsolutePathExpr: it consists of either (a) the operator / followed by zero or more operands separated by / or // operators, or (b) the operator // followed by one or more operands separated by / or // operators.

and expression

An and expression is a non-trivial instance of the production AndExpr.

anonymous function

An anonymous function is a function item with no name. Anonymous functions may be created, for example, by evaluating an inline function expression or by partial function application.

application function

Application functions are function definitions written in a host language such as XQuery or XSLT whose syntax and semantics are defined in this family of specifications. Their behavior (including the rules determining the static and dynamic context) follows the rules for such functions in the relevant host language specification.

argument expression

An argument to a function call is either an argument expression or an ArgumentPlaceholder (?); in both cases it may either be supplied positionally, or identified by a name (called a keyword).

arity range

A function definition has an arity range, which is a range of consecutive non-negative integers. If the function definition has M required parameters and N optional parameters, then its arity range is from M to M+N inclusive.

array

An array is a function item that associates a set of positions, represented as positive integer keys, with values.

associated value

The value associated with a given key is called the associated value of the key.

atomic item

An atomic item is a value in the value space of an atomic type, as defined in [XML Schema 1.0] or [XML Schema 1.1].

atomic type

An atomic type is a simple schema type whose {variety}XS11-1 is atomic.

atomization

Atomization of a sequence is defined as the result of invoking the fn:data function, as defined in [Functions and Operators 4.0] section 12.1.6 fn:data.

available documents

The term available documents refers (TODO: for the time being) to the set of XML documents that an application is able to access by URI.

axis step

An axis step is an instance of the production AxisStep: it is an expression that returns a sequence of GNodes that are reachable from a starting GNode via a specified axis. An axis step has three parts: an axis, which defines the direction of movement for the step, a node test, which selects GNodes based on their properties, and zero or more predicates which are used to filter the results.

binding collection

The result of evaluating the binding expression in a for expression is called the binding collection

choice item type

A choice item type defines an item type that is the union of a number of alternatives. For example the type (xs:hexBinary | xs:base64Binary) defines the union of these two primitive atomic types, while the type (map(*) | array(*)) matches any item that is either a map or an array.

coercion rules

The coercion rules are rules used to convert a supplied value to a required type, for example when converting an argument of a function call to the declared type of the function parameter.

collation

A collation is a specification of the manner in which strings and URIs are compared and, by extension, ordered. For a more complete definition of collation, see [Functions and Operators 4.0] section 5.3 Comparison of strings.

comma operator

A comma operator is a comma used specifically as the operator in a sequence expression.

complex terminal

A complex terminal is a variable terminal whose production rule references, directly or indirectly, an ordinary production rule.

constructor function

The constructor function for a given simple type is used to convert instances of other simple types into the given type. The semantics of the constructor function call T($arg) are defined to be equivalent to the expression $arg cast as T?.

content expression

In an enclosed expression, the optional expression enclosed in curly brackets is called the content expression.

context dependent

A function definition is said to be context dependent if its result depends on the static or dynamic context of its caller. A function definition may be context-dependent for some arities in its arity range, and context-independent for others: for example fn:name#0 is context-dependent while fn:name#1 is context-independent.

context node

When the context value is a single item, it can also be referred to as the context item; when it is a single node, it can also be referred to as the context node.

context position

The context position is the position of the context value within the series of values currently being processed.

context size

The context size is the number of values in the series of values currently being processed.

context value

The context value is the value currently being processed.

current dateTime

Current dateTime. This information represents an implementation-dependent point in time during the processing of an expression, and includes an explicit timezone. It can be retrieved by the fn:current-dateTime function. If called multiple times during the execution of an expression, this function always returns the same result.

data model

XPath 4.0 operates on the abstract, logical structure of an XML document or JSON object rather than its surface syntax. This logical structure, known as the data model, is defined in [XDM 4.0].

decimal-separator

decimal-separator(M, R) is used to separate the integer part of the number from the fractional part. The default value for both the marker and the rendition is U+002E (FULL STOP, PERIOD, .) .

default calendar

Default calendar. This is the calendar used when formatting dates in human-readable output (for example, by the functions fn:format-date and fn:format-dateTime) if no other calendar is requested. The value is a string.

default collation

Default collation. This identifies one of the collations in statically known collations as the collation to be used by functions and operators for comparing and ordering values of type xs:string and xs:anyURI (and types derived from them) when no explicit collation is specified.

default collection

Default collection. This is the sequence of items that would result from calling the fn:collection function with no arguments.

default element namespace rule

When an unprefixed lexical QName is expanded using the default element namespace rule, then it uses the default namespace for elements and types. If this is absent, or if it takes the special value ##any, then the no-namespace rule is used.

default function namespace

Default function namespace. This determines how unprefixed lexical QNames appearing in a static function call or a named function reference are interpreted.

default function namespace rule

When an unprefixed lexical QName is expanded using the default function namespace rule, the processor searches for a matching function definition as follows: first, if the static context includes a no-namespace function definition with the required local name and arity, then that function definition is used; otherwise, the name is expanded using the default function namespace from the static context.

default in-scope namespace

The default in-scope namespace of an element node

default language

Default language. This is the natural language used when creating human-readable output (for example, by the functions fn:format-date and fn:format-integer) if no other language is requested. The value is a language code as defined by the type xs:language.

default namespace for elements and types

Default namespace for elements and types. This is either a namespace URI, or the special value "##any", or absentDM. This indicates how unprefixed QNames are interpreted when they appear in a position where an element name or type name is expected.

default place

Default place. This is a geographical location used to identify the place where events happened (or will happen) when processing dates and times using functions such as fn:format-date, fn:format-dateTime, and fn:civil-timezone, if no other place is specified. It is used when translating timezone offsets to civil timezone names, and when using calendars where the translation from ISO dates/times to a local representation is dependent on geographical location. Possible representations of this information are an ISO country code or an Olson timezone name, but implementations are free to use other representations from which the above information can be derived. The only requirement is that it should uniquely identify a civil timezone, which means that country codes for countries with multiple timezones, such as the United States, are inadequate.

default type namespace rule

When an unprefixed lexical QName is expanded using the default type namespace rule, it uses the default namespace for elements and types. If this is absent, the no-namespace rule is used. If the default namespace for elements and types has the special value ##any, then the lexical QName refers to a name in the namespace http://www.w3.org/2001/XMLSchema.

default URI collection

Default URI collection. This is the sequence of URIs that would result from calling the fn:uri-collection function with no arguments.

delimiting terminal symbol

The delimiting terminal symbols are: !!=#$()**:+,-->...///::*:::=;<<<<===!>=>=?>>>=>>??[@[]```{{{|||}}}×÷AposStringLiteralBracedURILiteralQuotStringLiteralStringLiteralURIQualifiedName

derives from

A schema typeS1 is said to derive fromschema typeS2 if any of the following conditions is true:

digit

digit(M) is a character used in the picture string to represent an optional digit; the default value is U+0023 (NUMBER SIGN, #) .

document order

Informally, document order is the order in which nodes appear in the XML serialization of a document.

dynamically known function definitions

Dynamically known function definitions. This is a set of function definitions. It includes the statically known function definitions as a subset, but may include other function definitions that are not known statically.

dynamic context

The dynamic context of an expression is defined as information that is needed for the dynamic evaluation of an expression, beyond any information that is needed from the static context.

dynamic error

A dynamic error is an error that must be detected during the dynamic evaluation phase and may be detected during the static analysis phase.

dynamic evaluation phase

The dynamic evaluation phase is the phase during which the value of an expression is computed.

dynamic function call

A dynamic function call is an instance of the construct DynamicFunctionCall: that is, it is an expression in the form E1(E2, E3, ...) in which E1 identifies a function item to be called, and the parenthesized argument list (E2, E3, ...)) identifies the arguments supplied to the function.

dynamic type

Every value matches one or more sequence types. A value is said to have a dynamic typeT if it matches (or is an instance of) the sequence type T.

effective boolean value

The effective boolean value of a value is defined as the result of applying the fn:boolean function to the value.

element name matching rule

When an unprefixed lexical QName is expanded using the element name matching rule rule, then it uses the default namespace for elements and types. If this is absent, then it uses the no-namespace rule. But if it takes the special value ##any, then the name is taken as matching any expanded QName with the corresponding local part, regardless of namespace: that is, the unprefixed name local is interpreted as *:local.

empty sequence

AThe sequence containing zero items is called anthe empty sequence.

enclosed expression

An enclosed expression is an instance of the EnclosedExpr production, which allows an optional expression within curly brackets.

entry

Each key / value pair in a map is called an entry.

enumeration type

An EnumerationType accepts a fixed set of string values.

environment variables

Environment variables. This is a mapping from names to values. Both the names and the values are strings. The names are compared using an implementation-defined collation, and are unique under this collation. The set of environment variables is implementation-defined and may be empty.

error value

In addition to its identifying QName, a dynamic error may also carry a descriptive string and one or more additional values called error values.

Executable Base URI

Executable Base URI. This is an absolute URI used to resolve relative URIs during the evaluation of expressions; it is used, for example, to resolve a relative URI supplied to the fn:doc or fn:unparsed-text functions.

expanded QName

An expanded QName is a triple: its components are a prefix, a local name, and a namespace URI. In the case of a name in no namespace, the namespace URI and prefix are both absent. In the case of a name in the default namespace, the prefix is absent.

exponent-separator

exponent-separator(M, R) is used to separate the mantissa from the exponent in scientific notation. The default value for both the marker and the rendition is U+0065 (LATIN SMALL LETTER E, e) .

expression context

The expression context for a given expression consists of all the information that can affect the result of the expression.

external function

External functions can be characterized as functions that are neither part of the processor implementation, nor written in a language whose semantics are under the control of this family of specifications. The semantics of external functions, including any context dependencies, are entirely implementation-defined. In XSLT, external functions are called 24.1 Extension Functions XT30.

filter expression

A filter expression is an instance of the construct FilterExpr: that is, it is an expression in the form E1[E2]. Its effect is to return those items from the value of E1 that satisfy the predicate in E2.

filter expression for maps and arrays

A filter expression for maps and arrays is an instance of the construct FilterExprAM: that is, it is an expression in the form E1?[E2]. Its effect is to evaluate E1 to return an array or map, and to select members of the array, or entries from the map, that satisfy the predicate in E2.

fixed focus

A fixed focus is a focus for an expression that is evaluated once, rather than being applied to a series of values; in a fixed focus, the context value is set to one specific value, the context position is 1, and the context size is 1.

focus

The first three components of the dynamic context (context value, context position, and context size) are called the focus of the expression.

focus function

A focus function is an inline function expression in which the function signature is implicit: the function takes a single argument of type item()* (that is, any value), and binds this to the context value when evaluating the function body, which returns a result of type item()*.

function coercion

Function coercion wraps a function item in a new function whose signature is the same as the expected type. This effectively delays the checking of the argument and return types until the function is called.

function definition

A function definition contains information used to evaluate a static function call, including the name, parameters, and return type of the function.

function item

A function item is an item that can be called using a dynamic function call.

generalized atomic type

A generalized atomic type is an item type whose instances are all atomic items. Generalized atomic types include (a) atomic types, either built-in (for example xs:integer) or imported from a schema, (b) pure union types, either built-in (xs:numeric and xs:error) or imported from a schema, (c) choice item types if their alternatives are all generalized atomic types, and (d) enumeration types.

GNode

The term generic node or GNode is a collective term for XNodes (more commonly called simply nodes) representing the parts of an XML document, and JNodes, often used to represent the parts of a JSON document.

A GNode (for generalized node) is either an XNode or a JNode.

grouping-separator

grouping-separator(M, R) is used to separate groups of digits (for example as a thousands separator). The default value for both the marker and the rendition is U+002C (COMMA, ,) .

GTree

The term GTree means JTree or XTree.

guarded

An expression E is said to be guarded by some governing condition C if evaluation of E is not allowed to fail with a dynamic error except when C applies.

host language

A host language for XPath is any environment that provides capabilities for XPath expressions to be defined and evaluated, and that supplies a static and dynamic context for their evaluation.

ignorable whitespace

Ignorable whitespace consists of any whitespace characters that may occur between terminals, unless these characters occur in the context of a production marked with a ws:explicit annotation, in which case they can occur only where explicitly specified (see A.3.4.2 Explicit Whitespace Handling).

implausible

Certain expressions, while not erroneous, are classified as being implausible, because they achieve no useful effect.

implementation defined

Implementation-defined indicates an aspect that may differ between implementations, but must be specified by the implementer for each particular implementation.

implementation dependent

Implementation-dependent indicates an aspect that may differ between implementations, is not specified by this or any W3C specification, and is not required to be specified by the implementer for any particular implementation.

implicit timezone

Implicit timezone. This is the timezone to be used when a date, time, or dateTime value that does not have a timezone is used in a comparison or arithmetic operation. The implicit timezone is an implementation-defined value of type xs:dayTimeDuration. See 3.2.7.3 Timezones XS1-2 or 3.3.7 dateTime XS11-2 for the range of valid values of a timezone.

infinity

infinity(R) is the string used to represent the double value infinity (INF); the default value is the string "Infinity"

inline function expression

An inline function expression is an instance of the construct InlineFunctionExpr. When evaluated, an inline function expression creates an anonymous function whose properties are defined directly in the inline function expression.

in-scope attribute declarations

In-scope attribute declarations. Each attribute declaration is identified either by an expanded QName (for a top-level attribute declaration) or by an implementation-dependent attribute identifier (for a local attribute declaration).

in-scope element declarations

In-scope element declarations. Each element declaration is identified either by an expanded QName (for a top-level element declaration) or by an implementation-dependent element identifier (for a local element declaration).

in-scope named item types

In-scope named item types. This is a mapping from expanded QNames to named item types.

in-scope namespaces

The in-scope namespaces property of an element node is a set of namespace bindings, each of which associates a namespace prefix with a URI.

in-scope schema definitions

In-scope schema definitions is a generic term for all the element declarations, attribute declarations, and schema type definitions that are in scope during static analysis of an expression.

in-scope schema type

In-scope schema types. Each schema type definition is identified either by an expanded QName (for a named type) or by an implementation-dependent type identifier (for an anonymous type). The in-scope schema types include the predefined schema types described in 3.5 Schema Types.

in-scope variables

In-scope variables. This is a mapping from expanded QNames to sequence types. It defines the set of variables that are available for reference within an expression. The expanded QName is the name of the variable, and the type is the static type of the variable.

item

An item is either an atomic item, a node, or a function item.

item type

An item type is a type that can be expressed using the ItemType syntax, which forms part of the SequenceType syntax. Item types match individual items.

item type designator

An item type designator is a syntactic construct conforming to the grammar rule ItemType. An item type designator is said to designate an item type.

JNode

A JNode is a kind of item used to represent a value within the context of a tree of maps and arrays. A root JNode represents a map or array; a non-root JNode represents a member of an array or an entry in a map.

A JNode (see also [XDM 4.0] section 8.4 JNodes) is an encapsulation of a value as it appears within a tree of maps and arrays, typically (but not necessarily) obtained by parsing JSON texts.

JTree

A tree that is rooted at a parentless JNode is referred to as a JTree.

lexical QName

A lexical QName is a name that conforms to the syntax of the QName production

literal

A literal is a direct syntactic representation of an atomic item.

literal terminal

A literal terminal is a token appearing as a string in quotation marks on the right-hand side of an ordinary production rule.

logical expression

A logical expression is either an and expression or an or expression. If a logical expression does not raise an error, its value is always one of the boolean values true or false.

lookup expression

A lookup expression is an instance of the production LookupExpr: that is, an expression in the form E1?KS, where E1 is an expression returning a sequence of maps or arrays, and KS is a key specifier, which indicates which entries in a map, or members in an array, should be selected.

map

A map is a function that associates a set of keys with values, resulting in a collection of key / value pairs.

mapping arrow operator

The mapping arrow operator=!> applies a function to each item in a sequence.

may

MAY means that an item is truly optional.

member

The values of an array are called its members.

minus-sign

minus-sign(R) is the string used to mark negative numbers; the default value is U+002D (HYPHEN-MINUS, -) .

must

MUST means that the item is an absolute requirement of the specification.

must not

MUST NOT means that the item is an absolute prohibition of the specification.

named function reference

A named function reference is an instance of the production NamedFunctionRef: it is an expression (written name#arity) which evaluates to a function item, the details of the function item being based on the properties of a function definition in the static context.

named item type

A named item type is an ItemType identified by an expanded QName.

namespace binding

A namespace binding is a pair comprising a namespace prefix (which is either an xs:NCName or empty), and a namespace URI.

namespace-sensitive

The namespace-sensitive types are xs:QName, xs:NOTATION, types derived by restriction from xs:QName or xs:NOTATION, list types that have a namespace-sensitive item type, and union types with a namespace-sensitive type in their transitive membership.

name test

A node test that consists only of an EQName or a Wildcard is called a name test.

NaN

NaN(R) is the string used to represent the double value NaN (not a number); the default value is the string "NaN"

node

Except where the context indicates otherwise, the term node is used as a synonym for XNode.

node test

A node test is a condition on the properties of a GNode. A node test determines which GNodes returned by an axis are selected by a step.

no-namespace rule

When an unprefixed lexical QName is expanded using the no-namespace rule, it is interpreted as having an absent namespace URI.

non-delimiting terminal symbol

The non-delimiting terminal symbols are: ancestorancestor-or-selfandarrayasatattributecastcastablechildcommentdeclaredefaultdescendantdescendant-or-selfdivdocument-nodeelementelseempty-sequenceenumeqeveryexceptfalsefnfollowingfollowing-or-selffollowing-siblingfollowing-sibling-or-selffollowsfollows-or-isforfunctiongegetgnodegtidivifininstanceintersectisis-notitemjnodekeyleletltmapmembermodnamespacenamespace-nodenenodeoforotherwiseparentprecedesprecedes-or-isprecedingpreceding-or-selfpreceding-siblingpreceding-sibling-or-selfprocessing-instructionrecordreturnsatisfiesschema-attributeschema-elementselfsometextthentotreattrueunionvalueBinaryIntegerLiteralDecimalLiteralDoubleLiteralHexIntegerLiteralIntegerLiteralNCNameQName

non-trivial

A construct is said to be a non-trivial instance of a grammatical production if it is not also an instance of one of its sub-productions.

numeric

The type xs:numeric is defined as a union type with member types xs:double, xs:float, and xs:decimal. An item that is an instance of any of these types is referred to as a numeric value, and a type that is a subtype of xs:numeric is referred to as a numeric type.

ordinary production rule

An ordinary production rule is a production rule in A.1 EBNF that is not annotated ws:explicit.

or expression

An or expression is a non-trivial instance of the production OrExpr.

partial function application

A static or dynamic function call is a partial function application if one or more arguments is an ArgumentPlaceholder.

partially applied function

A partially applied function is a function created by partial function application.

path expression

A path expression is either an absolute path expression or a relative path expression

pattern-separator

pattern-separator(M) is a character used to separate positive and negative sub-pictures in a picture string; the default value is U+003B (SEMICOLON, ;) .

percent

percent(M, R) is used to indicate that the number is written as a per-hundred fraction; the default value for both the marker and the rendition is U+0025 (PERCENT SIGN, %) .

per-mille

per-mille(M, R) is used to indicate that the number is written as a per-thousand fraction; the default value for both the marker and the rendition is U+2030 (PER MILLE SIGN, ) .

pipeline operator

The pipeline operator-> evaluates an expression and binds the result to the context value before evaluating another expression.

predicate truth value

The predicate truth value of a value $V is the result of the expression if ($V instance of xs:numeric+) then ($V = position()) else fn:boolean($V).

primary expression

A primary expression is an instance of the production PrimaryExpr. Primary expressions are the basic primitives of the language. They include literals, variable references, context value references, and function calls. A primary expression may also be created by enclosing any expression in parentheses, which is sometimes helpful in controlling the precedence of operators.

principal node kind

Every axis has a principal node kind. If an axis can contain elements, then the principal node kind is element; otherwise, it is the kind of nodes that the axis can contain.

pure union type

A pure union type is a simple type that satisfies the following constraints: (a) {variety}XS11-1 is union, (b) the {facets}XS11-1 property is empty, (c) no type in the transitive membership of the union type has {variety}XS11-1list, and (d) no type in the transitive membership of the union type is a type with {variety}XS11-1union having a non-empty {facets}XS11-1 property

range expression

A range expression is a non-trivial instance of the production RangeExpr. A range expression is used to construct a sequence of integers.

relative path expression

A relative path expression is a non-trivial instance of the production RelativePathExpr: it consists of two or more operand expressions separated by / or // operators.

resolve

To resolve a relative URI$rel against a base URI $base is to expand it to an absolute URI, as if by calling the function fn:resolve-uri($rel, $base).

reverse document order

The node ordering that is the reverse of document order is called reverse document order.

same key

Two atomic items K1 and K2 have the same key value if fn:atomic-equal(K1, K2) returns true, as specified in [Functions and Operators 4.0] section 2.2.1 fn:atomic-equal

schema type

A schema type is a complex type or simple type as defined in the [XML Schema 1.0] or [XML Schema 1.1] specifications, including built-in types as well as user-defined types.

sequence

A sequence is an ordered collection of zero or more items.

sequence arrow operator

The sequence arrow operator=> applies a function to a supplied sequence.

sequence concatenation

The sequence concatenation of a number of sequences S1, S2, ... Sn is defined to be the sequence formed from the items of S1, followed by the items from S2, and so on, retaining order.

sequence expression

A sequence expression is a non-trivial instance of the production rule Expr, that is, an expression containing two or more instances of the production ExprSingle separated by the comma operator.

sequence type

A sequence type is a type that can be expressed using the SequenceType syntax. Sequence types are used whenever it is necessary to refer to a type in an XPath 4.0 expression. Since all values are sequences, every value matches one or more sequence types.

sequence type designator

A sequence type designator is a syntactic construct conforming to the grammar rule SequenceType. A sequence type designator is said to designate a sequence type.

SequenceType matching

SequenceType matching compares a value with an expected sequence type.

serialization

Serialization is the process of converting an XDM instance to a sequence of octets (step DM4 in Figure 1.), as described in [Serialization 4.0].

singleton

A sequence containing exactly one item is called a singleton.

singleton enumeration type

An enumeration type with a single enumerated value E (such as enum("red")) matches an item S if and only if (a) S is an instance of xs:string, and (b) S is equal to E when compared using Unicode codepoint collation. This is referred to as a singleton enumeration type.

singleton focus

A singleton focus is a fixed focus in which the context value is a singleton item.

stable

Document order is stable, which means that the relative order of two nodes will not change during the processing of a given expression, even if this order is implementation-dependent.

statically known collations

Statically known collations. This is an implementation-defined mapping from URI to collation. It defines the names of the collations that are available for use in processing expressions.

statically known decimal formats

Statically known decimal formats. This is a mapping from QNames to decimal formats, with one default format that has no visible name, referred to as the unnamed decimal format. Each format is available for use when formatting numbers using the fn:format-number function.

statically known function definitions

Statically known function definitions. This is a set of function definitions.

statically known namespaces

Statically known namespaces. This is a mapping from prefix to namespace URI that defines all the namespaces that are known during static processing of a given expression.

static analysis phase

The static analysis phase depends on the expression itself and on the static context. The static analysis phase does not depend on input data (other than schemas).

Static Base URI

Static Base URI. This is an absolute URI, used to resolve relative URIs during static analysis.

static context

The static context of an expression is the information that is available during static analysis of the expression, prior to its evaluation.

static error

An error that can be detected during the static analysis phase, and is not a type error, is a static error.

static function call

A static function call is an instance of the production FunctionCall: it consists of an EQName followed by a parenthesized list of zero or more arguments.

static type

The static type of an expression is the best inference that the processor is able to make statically about the type of the result of the expression.

step

The operands of a path expression are conventionally referred to as steps.

string value

The string value of a node is a string and can be extracted by applying the string function to the node.

substantively disjoint

Two sequence types are deemed to be substantively disjoint if (a) neither is a subtype of the other (see 3.3.1 Subtypes of Sequence Types) and (b) the only values that are instances of both types are one or more of the following:

substitution group

Substitution groups are defined in 2.2.2.2 Element Substitution Group XS1-1 and 2.2.2.2 Element Substitution Group XS11-1. Informally, the substitution group headed by a given element (called the head element) consists of the set of elements that can be substituted for the head element without affecting the outcome of schema validation.

subtype

Given two sequence types or item types, the rules in this section determine if one is a subtype of the other. If a type A is a subtype of type B, it follows that every value matched by A is also matched by B.

subtype substitution

The use of a value that has a dynamic type that is a subtype of the expected type is known as subtype substitution.

symbol

Each rule in the grammar defines one symbol, using the following format:

symbol ::= expression
symbol separators

Whitespace and Comments function as symbol separators. For the most part, they are not mentioned in the grammar, and may occur between any two terminal symbols mentioned in the grammar, except where that is forbidden by the /* ws: explicit */ annotation in the EBNF, or by the /* xgc: xml-version */ annotation.

system function

System functions include the functions defined in [Functions and Operators 4.0], functions defined by the specifications of a host language, constructor functions for atomic types, and any additional functions provided by the implementation. System functions are sometimes called built-in functions.

terminal

A terminal is a symbol or string or pattern that can appear in the right-hand side of a rule, but never appears on the left-hand side in the main grammar, although it may appear on the left-hand side of a rule in the grammar for terminals.

trusted

The static context includes a boolean property called trusted that determines whether external resources are available.

type annotation

Each element node and attribute node in an XDM instance has a type annotation (described in [XDM 4.0] section 4.1 Schema Information). The type annotation of a node is a reference to a schema type.

typed value

The typed value of a node is a sequence of atomic items and can be extracted by applying the data function to the node.

type error

A type error may be raised during the static analysis phase or the dynamic evaluation phase. During the static analysis phase, a type error occurs when the static type of an expression does not match the expected type of the context in which the expression occurs. During the dynamic evaluation phase, a type error occurs when the dynamic type of a value does not match the expected type of the context in which the value occurs.

untrusted
URI

Within this specification, the term URI refers to a Universal Resource Identifier as defined in [RFC3986] and extended in [RFC3987] with the new name IRI.

value

In the data model, a value is always a sequence.

variable reference

A variable reference is an EQName preceded by a $-sign.

variable terminal

A variable terminal is an instance of a production rule that is not itself an ordinary production rule but that is named (directly) on the right-hand side of an ordinary production rule.

variable values

Variable values. This is a mapping from expanded QNames to values. It contains the same expanded QNames as the in-scope variables in the static context for the expression. The expanded QName is the name of the variable and the value is the dynamic value of the variable, which includes its dynamic type.

warning

In addition to static errors, dynamic errors, and type errors, an XPath 4.0 implementation may raise warnings, either during the static analysis phase or the dynamic evaluation phase. The circumstances in which warnings are raised, and the ways in which warnings are handled, are implementation-defined.

whitespace

A whitespace character is any of the characters defined by [http://www.w3.org/TR/REC-xml/#NT-S].

wildcard-matches

In these rules, if MU and NU are NameTestUnions, then MUwildcard-matchesNU is true if every name that matches MU also matches NU.

XDM instance

The term XDM instance is used, synonymously with the term value, to denote an unconstrained sequence of items.

XNode

An XNode is an instance of one of the node kinds defined in [XDM 4.0] section 7.1 XML Nodes.

XPath 1.0 compatibility mode

XPath 1.0 compatibility mode.This value is true if rules for backward compatibility with XPath Version 1.0 are in effect; otherwise it is false.

xs:anyAtomicType

xs:anyAtomicType is an atomic type that includes all atomic items (and no values that are not atomic). Its base type is xs:anySimpleType from which all simple types, including atomic, list, and union types, are derived. All primitive atomic types, such as xs:decimal and xs:string, have xs:anyAtomicType as their base type.

xs:dayTimeDuration

xs:dayTimeDuration is derived by restriction from xs:duration. The lexical representation of xs:dayTimeDuration is restricted to contain only day, hour, minute, and second components.

xs:error

xs:error is a simple type with no value space. It is defined in 3.16.7.3 xs:error XS11-1 and can be used in the 3.1 Sequence Types to raise errors.

xs:untyped

xs:untyped is used as the type annotation of an element node that has not been validated, or has been validated in skip mode.

xs:untypedAtomic

xs:untypedAtomic is an atomic type that is used to denote untyped atomic data, such as text that has not been assigned a more specific type.

xs:yearMonthDuration

xs:yearMonthDuration is derived by restriction from xs:duration. The lexical representation of xs:yearMonthDuration is restricted to contain only year and month components.

XTree

A tree that is rooted at a parentless XNode is referred to as an XTree.

zero-digit

zero-digit(M) is the character used in the picture string to represent the digit zero; the default value is U+0030 (DIGIT ZERO, 0) . This character must be a digit (category Nd in the Unicode property database), and it must have the numeric value zero. This property implicitly defines the ten Unicode characters that are used to represent the values 0 to 9 in the function output: Unicode is organized so that each set of decimal digits forms a contiguous block of characters in numerical sequence. Within the picture string any of these ten character can be used (interchangeably) as a place-holder for a mandatory digit. Within the final result string, these ten characters are used to represent the digits zero to nine.

I Change Log (Non-Normative)

  1. If a section of this specification has been updated since version 3.1, an overview of the changes is provided, along with links to navigate to the next or previous change.

    See 1 Introduction

  2. Sections with significant changes are marked with a ✭ symbol in the table of contents.

    See 1 Introduction

  3. PR 691 2154 

    Enumeration types are added as a new kind of ItemType, constraining the value space of strings.

    See 3.2.6 Enumeration Types

  4. Setting the default namespace for elements and types to the special value ##any causes an unprefixed element name to act as a wildcard, matching by local name regardless of namespace.

    See 3.2.7.2 Element Types

  5. The terms FunctionType, ArrayType, MapType, and RecordType replace FunctionTest, ArrayTest, MapTest, and RecordTest, with no change in meaning.

    See 3.2.8.1 Function Types

  6. Record types are added as a new kind of ItemType, constraining the value space of maps.

    See 3.2.8.3 Record Types

  7. Function coercion now allows a function with arity N to be supplied where a function of arity greater than N is expected. For example this allows the function true#0 to be supplied where a predicate function is required.

    See 3.4.4 Function Coercion

  8. The symbols × and ÷ can be used for multiplication and division.

    See 4.9 Arithmetic Expressions

  9. PR 1763 1830 

    The syntax on the right-hand side of an arrow operator has been relaxed; a dynamic function call no longer needs to start with a variable reference or a parenthesized expression, it can also be (for example) an inline function expression or a map or array constructor.

    See 4.21 Arrow Expressions

  10. The arrow operator => is now complemented by a “mapping arrow” operator =!> which applies the supplied function to each item in the input sequence independently.

    See 4.21.2 Mapping Arrow Expressions

  11. PR 1023 1128 

    It has been clarified that function coercion applies even when the supplied function item matches the required function type. This is to ensure that arguments supplied when calling the function are checked against the signature of the required function type, which might be stricter than the signature of the supplied function item.

    See 3.4.4 Function Coercion

  12. A dynamic function call can now be applied to a sequence of functions, and in particular to anthe empty sequence. This makes it easier to chain a sequence of calls.

    See 4.6.3.1 Evaluating Dynamic Function Calls

  13. The syntax document-node(N), where N is a NameTestUnion, is introduced as an abbreviation for document-node(element(N)). For example, document-node(*) matches any well-formed XML document (as distinct from a document fragment).

    See 3.2.7 Node Types

  14. QName literals are new in 4.0.

    See 4.3.1.3 QName Literals

  15. Path expressions are extended to handle JNodes (found in trees of maps and arrays) as well as XNodes (found in trees representing parsed XML).

    See 4.7 Path Expressions

  16. A method call invokes a function held as the value of an entry in a map, supplying the map implicitly as the value of the first argument.

    See 4.14.4 Method Calls

  17. The treat as expression now raises a type error rather than a dynamic error when it fails.

    See 4.18.5 Treat

  18. XPath 4.0 allows an XPath expression to be preceded by namespace declarations, allowing namespace prefixes to be bound within the XPath expression, rather than relying entirely on the host language to declare namespace prefixes.

    See 4.1 Namespace Declarations

  19. The group is considering removing or substantially changing this feature, it is considered at risk.

    See 4.14.5 Filter Expressions for Maps and Arrays

  20. PR 28 

    Multiple for and let clauses can be combined in an expression without an intervening return keyword.

    See 4.13.1 For Expressions

    See 4.13.2 Let Expressions

  21. PR 159 

    Keyword arguments are allowed on static function calls, as well as positional arguments.

    See 4.6.1.1 Static Function Call Syntax

  22. PR 202 

    The presentation of the rules for the subtype relationship between sequence types and item types has been substantially rewritten to improve clarity; no change to the semantics is intended.

    See 3.3 Subtype Relationships

  23. PR 230 

    The rules for “errors and optimization” have been tightened up to disallow many cases of optimizations that alter error behavior. In particular there are restrictions on reordering the operands of and and or, and of predicates in filter expressions, in a way that might allow the processor to raise dynamic errors that the author intended to prevent.

    See 2.5.5 Guarded Expressions

    See 4.12 Logical Expressions

  24. PR 254 

    The term "function conversion rules" used in 3.1 has been replaced by the term "coercion rules".

    See 3.4 Coercion Rules

    The coercion rules allow “relabeling” of a supplied atomic item where the required type is a derived atomic type: for example, it is now permitted to supply the value 3 when calling a function that expects an instance of xs:positiveInteger.

    See 3.4 Coercion Rules

  25. PR 284 

    Alternative syntax for conditional expressions is available: if (condition) { X }.

    See 4.15 Conditional Expressions

  26. PR 286 

    Element and attribute tests can include alternative names: element(chapter|section), attribute(role|class).

    See 3.2.7 Node Types

    The NodeTest in an AxisStep now allows alternatives: ancestor::(section|appendix)

    See 3.2.7 Node Types

    Element and attribute tests of the form element(N) and attribute(N) now allow N to be any NameTest, including a wildcard.

    See 3.2.7.2 Element Types

    See 3.2.7.3 Attribute Types

  27. PR 324 

    String templates provide a new way of constructing strings: for example `{$greeting}, {$planet}!` is equivalent to $greeting || ', ' || $planet || '!'

    See 4.10.2 String Templates

  28. PR 326 

    Support for higher-order functions is now a mandatory feature (in 3.1 it was optional).

    See 5 Conformance

  29. PR 344 

    A for member clause is added to FLWOR expressions to allow iteration over an array.

    See 4.13.1 For Expressions

  30. PR 368 

    The concept of the context item has been generalized, so it is now a context value. That is, it is no longer constrained to be a single item.

    See 2.2.2 Dynamic Context

  31. PR 433 

    Numeric literals can now be written in hexadecimal or binary notation; and underscores can be included for readability.

    See 4.3.1.1 Numeric Literals

  32. PR 519 

    The rules for tokenization have been largely rewritten. In some cases the revised specification may affect edge cases that were handled in different ways by different 3.1 processors, which could lead to incompatible behavior.

    See A.3 Lexical structure

  33. PR 521 

    New abbreviated syntax is introduced (focus function) for simple inline functions taking a single argument. An example is fn { ../@code }

    See 4.6.6 Inline Function Expressions

  34. PR 603 

    The rules for reporting type errors during static analysis have been changed so that a processor has more freedom to report errors in respect of constructs that are evidently wrong, such as @price/@value, even though dynamic evaluation is defined to return anthe empty sequence rather than an error.

    See 2.5.6 Implausible Expressions

    See 4.7.5.6 Implausible Axis Steps

  35. PR 606 

    Element and attribute tests of the form element(A|B) and attribute(A|B) are now allowed.

    See 3.2.7.2 Element Types

    See 3.2.7.3 Attribute Types

  36. PR 728 

    The syntax record(*) is allowed; it matches any map.

    See 3.2.8.3 Record Types

  37. PR 815 

    The coercion rules now allow conversion in either direction between xs:hexBinary and xs:base64Binary.

    See 3.4 Coercion Rules

  38. PR 911 

    The coercion rules now allow any numeric type to be implicitly converted to any other, for example an xs:double is accepted where the required type is xs:decimal.

    See 3.4 Coercion Rules

  39. PR 996 

    The value of a predicate in a filter expression can now be a sequence of integers.

    See 4.5 Filter Expressions

  40. PR 1031 

    An otherwise operator is introduced: A otherwise B returns the value of A, unless it is anthe empty sequence, in which case it returns the value of B.

    See 4.16 Otherwise Expressions

  41. PR 1071 

    In map constructors, the keyword map is now optional, so map { 0: false(), 1: true() } can now be written { 0: false(), 1: true() }, provided it is used in a context where this creates no ambiguity.

    See 4.14.1.1 Map Constructors

  42. PR 1131 

    A positional variable can be defined in a for expression.

    See 4.13.1 For Expressions

    The type of a variable used in a for expression can be declared.

    See 4.13.1 For Expressions

    The type of a variable used in a let expression can be declared.

    See 4.13.2 Let Expressions

  43. PR 1132 

    Choice item types (an item type allowing a set of alternative item types) are introduced.

    See 3.2.5 Choice Item Types

  44. PR 1163 

    Filter expressions for maps and arrays are introduced.

    See 4.14.5 Filter Expressions for Maps and Arrays

  45. PR 1181 

    The default namespace for elements and types can be set to the value ##any, allowing unprefixed names in axis steps to match elements with a given local name in any namespace.

    See 2.2.1 Static Context

    If the default namespace for elements and types has the special value ##any, then an unprefixed name in a NameTest acts as a wildcard, matching names in any namespace or none.

    See 4.7.5.2 Node Tests

  46. PR 1197 

    The keyword fn is allowed as a synonym for function in function types, to align with changes to inline function declarations.

    See 3.2.8.1 Function Types

    In inline function expressions, the keyword function may be abbreviated as fn.

    See 4.6.6 Inline Function Expressions

  47. PR 1212 

    New keywords introducing item types, such as record, item, and enum, have been added to the list of reserved function names.

    See A.4 Reserved Function Names

  48. PR 1217 

    Predicates in filter expressions for maps and arrays can now be numeric.

    See 4.14.5 Filter Expressions for Maps and Arrays

  49. PR 1249 

    A for key/value clause is added to FLWOR expressions to allow iteration over maps.

    See 4.13.1 For Expressions

  50. PR 1250 

    Several decimal format properties, including minus sign, exponent separator, percent, and per-mille, can now be rendered as arbitrary strings rather than being confined to a single character.

    See 2.2.1.2 Decimal Formats

  51. PR 1265 

    The rules regarding the document-uri property of nodes returned by the fn:collection function have been relaxed.

    See 2.2.2 Dynamic Context

  52. PR 1344 

    Parts of the static context that were there purely to assist in static typing, such as the statically known documents, were no longer referenced and have therefore been dropped.

    See 2.2.1 Static Context

    The static typing option has been dropped.

    See 2.4 Processing Model

    The static typing feature has been dropped.

    See 5 Conformance

  53. PR 1361 

    The term atomic value has been replaced by atomic item.

    See 2.1.3 Values

  54. PR 1384 

    If a type declaration is present, the supplied values in the input sequence are now coerced to the required type. Type declarations are now permitted in XPath as well as XQuery.

    See 4.17 Quantified Expressions

  55. PR 1496 

    The context value static type, which was there purely to assist in static typing, has been dropped.

    See 2.2.1 Static Context

  56. PR 1498 

    The EBNF operators ++ and ** have been introduced, for more concise representation of sequences using a character such as "," as a separator. The notation is borrowed from Invisible XML.

    See 2.1 Terminology

    The EBNF notation has been extended to allow the constructs (A ++ ",") (one or more occurrences of A, comma-separated, and (A ** ",") (zero or more occurrences of A, comma-separated.

    See 2.1.1 Grammar Notation

    The EBNF operators ++ and ** have been introduced, for more concise representation of sequences using a character such as "," as a separator. The notation is borrowed from Invisible XML.

    See A.1 EBNF

    See A.1.1 Notation

  57. PR 1501 

    The coercion rules now apply recursively to the members of an array and the entries in a map.

    See 3.4 Coercion Rules

  58. PR 1532 

    Four new axes have been defined: preceding-or-self, preceding-sibling-or-self, following-or-self, and following-sibling-or-self.

    See 4.7.5.1 Axes

  59. PR 1577 

    The syntax record() is allowed; the only thing it matches is anthe empty map.

    See 3.2.8.3 Record Types

  60. PR 1686 

    With the pipeline operator ->, the result of an expression can be bound to the context value before evaluating another expression.

    See 4.19 Pipeline operator

  61. PR 1696 

    Parameter names may be included in a function signature; they are purely documentary.

    See 3.2.8.1 Function Types

  62. PR 1703 

    Ordered maps are introduced.

    See 4.14.1 Maps

    The order of key-value pairs in the map constructor is now retained in the constructed map.

    See 4.14.1.1 Map Constructors

  63. PR 1874 

    The coercion rules now reorder the entries in a map when the required type is a record type.

    See 3.4 Coercion Rules

  64. PR 1898 

    The rules for subtyping of document node types have been refined.

    See 3.3.2.5.2 Subtyping Nodes: Document Nodes

  65. PR 1991 

    Named record types used in the signatures of built-in functions are now available as standard in the static context.

    See 2.2.1 Static Context

  66. PR 2031 

    The terms XNode and JNode are introduced; the existing term node remains in use as a synonym for XNode where the context does not specify otherwise.

    See 2.1.3 Values

    JNodes are introduced

    See 3.2.9 JNode Types

    See 3.2.10 Generalized Node Types

  67. PR 2055 

    Sequences, arrays, and maps can be destructured in a let expression to extract their components into multiple variables.

    See 4.13.2 Let Expressions

  68. PR 2094 

    A general expression is allowed within a map constructor; this facilitates the creation of maps in which the presence or absence of particular keys is decided dynamically.

    See 4.14.1.1 Map Constructors

  69. PR 2115 

    This section describes and formalizes a convention that was already in use, but not explicitly stated, in earlier versions of the specification.

    See 2.1.2 Expression Names

  70. PR 2130 

    Operator is-not is introduced, as a complement to the operator is.

    See 4.11.3 GNode Comparisons

    Operators precedes and follows are introduced as synonyms for operators << and >>.

    See 4.11.3 GNode Comparisons

  71. PR 2134 

    The lookup operator ? can now be followed by an arbitrary literal, for cases where keys are items other than integers or NCNames. It can also be followed by a variable reference or a context value reference.

    See 4.14.3 Lookup Expressions

  72. PR 2176 

    Operators precedes-or-is and follows-or-is are introduced as synonyms for the union of operators << and is and for the union of operators >> and is, respectively.

    See 4.11.3 GNode Comparisons

  73. PR 2202 

    The type schema-element(N) is now defined to be a subtype of element() and of various other element tests.

    See 3.3.2.5.3 Subtyping Nodes: Elements

    The type schema-attribute(N) is now defined to be a subtype of attribute() and of various other attribute tests.

    See 3.3.2.5.4 Subtyping Nodes: Attributes

  74. PR 2213 

    This section (“External Resources and Security”) is new.

    See 2.3 External Resources and Security

  75. PR 2218 

    The rules for value comparisons when comparing values of different types (for example, decimal and double) have changed to be transitive. A decimal value is no longer converted to double, instead the double is converted to a decimal without loss of precision. This may affect compatibility in edge cases involving comparison of values that are numerically very close.

    See 4.11.1 Value Comparisons

    The rules for comparing untyped atomic items with numeric values have changed. Rather than converting an untyped atomic item unconditionally to xs:double, it is now converted to the type of the numeric operand. This is designed to ensure that comparisons such as <a>1.1</a> = 1.1 succeed, given that the values will now be compared as decimals rather than as doubles.

    See 4.11.2 General Comparisons

  76. PR 2227 

    A URIQualifiedName may now supply a prefix as well as a URI and local name.

    See 2.1.4 Namespaces and QNames

  77. PR 2256 

    An ordering is now defined for all data types.

    See 4.11.1 Value Comparisons