<?xml version="1.0" encoding="UTF-8"?>
<!--XSLT Processor: Saxonica-->
<!--XSLT Processor: Saxonica-->
<!DOCTYPE spec
  SYSTEM "../../../schema/xsl-query.dtd">
<spec xmlns:e="http://www.w3.org/1999/XSL/Spec/ElementSyntax"
      id="spec-top"
      w3c-doctype="wd"
      status="ext-review">
   <header id="id-spec-header">
      <title>XPath 4.0</title>
      <version>WG Review Draft</version>
      <w3c-designation>WD-xpath-40</w3c-designation>
      <w3c-doctype>W3C Editor's Draft</w3c-doctype>
      <pubdate>
         <day>01</day>
         <month>January</month>
         <year>2000</year>
      </pubdate>
      <publoc>
         <loc xmlns:xlink="http://www.w3.org/1999/xlink"
              href="https://qt4cg.org/specifications/xpath-40/"
              xlink:type="simple"
              xlink:show="replace"
              xlink:actuate="onRequest">https://qt4cg.org/specifications/xpath-40/</loc>
      </publoc>
      <!-- These altlocs URIs are computed from the concatenation of doc.public, doc.shortname, and either '.xml' or
     '-diff-from-yyyymmdd.html', where 'yyyymmdd' is the earlier version of the spec from which a diff has been produced -->
      <altlocs>
         <loc xmlns:xlink="http://www.w3.org/1999/xlink"
              href="xpath-40.xml"
              xlink:type="simple"
              xlink:show="replace"
              xlink:actuate="onRequest">XML</loc>
      </altlocs>
      <!-- The latestloc URI is computed from doc.latestloc -->
      <!--<latestloc doc="&language;">
  <loc xmlns:xlink="http://www.w3.org/1999/xlink" href="&doc.latestloc;" xlink:type="simple" xlink:show="replace" xlink:actuate="onRequest">&doc.latestloc;</loc>
</latestloc>-->
      <!-- These prevlocs URIs are always hard-coded and are never computed from entities -->
      <!-- Pubrules doesn't like FPWD to have a prevloc, not even a previous Recommendation -->
      <!--<prevlocs doc="&language;">
  <loc role="xquery" xmlns:xlink="http://www.w3.org/1999/xlink" href="https://www.w3.org/TR/2017/PR-xquery-31-20170117/" xlink:type="simple" xlink:show="replace" xlink:actuate="onRequest">https://www.w3.org/TR/2017/PR-xquery-31-20170117/</loc>
  <loc role="xquery" xmlns:xlink="http://www.w3.org/1999/xlink" href="https://www.w3.org/TR/2016/CR-xquery-31-20161213/" xlink:type="simple" xlink:show="replace" xlink:actuate="onRequest">https://www.w3.org/TR/2016/CR-xquery-31-20161213/</loc>
  <loc role="xquery" xmlns:xlink="http://www.w3.org/1999/xlink" href="https://www.w3.org/TR/2015/CR-xquery-31-20151217/" xlink:type="simple" xlink:show="replace" xlink:actuate="onRequest">https://www.w3.org/TR/2015/CR-xquery-31-20151217/</loc>
  <loc role="xquery" xmlns:xlink="http://www.w3.org/1999/xlink" href="https://www.w3.org/TR/2014/CR-xquery-31-20141218/" xlink:type="simple" xlink:show="replace" xlink:actuate="onRequest">https://www.w3.org/TR/2014/CR-xquery-31-20141218/</loc>
  <loc role="xquery" xmlns:xlink="http://www.w3.org/1999/xlink" href="https://www.w3.org/TR/2014/WD-xquery-31-20141007/" xlink:type="simple" xlink:show="replace" xlink:actuate="onRequest">https://www.w3.org/TR/2014/WD-xquery-31-20141007/</loc>
  <loc role="xquery" xmlns:xlink="http://www.w3.org/1999/xlink" href="https://www.w3.org/TR/2014/WD-xquery-31-20140424/" xlink:type="simple" xlink:show="replace" xlink:actuate="onRequest">https://www.w3.org/TR/2014/WD-xquery-31-20140424/</loc>
  <loc role="xpath" xmlns:xlink="http://www.w3.org/1999/xlink" href="https://www.w3.org/TR/2017/PR-xpath-31-20170117/" xlink:type="simple" xlink:show="replace" xlink:actuate="onRequest">https://www.w3.org/TR/2017/PR-xpath-31-20170117/</loc>
  <loc role="xpath" xmlns:xlink="http://www.w3.org/1999/xlink" href="https://www.w3.org/TR/2016/CR-xpath-31-20161213/" xlink:type="simple" xlink:show="replace" xlink:actuate="onRequest">https://www.w3.org/TR/2016/CR-xpath-31-20161213/</loc>
  <loc role="xpath" xmlns:xlink="http://www.w3.org/1999/xlink" href="https://www.w3.org/TR/2015/CR-xpath-31-20151217/" xlink:type="simple" xlink:show="replace" xlink:actuate="onRequest">https://www.w3.org/TR/2015/CR-xpath-31-20151217/</loc>
  <loc role="xpath" xmlns:xlink="http://www.w3.org/1999/xlink" href="https://www.w3.org/TR/2014/CR-xpath-31-20141218/" xlink:type="simple" xlink:show="replace" xlink:actuate="onRequest">https://www.w3.org/TR/2014/CR-xpath-31-20141218/</loc>
  <loc role="xpath" xmlns:xlink="http://www.w3.org/1999/xlink" href="https://www.w3.org/TR/2014/WD-xpath-31-20141007/" xlink:type="simple" xlink:show="replace" xlink:actuate="onRequest">https://www.w3.org/TR/2014/WD-xpath-31-20141007/</loc>
  <loc role="xpath" xmlns:xlink="http://www.w3.org/1999/xlink" href="https://www.w3.org/TR/2014/WD-xpath-31-20140424/" xlink:type="simple" xlink:show="replace" xlink:actuate="onRequest">https://www.w3.org/TR/2014/WD-xpath-31-20140424/</loc>
</prevlocs>
-->
      <!--
<latestloc-major doc="&language-major;">
  <loc href="&doc.latestloc-major;">&doc.latestloc-major;</loc>
</latestloc-major>
-->
      <latestloc-tech doc="XPath">
         <loc xmlns:xlink="http://www.w3.org/1999/xlink"
              href="https://qt4cg.org/specifications/xpath-40/"
              xlink:type="simple"
              xlink:show="replace"
              xlink:actuate="onRequest">https://qt4cg.org/specifications/xpath-40/</loc>
      </latestloc-tech>
      <prevrec doc="XPath">
         <loc xmlns:xlink="http://www.w3.org/1999/xlink"
              role="xpath"
              href="https://www.w3.org/TR/2017/REC-xpath-31-20170321/"
              xlink:type="simple"
              xlink:show="replace"
              xlink:actuate="onRequest">https://www.w3.org/TR/2017/REC-xpath-31-20170321/</loc>
      </prevrec>
      <authlist>
         <author>
            <name>Michael Kay</name>
            <affiliation>Saxonica</affiliation>
            <email xmlns:xlink="http://www.w3.org/1999/xlink"
                   href="http://www.saxonica.com/"
                   xlink:type="simple"
                   xlink:show="new"
                   xlink:actuate="onRequest">http://www.saxonica.com/</email>
         </author>
      </authlist>
      <status>
         <p>
            <emph>This section describes the status of this document at the time of its publication.
               Other documents may supersede this document.</emph>
         </p>
         <p>This document is a working draft developed and maintained by a W3C Community Group,
            the <loc xmlns:xlink="http://www.w3.org/1999/xlink"
                 href="https://www.w3.org/community/xslt-40/"
                 xlink:type="simple"
                 xlink:show="replace"
                 xlink:actuate="onRequest">XQuery and XSLT Extensions Community Group</loc>
            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.</p>
         <p>The community group welcomes comments on the specification. Comments are best submitted
         as issues on the group's <loc xmlns:xlink="http://www.w3.org/1999/xlink"
                 href="https://github.com/qt4cg/qtspecs/issues"
                 xlink:type="simple"
                 xlink:show="replace"
                 xlink:actuate="onRequest">GitHub repository</loc>.</p>
         <?at-risk?>
         <p>The community group maintains two extensive test suites, 
            one oriented to XQuery and XPath, the other to XSLT.
         These can be found at <loc xmlns:xlink="http://www.w3.org/1999/xlink"
                 href="https://github.com/qt4cg/qt4tests"
                 xlink:type="simple"
                 xlink:show="replace"
                 xlink:actuate="onRequest">qt4tests</loc> and
         <loc xmlns:xlink="http://www.w3.org/1999/xlink"
                 href="https://github.com/qt4cg/xslt40-test"
                 xlink:type="simple"
                 xlink:show="replace"
                 xlink:actuate="onRequest">xslt40-test</loc> 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.</p>
         <note role="dedication" id="dedication">
            <p role="xpath">The publications of this community group are dedicated to our co-chair,
Michael Sperberg-McQueen (1954–2024).</p>
            <p role="xpath">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.</p>
         </note>
      </status>
      <!--* N.B. the value of the errataloc href attribute is set in
    * ../style/assemble-spec.xsl
    * when the XQuery or XPath spec is assembled.  If it changes,
    * change it THERE.
    *-->
      <!--<errataloc
 role="spec-conditional"
 href="https://www.w3.org/XML/2017/qt-errata/xquery-31-errata.html"
 xlink:type="simple"/>


<translationloc
 role="spec-conditional"
 href="http://www.w3.org/2003/03/Translations/byTechnology?technology=xquery-31"/>
-->
      <!--&status-section;-->
      <!--<status>
    <p>This is a draft prepared by the QT4CG (officially registered in W3C as the
      XSLT Extensions Community Group). Comments are invited.</p>
-->
      <!--</status>-->
      <abstract id="id-abstract">
         <p role="xpath" diff="chg">

XPath 4.0 is an expression language that allows the processing of
values conforming to the data model defined in
<bibref ref="xpath-datamodel-40"/>. 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 <bibref ref="xpath-functions-40"/>.</p>
         <p role="xpath" diff="chg">XPath 4.0 is a superset of XPath 3.1. A detailed list of changes
made since XPath 3.1 can be found in <specref ref="id-revision-log"/>. 
</p>
      </abstract>
      <langusage>
         <language id="EN">English</language>
         <!--
<language id="ebnf">EBNF</language>
-->
      </langusage>
      <revisiondesc id="id-DOESNOTEXIST">
         <slist>
            <sitem>XQuery 4.0 First Public Working Draft. (#####)</sitem>
         </slist>
      </revisiondesc>
   </header>
   <body>
      <div1 id="id-introduction">
         <head>Introduction</head>
         <changes>
            <change>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.</change>
            <change>Sections with significant changes are marked with a ✭ symbol in the
        table of contents.</change>
         </changes>
         <p role="xpath" diff="chg" at="2023-10-19">XPath was originally designed as an expression language 
		to address the nodes of XML trees; it has since been extended to address a variety of non-XML data sources. 
		XPath gets its name from its use of a path notation for
		navigating through the hierarchical structure of an XML document; similar capabilities for
		navigating JSON structures were added in versions 3.0 and 3.1. XPath uses a compact,
		non-XML syntax, allowing XPath expressions to be embedded within URIs and to be used as 
		XML attribute values. XPath is designed to be embedded in (or invoked from) other
		host languages, including both languages specialized towards XML processing (such as <bibref ref="xslt-40"/> and XSD),
	   and general purpose programming languages such as Java, C#, Python, and Javascript. The interface
	   between XPath and its host language is formalized with an abstract definition of a static and dynamic
	   context, made available by the host language to the XPath processor.</p>
         <p diff="chg" at="2023-10-19" role="xpath">
            <termdef id="dt-host-language" term="host language">
		A <term>host language</term> 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.
	</termdef>
         </p>
         <p>
            <termdef id="dt-datamodel" term="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 <term>data model</term>, is defined in <bibref ref="xpath-datamodel-40"/>.</termdef>
         </p>
         <p>
            <phrase role="xpath">XPath 4.0 is a subset of XQuery 4.0.</phrase>

 In general, any expression that is
		syntactically valid and executes successfully in both XPath 4.0 and XQuery 4.0 will return
		the same result in both languages. There are a few exceptions to this rule: <ulist>
               <item>
                  <p>Because XQuery expands 
					<phrase role="xpath"> predefined entity references and character references
					</phrase> and XPath does not, expressions containing these produce different
					results in the two languages. For instance, the value of the string literal
						<code role="parse-test" nobreak="false">"&amp;amp;"</code> is <code nobreak="false">&amp;</code> in XQuery,
					and <code nobreak="false">&amp;amp;</code> in XPath. (A host language may expand predefined entity references or character references
					before the XPath expression is evaluated.)</p>
               </item>
               <item>
                  <p>If XPath 1.0 compatibility mode is enabled, XPath behaves differently from
					XQuery in a number of ways, <phrase role="xpath">which are noted throughout this
						document, and listed in <specref ref="id-incompat-in-false-mode"/>.</phrase>
                  </p>
               </item>
            </ulist>
         </p>
         <p>Because these languages are so closely related, their grammars and language descriptions are
		generated from a common source to ensure consistency.</p>
         <p>XPath 4.0 also depends on and is closely related to the following specifications:</p>
         <ulist>
            <item>
               <p>
                  <bibref ref="xpath-datamodel-40"/> defines the data model that underlies all
				XPath 4.0 expressions.</p>
            </item>
            <item>
               <p>The type system of XPath 4.0 is based on XML Schema. It is implementation-defined
				whether the type system is based on <bibref ref="XMLSchema10"/> or <bibref ref="XMLSchema11"/>.</p>
            </item>
            <item>
               <p>The system function library and the operators supported by XPath 4.0 are defined
				in <bibref ref="xpath-functions-40"/>.</p>
            </item>
         </ulist>
         <note diff="add" at="2023-10-19">
            <p>The XML-based syntax for XQuery known as XQueryX
		is no longer maintained.</p>
         </note>
         <p>This document specifies a grammar for XPath 4.0, using the same basic EBNF notation used in
			<bibref ref="XML"/>. Unless otherwise noted (see <specref ref="lexical-structure"/>),
		whitespace is not significant in <phrase role="xpath">expressions</phrase>. Grammar productions are introduced together with the features
		that they describe, and a complete grammar is also presented in the appendix [<specref ref="nt-bnf"/>]. The appendix is the normative version.</p>
         <p>In the grammar productions in this document, named symbols are underlined and literal text is
		enclosed in double quotes. For example, the following productions describe the syntax of a
		static function call:</p>
         <scrap role="example" headstyle="show">
            <prod id="example-example-doc-xpath40-FunctionCall">
               <lhs>FunctionCall</lhs>
               <rhs>
                  <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                  <nt def="prod-xpath40-ArgumentList">ArgumentList<!--$idref_lang_part = xpath40- --></nt>
               </rhs>
               <com>
                  <loc href="#parse-note-reserved-function-names">xgc: reserved-function-names</loc>
               </com>
               <com>
                  <loc href="#parse-note-parens">gn: parens</loc>
               </com>
            </prod>

            <prod id="example-example-doc-xpath40-FunctionCall-EQName">
               <lhs>EQName</lhs>
               <rhs>
                  <nt def="prod-xpath40-QName">QName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$idref_lang_part = xpath40- --></nt>
               </rhs>
            </prod>

            <prod id="example-example-doc-xpath40-FunctionCall-ArgumentList">
               <lhs>ArgumentList</lhs>
               <rhs>"("  ((<nt def="prod-xpath40-PositionalArguments">PositionalArguments<!--$idref_lang_part = xpath40- --></nt>  (","  <nt def="prod-xpath40-KeywordArguments">KeywordArguments<!--$idref_lang_part = xpath40- --></nt>)?)  |  <nt def="prod-xpath40-KeywordArguments">KeywordArguments<!--$idref_lang_part = xpath40- --></nt>)?  ")"</rhs>
            </prod>

            <prod id="example-example-doc-xpath40-FunctionCall-PositionalArguments">
               <lhs>PositionalArguments</lhs>
               <rhs>(<nt def="prod-xpath40-Argument">Argument<!--$idref_lang_part = xpath40- --></nt> ++ ",")</rhs>
            </prod>

            <prod id="example-example-doc-xpath40-FunctionCall-Argument">
               <lhs>Argument</lhs>
               <rhs>
                  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ArgumentPlaceholder">ArgumentPlaceholder<!--$idref_lang_part = xpath40- --></nt>
               </rhs>
            </prod>

            <prod id="example-example-doc-xpath40-FunctionCall-ExprSingle">
               <lhs>ExprSingle</lhs>
               <rhs>
                  <nt def="prod-xpath40-ForExpr">ForExpr<!--$idref_lang_part = xpath40- --></nt>
                  <br/>|  <nt def="prod-xpath40-LetExpr">LetExpr<!--$idref_lang_part = xpath40- --></nt>
                  <br/>|  <nt def="prod-xpath40-QuantifiedExpr">QuantifiedExpr<!--$idref_lang_part = xpath40- --></nt>
                  <br/>|  <nt def="prod-xpath40-IfExpr">IfExpr<!--$idref_lang_part = xpath40- --></nt>
                  <br/>|  <nt def="prod-xpath40-OrExpr">OrExpr<!--$idref_lang_part = xpath40- --></nt>
               </rhs>
            </prod>

            <prod id="example-example-doc-xpath40-FunctionCall-ArgumentPlaceholder">
               <lhs>ArgumentPlaceholder</lhs>
               <rhs>"?"</rhs>
            </prod>

            <prod id="example-example-doc-xpath40-FunctionCall-KeywordArguments">
               <lhs>KeywordArguments</lhs>
               <rhs>(<nt def="prod-xpath40-KeywordArgument">KeywordArgument<!--$idref_lang_part = xpath40- --></nt> ++ ",")</rhs>
            </prod>

            <prod id="example-example-doc-xpath40-FunctionCall-KeywordArgument">
               <lhs>KeywordArgument</lhs>
               <rhs>
                  <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>  ":="  <nt def="prod-xpath40-Argument">Argument<!--$idref_lang_part = xpath40- --></nt>
               </rhs>
            </prod>
         </scrap>
         <p>The productions should be read as follows: A function call consists of an <nt def="doc-xpath40-EQName">EQName<!--$spec = xpath40--></nt> followed by an <nt def="prod-xpath40-ArgumentList">ArgumentList<!--$spec = xpath40--></nt>. The
		argument list consists of an opening parenthesis, an optional list of one or more arguments
		(separated by commas), and a closing parenthesis.</p>
         <p>This document normatively defines the static and dynamic semantics of XPath 4.0. In this
		document, examples and material labeled as “Note” are provided for explanatory purposes and
		are not normative.</p>
      </div1>
      <div1 id="id-basics">
         <head>Basics</head>
         <div2 id="id-terminology">
            <head>Terminology</head>
            <changes>
               <change issue="1366" PR="1498">The EBNF operators <code nobreak="false">++</code> and <code nobreak="false">**</code>
      have been introduced, for more concise representation of sequences using a character
      such as <code nobreak="false">","</code> as a separator. The notation is borrowed from Invisible XML.</change>
            </changes>
            <p>The basic building block of XPath 4.0 is the
	 <term>expression</term>, which is a string of <bibref ref="Unicode"/> characters; the version of Unicode to be used is <termref def="dt-implementation-defined">implementation-defined</termref>.
	 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. 
      </p>
            <note>
               <p>This specification contains no
assumptions or requirements regarding the character set encoding of strings
of <bibref ref="Unicode"/> characters.</p>
            </note>
            <p>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 <specref ref="id-reserved-fn-names"/>.</p>
            <p>In this specification the phrases <rfc2119>must</rfc2119>, <rfc2119>must
                  not</rfc2119>, <rfc2119>should</rfc2119>, <rfc2119>should not</rfc2119>,
                  <rfc2119>may</rfc2119>, <rfc2119>required</rfc2119>, and
                  <rfc2119>recommended</rfc2119>, when used in normative
                  text and rendered in small capitals, are to be interpreted as described in
                  <bibref ref="RFC2119"/>.</p>
            <p>Certain aspects of language processing are described in this specification as
			<term>implementation-defined</term> or <term>implementation-dependent</term>.</p>
            <ulist>
               <item>
                  <p>
                     <termdef id="dt-implementation-defined" term="implementation defined">
                        <term>Implementation-defined</term> indicates an aspect that may differ
					between implementations, but must be specified by the implementer for each
					particular implementation.</termdef>
                  </p>
               </item>
               <item>
                  <p>
                     <termdef id="dt-implementation-dependent" term="implementation   dependent">
                        <term>Implementation-dependent</term> 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.</termdef>
                  </p>
               </item>
            </ulist>
            <p role="xpath">A language aspect described in this specification as
			<term>implementation-defined</term> or <term>implementation dependent</term> may be
		further constrained by the specifications of a host language in which XPath is embedded.</p>
            <div3 id="id-ebnf-introduction">
               <head>Grammar Notation</head>
               <changes>
                  <change issue="1366" PR="1498" date="2024-10-30">
                  The EBNF notation has been extended to allow the constructs <code nobreak="false">(A ++ ",")</code>
                  (one or more occurrences of <code nobreak="false">A</code>, comma-separated, and <code nobreak="false">(A ** ",")</code>
                  (zero or more occurrences of <code nobreak="false">A</code>, comma-separated.
               </change>
               </changes>
               <p>The grammar of XPath 4.0 is defined using a version of EBNF defined
            in <specref ref="EBNFNotation"/>. The notation is based on the EBNF dialect used in the
            XML specification, with two notable additions derived from the Invisible XML grammar:</p>
               <p>
                  <code nobreak="false">(A ++ ",")</code> represents a sequence of one or more comma-separated
               occurrences of <code nobreak="false">A</code>.</p>
               <p>
                  <code nobreak="false">(A ** ",")</code> represents a sequence of zero or more comma-separated
               occurrences of <code nobreak="false">A</code>.</p>
               <p>For example the following production rule indicates that an <code nobreak="false">Expr</code>
            consists of one or more occurrences of <code nobreak="false">ExprSingle</code>, separated by commas:</p>
               <scrap role="example" headstyle="show">
                  <prod id="example-example-doc-xpath40-Expr">
                     <lhs>Expr</lhs>
                     <rhs>(<nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt> ++ ",")</rhs>
                  </prod>

                  <prod id="example-example-doc-xpath40-Expr-ExprSingle">
                     <lhs>ExprSingle</lhs>
                     <rhs>
                        <nt def="prod-xpath40-ForExpr">ForExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-LetExpr">LetExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-QuantifiedExpr">QuantifiedExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-IfExpr">IfExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-OrExpr">OrExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>
               </scrap>
               <p>In principle any production can be used for the separator, but in practice this notation
            is only used in cases where the separator is a simple constant string.</p>
               <p>EBNF grammar rules appear throughout the specification for ease of reference, and the
            entire grammar is summarized in <specref ref="id-grammar"/>.
            <phrase role="xpath">For XPath 4.0, the top-level production rule is 
            <nt def="doc-xpath40-XPath">XPath<!--$spec = xpath40--></nt>, representing an XPath expression.</phrase>
               </p>
            </div3>
            <div3 id="id-expression-names">
               <head>Expression Names</head>
               <changes>
                  <change issue="2084" PR="2115" date="2025-07-23">
                  This section describes and formalizes a convention that was already in use,
                  but not explicitly stated, in earlier versions of the specification.
               </change>
               </changes>
               <p>Many grammatical production rules for expressions 
               take a form similar to:</p>
               <scrap role="example" headstyle="show">
                  <prod id="example-example-doc-xpath40-RangeExpr">
                     <lhs>RangeExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-AdditiveExpr">AdditiveExpr<!--$idref_lang_part = xpath40- --></nt>  ("to"  <nt def="prod-xpath40-AdditiveExpr">AdditiveExpr<!--$idref_lang_part = xpath40- --></nt>)?</rhs>
                  </prod>

                  <prod id="example-example-doc-xpath40-RangeExpr-AdditiveExpr">
                     <lhs>AdditiveExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-MultiplicativeExpr">MultiplicativeExpr<!--$idref_lang_part = xpath40- --></nt>  (("+"  |  "-")  <nt def="prod-xpath40-MultiplicativeExpr">MultiplicativeExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
                  </prod>
               </scrap>
               <p>In describing the semantics of the language, we adopt the convention that a
               term such as <term>range expression</term> (written in bold, or hyperlinked to its definition)
               refers to a non-trivial instance of the production named <nt def="doc-xpath40-RangeExpr">RangeExpr<!--$spec = xpath40--></nt>. More
               specifically, it refers to an instance of the production in which the optional part
               (<code nobreak="false">to AdditiveExpr</code>) is actually present. The construct <code nobreak="false">$n + 1</code>,
               being an <nt def="doc-xpath40-AdditiveExpr">AdditiveExpr<!--$spec = xpath40--></nt>, is technically an instance of <nt def="doc-xpath40-RangeExpr">RangeExpr<!--$spec = xpath40--></nt>,
               but it is not a <term>range expression</term> under this definition.</p>
               <p>
                  <termdef id="dt-non-trivial" term="non-trivial">A construct is said to be a
            <term>non-trivial</term> instance of a grammatical production if it is not also
            an instance of one of its sub-productions.</termdef>
               </p>
            </div3>
            <div3 id="id-values">
               <head>Values</head>
               <changes>
                  <change issue="1337" PR="1361" date="2024-08-02">
               The term <term>atomic value</term> has been replaced by <termref def="dt-atomic-item"/>.
            </change>
                  <change issue="2025" PR="2031" date="2025-06-13">
               The terms <term>XNode</term> and <code nobreak="false">JNode</code> are introduced; the existing
               term <term>node</term> remains in use as a synonym for <term>XNode</term> where
               the context does not specify otherwise.
            </change>
               </changes>
               <p>
                  <termdef term="value" id="dt-value">In the <termref def="dt-datamodel">data model</termref>, a <term>value</term> is always a <termref def="dt-sequence">sequence</termref>.</termdef>
               </p>
               <p>
                  <termdef id="dt-sequence" term="sequence">A
<term>sequence</term> is an ordered collection of zero or more
<termref def="dt-item">items</termref>.</termdef>
               </p>
               <p>
                  <termdef id="dt-item" term="item">
  An <term>item</term> is either an <termref def="dt-atomic-item">atomic item</termref>, a <termref def="dt-node">node</termref>,
or a <termref def="dt-function-item">function item</termref>.</termdef>
               </p>
               <p>
                  <termdef id="dt-atomic-item" term="atomic item">An <term>atomic
	 item</term> is a value in the value space of an <term>atomic
	 type</term>, as defined in <bibref ref="XMLSchema10"/>  or <bibref ref="XMLSchema11"/>.</termdef>
               </p>
               <p>
                  <termdef id="dt-XNode" term="XNode">An <term>XNode</term> is an instance of one of the
	  <term>node kinds</term> defined in <xspecref spec="DM40" ref="nodes"/>.</termdef>
Each XNode has a unique <term>node identity</term>, a <term>typed value</term>, and a <term>string value</term>. 
            In addition, some XNodes have a <term>name</term>. The <term>typed value</term> of an XNode is a sequence
	 of zero or more atomic items. The <term>string value</term> of an XNode is a
	 value of type <code nobreak="false">xs:string</code>. The <term>name</term> of an XNode is a value of type <code nobreak="false">xs:QName</code>.</p>
               <p>
                  <termdef id="dt-node" term="node">Except where the context indicates otherwise, the term
         <term>node</term> is used as a synonym for <termref def="dt-XNode"/>.</termdef>
               </p>
               <p>
                  <termdef id="dt-JNode" term="JNode">A <term>JNode</term> (see also <xspecref spec="DM40" ref="id-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.</termdef>
               </p>
               <p>
                  <termdef id="dt-GNode" term="GNode">A <term>GNode</term> (for <emph>generalized node</emph>)
               is either an <termref def="dt-XNode"/> or a <termref def="dt-JNode"/>.</termdef>
               </p>
               <p>
                  <termdef id="dt-function-item" term="function item">A <term>function item</term> is an item that can
         be called using a <termref def="dt-dynamic-function-call"/>.</termdef>
               </p>
               <p>Maps (see <specref ref="id-maps"/>) and arrays (see <specref ref="id-arrays"/>) are
         specific kinds of <termref def="dt-function-item"/>s.</p>
               <p>
                  <termdef id="dt-singleton" term="singleton">A sequence containing exactly one item is called a
	 <term>singleton</term>.</termdef> 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). </p>
               <p>
                  <termdef id="dt-empty-sequence" term="empty sequence">The sequence containing zero items is called the <term>empty sequence</term>.</termdef>
               </p>
               <p>
                  <termdef id="dt-data-model-instance" term="XDM instance">The term <term>XDM instance</term> is used,
    synonymously with the term <termref def="dt-value">value</termref>, to denote an unconstrained
    <termref def="dt-sequence">sequence</termref> of <termref def="dt-item">items</termref>.</termdef>
               </p>
               <!-- -->
            </div3>
            <div3 id="id-namespaces-and-qnames">
               <head>Namespaces and QNames</head>
               <changes>
                  <change issue="2079" PR="2227" date="2025-10-03">A <code nobreak="false">URIQualifiedName</code> may now supply a prefix
            as well as a URI and local name.</change>
               </changes>
               <p>
                  <termdef id="dt-namespace-binding" term="namespace binding">A <term>namespace binding</term>
         is a pair comprising a namespace prefix (which is either an <code nobreak="false">xs:NCName</code> or empty),
         and a namespace URI.</termdef>
               </p>
               <p>Element nodes have a property called <term>in-scope namespaces</term>. <termdef term="in-scope namespaces" id="dt-in-scope-namespaces">The <term>in-scope namespaces</term> property of an element node is a set of 
         <termref def="dt-namespace-binding">namespace bindings</termref>, each of which associates a namespace prefix with a URI.</termdef>
For a given element, one namespace binding may have an empty prefix; the URI of this namespace binding is 
referred to as the <termref def="dt-default-in-scope-namespace"/> for the element.</p>
               <p role="xpath">In <bibref ref="xpath"/>, the in-scope namespaces of an element node are represented by a collection of <term>namespace nodes</term> arranged on a <term>namespace axis</term>. 
As of XPath 2.0, the namespace axis is deprecated and need not be supported by a host language. A host language that does not support the namespace axis need not represent namespace bindings in the form of nodes.</p>
               <p>
                  <termdef id="dt-default-in-scope-namespace" term="default in-scope namespace">The <term>default in-scope namespace</term>
         of an element node</termdef> is the namespace URI to which the empty prefix is bound in the element’s 
         <termref def="dt-in-scope-namespaces"/>. In the absence of an explicit binding for the empty prefix, the
         default in-scope namespace is <xtermref spec="DM40" ref="dt-absent"/>.</p>
               <p>
                  <termdef id="dt-expanded-qname" term="expanded QName">An <term>expanded QName</term> 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.</termdef> When
      comparing two expanded QNames, the prefixes are ignored: the
      local name parts must be equal under the Unicode codepoint
      collation (<xspecref spec="FO40" ref="collations"/>), 
      and the namespace URI parts must either both be
      absent, or must be equal under the Unicode codepoint
      collation.</p>
               <note>
                  <p>The <xtermref spec="DM40" ref="dt-datum"/> of 
            an <termref def="dt-atomic-item"/> of type <code nobreak="false">xs:QName</code>
            is an <termref def="dt-expanded-qname"/>. However, the
            term <termref def="dt-expanded-qname"/> is also used for
            the names of constructs such as functions, variables, and types
            that are not themselves atomic items.</p>
               </note>
               <p>In the XPath 4.0
      grammar, QNames representing the names of
      elements, attributes, functions, variables, types, or other such
      constructs are written as instances of the grammatical
      production <nt def="doc-xpath40-EQName">EQName<!--$spec = xpath40--></nt>.</p>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-EQName">
                     <lhs>EQName</lhs>
                     <rhs>
                        <nt def="prod-xpath40-QName">QName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-EQName-URIQualifiedName">
                     <lhs>URIQualifiedName</lhs>
                     <rhs>
                        <nt def="prod-xpath40-BracedURILiteral">BracedURILiteral<!--$idref_lang_part = xpath40- --></nt>  (<nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>  ":")?  <nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>
               </scrap>
               <p>The <nt def="doc-xpath40-EQName">EQName<!--$spec = xpath40--></nt> production allows a QName to
      be written in one of four ways:
      <ulist>
                     <item>
                        <p>local-name only (for example, <code nobreak="false">invoice</code>).</p>
                        <p>A name written in this form has no prefix, and the rules
        for determining the namespace depend on the context in which
        the name appears: the various rules used are summarized
        in <specref ref="id-expanding-unprefixed-qnames"/>.
                  This form is a <termref def="dt-qname">lexical QName</termref>.</p>
                     </item>
                     <item>
                        <p>prefix plus local-name (for example, <code nobreak="false">my:invoice</code>).</p>
                        <p>In this case the prefix and local name of the QName are as
        written, and the namespace URI is inferred from the prefix by
        examining the <termref def="dt-static-namespaces"/> in the static context where
        the QName appears; the context must include a binding for the
        prefix. This form is a <termref def="dt-qname">lexical
        QName</termref>.</p>
                     </item>
                     <item>
                        <p>URI plus local-name (for example,
        <code nobreak="false">Q{http://example.com/ns}invoice</code>).</p>
                        <p>In this case the local name and namespace URI are as
        written, and the prefix is absent. This way of writing a QName
        is context-free, which makes it particularly suitable for use
        in  
            <phrase role="xpath">expressions</phrase>
        that are generated by software. This
        form is a <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$spec = xpath40--></nt>.  
        If the <nt def="prod-xpath40-BracedURILiteral">
        BracedURILiteral<!--$spec = xpath40--></nt> has no content (for example, <code nobreak="false">Q{}invoice</code>) 
        then the namespace URI of the QName is absent.</p>
                     </item>
                     <item>
                        <p>URI plus prefix plus local-name (for example,
        <code nobreak="false">Q{http://example.com/ns}xmp:invoice</code>).</p>
                        <p>In this case all three components of the expanded QName are
                  present. Although in most contexts the prefix will be ignored,
                  there may be cases where it is useful, for example if the QName
                  is cast to a string.</p>
                        <p>It is a static error <errorref class="ST" code="0154"/> 
                  if the prefix is present and the namespace URI
               is absent (for example <code nobreak="false">Q{}xmp:invoice</code>).</p>
                     </item>
                  </ulist>
               </p>
               <p>
                  <termdef id="dt-qname" term="lexical QName">A
          <term>lexical QName</term> is a name that conforms to the syntax of the
          <nt def="prod-xpath40-QName">QName<!--$spec = xpath40--></nt> production</termdef>.
          </p>
               <p>
	  The namespace URI value in a <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$spec = xpath40--></nt> is whitespace normalized according
	  to the rules for the <code nobreak="false">xs:anyURI</code> type in
          <xspecref spec="XS1-2" ref="anyURI"/> or 
          <xspecref spec="XS11-2" ref="anyURI"/>. 

          It is a <termref def="dt-static-error">static
          error</termref>
                  <errorref class="ST" code="0070"/> if the
          namespace URI for an EQName is
          <code nobreak="false">http://www.w3.org/2000/xmlns/</code>.
          </p>
               <p>Here are some examples of <nt def="doc-xpath40-EQName">EQName<!--$spec = xpath40--></nt>s:</p>
               <ulist>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">pi</code> is a <termref def="dt-qname">lexical QName</termref> without a namespace prefix.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">math:pi</code> is a <termref def="dt-qname">lexical QName</termref> with a namespace prefix.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">Q{http://www.w3.org/2005/xpath-functions/math}pi</code> specifies the namespace URI using a  <nt def="prod-xpath40-BracedURILiteral">BracedURILiteral<!--$spec = xpath40--></nt>; it is not a  <termref def="dt-qname">lexical QName</termref>.</p>
                  </item>
               </ulist>
               <p>This document uses the following namespace prefixes to represent the namespace URIs 
         with which they are listed.</p>
               <ulist>
                  <item>
                     <p>
                        <code nobreak="false">xs</code>: <code nobreak="false">http://www.w3.org/2001/XMLSchema</code>
                     </p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">fn</code>: <code nobreak="false">http://www.w3.org/2005/xpath-functions</code>
                     </p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">array</code>: <code nobreak="false">http://www.w3.org/2005/xpath-functions/array</code>
                     </p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">map</code>: <code nobreak="false">http://www.w3.org/2005/xpath-functions/map</code>
                     </p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">math</code>: <code nobreak="false">http://www.w3.org/2005/xpath-functions/math</code>
                     </p>
                  </item>
                  <item diff="add" at="2023-05-10">
                     <p>
                        <code nobreak="false">err</code>: <code nobreak="false">http://www.w3.org/2005/xqt-errors</code>
                  (see <specref ref="id-identifying-errors"/>).</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">output</code>: <code nobreak="false">http://www.w3.org/2010/xslt-xquery-serialization</code>
                     </p>
                  </item>
               </ulist>
               <p role="xpath">In XPath 4.0, the above namespace bindings are not automatically
     included in the <termref def="dt-static-namespaces"/> of the <termref def="dt-static-context"/> 
     of an expression unless the host language chooses to include them.</p>
               <p>
                  <termdef term="URI" id="dt-URI">Within this specification, the term <term>URI</term> refers to a Universal Resource Identifier as defined in <bibref ref="RFC3986"/> and extended in <bibref ref="RFC3987"/> with the new name <term>IRI</term>.</termdef>
The term URI has been retained in preference to IRI to avoid introducing new names for concepts such as “Base URI” that are defined or referenced across the whole family of XML specifications.</p>
               <note>
                  <p>In most contexts, processors are not required to raise errors if a URI is not lexically valid according to  <bibref ref="RFC3986"/> and  <bibref ref="RFC3987"/>. See <specref ref="id-uri-literals"/>
             for details.</p>
               </note>
            </div3>
            <div3 id="id-expanding-unprefixed-qnames">
               <head>Expanding Lexical QNames</head>
               <p>When a <termref def="dt-qname"/> appearing in an XPath 4.0 expression is expanded, the rules are as follows.</p>
               <p>If the name contains a colon, then the prefix (the substring before the colon) is used to establish the 
               corresponding URI by reference to the <termref def="dt-static-namespaces"/>
            in the <termref def="dt-static-context"/>. If there
                  is no binding for the prefix in the <termref def="dt-static-namespaces"/> then
                  a static error is raised <errorref class="ST" code="0081"/>.
            </p>
               <p>If the <termref def="dt-qname">lexical QName</termref> contains no colon (and therefore no prefix),
            the namespace URI part of the QName is inferred in one of a number of ways, depending on the syntactic context
            in which the name appears. The various rules are defined below, and are referred to throughout the specification.</p>
               <ulist>
                  <item>
                     <p>
                        <termdef id="dt-no-namespace-rule" term="no-namespace rule">When an unprefixed lexical QName
               is expanded using the <term>no-namespace rule</term>, it is interpreted as having an absent namespace URI.</termdef>
                     </p>
                  </item>
                  <item>
                     <p>
                        <termdef id="dt-default-function-namespace-rule"
                                 term="default function namespace rule">When 
                     an unprefixed lexical QName
                     is expanded using the <term>default function namespace rule</term>, 
                     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 <termref def="dt-default-function-namespace"/> from 
                     the <termref def="dt-static-context"/>.</termdef>
                     </p>
                     <note>
                        <p>The implication of this rule is that if there is a user-defined function in no namespace
                  with the same local name as a system-defined function in the <code nobreak="false">fn</code>
                     namespace, then a function call using the unprefixed function name invokes the user-defined
                     function in preference to the system-defined function.</p>
                        <p>It is generally advisable to avoid any danger of user confusion by keeping the names
                        of user-defined functions noticably distinct from the names of system-defined functions,
                        for example by using different naming conventions (for example, leading upper-case letters
                        leading underscores, or <code nobreak="false">camelCase</code>).</p>
                        <p>There may however be cases where a user-defined function deliberately has the same local name
                        as a system-defined function, but with modified semantics. For example a user might choose
                        to define a function <code nobreak="false">Q{}current-date()</code> that returns a date with no timezone:
                        this might be defined in XQuery as:</p>
                        <eg xml:space="preserve">declare function current-date() as xs:date {
   fn:current-date() =&gt; fn:adjust-date-to-timezone(())
}</eg>
                     </note>
                  </item>
                  <item>
                     <p>
                        <termdef id="dt-default-type-namespace-rule" term="default type namespace rule">When 
                  an unprefixed lexical QName
               is expanded using the <term>default type namespace rule</term>, it uses the 
                  <termref def="dt-default-namespace-elements-and-types"/>. If this is absent, the <termref def="dt-no-namespace-rule"/>
                  is used. If the <termref def="dt-default-namespace-elements-and-types"/> has the special value <code nobreak="false">##any</code>,
                  then the lexical QName refers to a name in the namespace <code nobreak="false">http://www.w3.org/2001/XMLSchema</code>.</termdef>
                     </p>
                  </item>
                  <item>
                     <p>
                        <termdef id="dt-default-element-namespace-rule"
                                 term="default element namespace rule">When 
                  an unprefixed lexical QName
               is expanded using the <term>default element namespace rule</term>, then it uses the 
                  <termref def="dt-default-namespace-elements-and-types"/>. If this is absent, or if it takes
                  the special value <code nobreak="false">##any</code>, then the <termref def="dt-no-namespace-rule"/>
                  is used.</termdef>
                     </p>
                  </item>
                  <item>
                     <p>
                        <termdef id="dt-constructed-element-namespace-rule"
                                 term="constructed element namespace rule">
                  When  an unprefixed lexical QName
               is expanded using the <term>constructed element namespace rule</term>, then it uses the namespace URI
                     that is bound to the empty (zero-length) prefix in the <termref def="dt-static-namespaces"/> of the
                     <termref def="dt-static-context"/>. If there is no such <termref def="dt-namespace-binding"/>
                  then it uses the <termref def="dt-no-namespace-rule"/>.</termdef>
                     </p>
                  </item>
                  <item>
                     <p>
                        <termdef id="dt-element-name-matching-rule" term="element name matching rule">When 
                  an unprefixed lexical QName
               is expanded using the <term>element name matching rule</term>, then it uses the 
                  <termref def="dt-default-namespace-elements-and-types"/>. If this is absent, then 
                  it uses the <termref def="dt-no-namespace-rule"/>. But if it takes the special value <code nobreak="false">##any</code>,
                  then the name is taken as matching any <termref def="dt-expanded-qname"/> with the corresponding local part,
                  regardless of namespace: that is, the  unprefixed name <code nobreak="false">local</code> is interpreted
                  as <code nobreak="false">*:local</code>.</termdef>
                     </p>
                  </item>
               </ulist>
            </div3>
         </div2>
         <div2 id="context">
            <head>Expression Context</head>
            <p>
               <termdef id="dt-expression-context" term="expression context">The <term>expression
		context</term> for a given expression consists of all
		the information that can affect the result of the
		expression.</termdef>
            </p>
            <p>This information is organized into two categories
		called the <termref def="dt-static-context">static
		context</termref> and the <termref def="dt-dynamic-context">dynamic
		context</termref>.</p>
            <!--<p role="xquery">
            <termdef id="dt-module-context" term="module context"
               >The <term>module context</term> for a given
		module consists of all the information that is
		accessible to top-level expressions in the
		module.</termdef> The context of a top-level
		expression is defined based on the context of the
		module in which it is defined: the context of the <nt
               def="QueryBody"
            >QueryBody</nt> is the context of the
		main module, and the context for evaluating a function
		body or for a variable’s initializing expression is
		defined based on the context of the module in which
		the function or variable is defined.</p>-->
            <div3 id="static_context">
               <head>Static Context</head>
               <changes>
                  <change issue="296" PR="1181" date="2024-04-30">
                  The <termref def="dt-default-namespace-elements-and-types"/> can be set to the value <code nobreak="false">##any</code>,
                  allowing unprefixed names in axis steps to match elements with a given local name in any namespace.
               </change>
                  <change issue="1343" PR="1344" date="2024-09-23">

                  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.
               </change>
                  <change issue="1495" PR="1496" date="2024-10-29">
                  The context value static type, which was there purely to assist in static typing, has been dropped.
               </change>
                  <change issue="835" PR="1991" date="2025-05-11">
                  Named record types used in the signatures of built-in functions are now available as standard
                  in the static context.
               </change>
               </changes>
               <p>
                  <termdef id="dt-static-context" term="static context">The <term>static context</term> of an expression is
		  the information that is available during static analysis of the expression, prior
		  to its evaluation.</termdef> This information can be used to decide whether the
		  expression contains a <termref def="dt-static-error">static error</termref>. </p>
               <p>The individual components of the <termref def="dt-static-context">static context</termref> are described below.</p>
               <p role="xpath">In XPath 4.0, the static context for an expression is largely defined
               by the host language, that is, by the calling environment that causes an XPath
               expression to be evaluated. Most of the static context components are constant
               throughout an expression; the only exception is <termref def="dt-in-scope-variables"/>.
               (There are constructs in the language, such as the <nt def="doc-xpath40-ForExpr">ForExpr<!--$spec = xpath40--></nt>
               and <nt def="doc-xpath40-LetExpr">LetExpr<!--$spec = xpath40--></nt>, that add additional variables to the static context
               of their subexpressions.)</p>
               <p>Some components of the static context, but not all, also affect the dynamic semantics
            of expressions. For example, casting of a string such as <code nobreak="false">"xbrl:xbrl"</code> to
            an <code nobreak="false">xs:QName</code> might expand the prefix <code nobreak="false">xbrl</code> to the namespace
            URI <code nobreak="false">http://www.xbrl.org/2003/instance</code> using the <termref def="dt-static-namespaces"/>
               from the static context;
            since the input string <code nobreak="false">"xbrl:xbrl"</code> is in general not known until execution time (it
            might be read from a source document), this means that the values of the 
            <termref def="dt-static-namespaces"/> must be available at execution time.</p>
               <ulist>
                  <item>
                     <p>
                        <termdef id="dt-xpath-compat-mode" term="XPath 1.0 compatibility     mode">
                           <term>XPath 1.0 compatibility
			 mode.</term>
                           <phrase role="xpath">This value is <code nobreak="false">true</code> if rules for backward compatibility with XPath Version 1.0 are in effect; otherwise it is <code nobreak="false">false</code>.</phrase>
                        </termdef>
                     </p>
                  </item>
                  <item>
                     <p>
                        <termdef id="dt-static-namespaces" term="statically known namespaces">
                           <term>Statically known namespaces.</term> 
        This is a mapping from prefix to namespace URI that defines all the namespaces 
        that are known during static processing of a given expression.</termdef>
                     </p>
                     <p>The URI value is whitespace normalized according to the rules for the
                     <code nobreak="false">xs:anyURI</code> type in <xspecref spec="XS1-2" ref="anyURI"/> or 
                     <xspecref spec="XS11-2" ref="anyURI"/>.</p>
                     <p>Note the difference between <termref def="dt-in-scope-namespaces">in-scope namespaces</termref>, which is a dynamic property of an element node, and <termref def="dt-static-namespaces">statically known namespaces</termref>, which is a static property of an expression.</p>
                  </item>
                  <item>
                     <p diff="chg" at="A">
                        <termdef id="dt-default-namespace-elements-and-types"
                                 term="default namespace for elements and types">
                           <term>Default namespace for elements and types.</term> This is either a
				namespace URI, or the special value <code nobreak="false">"##any"</code>, or <xtermref spec="DM40" ref="dt-absent"/>. This indicates how unprefixed QNames are interpreted when
                        they appear in a position  where an element name or type name is expected.</termdef>
                     </p>
                     <ulist>
                        <item>
                           <p diff="chg" at="issue372">If the value is set to a namespace URI, 
                        this namespace is used for any such unprefixed QName. The URI value is
               whitespace-normalized according to the rules for the <code nobreak="false">xs:anyURI</code> type in <xspecref spec="XS1-2" ref="anyURI"/> or <xspecref spec="XS11-2" ref="anyURI"/>.</p>
                        </item>
                        <item>
                           <p>The special value <code nobreak="false">"##any"</code> indicates that:</p>
                           <ulist>
                              <item>
                                 <p>When an unprefixed QName is used as a <termref def="dt-name-test"/> for selecting
                              named elements in an <termref def="dt-axis-step"/>, the <termref def="dt-name-test"/>
                           will match an element having the specified local name, in any namespace or none.</p>
                              </item>
                              <item>
                                 <p>When an unprefixed QName is used in a context where a type name is expected
                           (but not as a function name), the default namespace is the <code nobreak="false">xs</code>
                           namespace, <code nobreak="false">http://www.w3.org/2001/XMLSchema</code>.</p>
                              </item>
                              <item>
                                 <p>In any other context, an unprefixed QName represents a name in no namespace.</p>
                              </item>
                           </ulist>
                        </item>
                        <item>
                           <p diff="chg" at="issue372">If the value is <xtermref spec="DM40" ref="dt-absent"/>,
                        an unprefixed QName representing an element or type
                        name is interpreted as being in no namespace.</p>
                        </item>
                     </ulist>
                  </item>
                  <item>
                     <p>
                        <termdef id="dt-default-function-namespace" term="default function namespace">
                           <term>Default function namespace.</term> This determines how unprefixed lexical QNames
                        appearing in a <termref def="dt-static-function-call"/> or a
                        <termref def="dt-named-function-ref"/> are interpreted.</termdef>
                     </p>
                     <p>There are three possible settings:</p>
                     <olist>
                        <item>
                           <p>The property may be <xtermref spec="DM40" ref="dt-absent"/>. In this case
                     an unprefixed <termref def="dt-qname"/> appearing in a <termref def="dt-static-function-call"/> 
                      or in a <termref def="dt-named-function-ref"/>
                     is resolved first by searching the static context for a <termref def="dt-function-definition"/> in no namespace,
                     having a matching local name and <termref def="dt-arity-range"/>; if that fails to find a matching function
                     definition, a second search is conducted looking for a <termref def="dt-function-definition"/>
                     in the namespace <code nobreak="false">http://www.w3.org/2005/xpath-functions</code>, again
                     having a matching local name and <termref def="dt-arity-range"/>.</p>
                        </item>
                        <item>
                           <p>The property may be set to the empty URI, <code nobreak="false">""</code>. In this case
                     an unprefixed <termref def="dt-qname"/> appearing in a 
                        <termref def="dt-static-function-call"/> or a <termref def="dt-named-function-ref"/>
                     is resolved by searching the static context for a <termref def="dt-function-definition"/> in no namespace,
                     having a matching local name and <termref def="dt-arity-range"/>.</p>
                        </item>
                        <item>
                           <p>The property may be set to an explicit URI, say <var>NS</var>. In this case
                     an unprefixed <termref def="dt-qname"/> appearing in a 
                        <termref def="dt-static-function-call"/> or a <termref def="dt-named-function-ref"/>
                     is resolved by searching the static context for a <termref def="dt-function-definition"/> in namespace <var>NS</var>,
                     having a matching local name and <termref def="dt-arity-range"/>.</p>
                        </item>
                     </olist>
                     <p>The URI value is whitespace-normalized according
                     to the rules for the <code nobreak="false">xs:anyURI</code> type in <xspecref spec="XS1-2" ref="anyURI"/> or <xspecref spec="XS11-2" ref="anyURI"/>
                     </p>
                     <p>Host languages may use a more complex algorithm for resolving function names. For
                     example XSLT resolves ambiguities using the concept of import precedence.
                  </p>
                  </item>
                  <item>
                     <p>
                        <termdef id="dt-issd" term="in-scope schema definitions">
                           <term>In-scope schema
			 definitions</term> 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.</termdef> It includes the
			 following three
			 parts:</p>
                     <ulist>
                        <item>
                           <p>
                              <termdef id="dt-is-types" term="in-scope schema type">
                                 <term>In-scope schema types.</term> Each schema type
			        definition is identified either by an <termref def="dt-expanded-qname">expanded
			        QName</termref> (for a <term>named type</term>)
			        or by an <termref def="dt-implementation-dependent">implementation-dependent</termref> type
			        identifier (for an <term>anonymous
			        type</term>). The in-scope schema types include the predefined schema types described in <specref ref="id-predefined-types"/>.

                                
                           </termdef>
                           </p>
                        </item>
                        <item>
                           <p>
                              <termdef id="dt-is-elems" term="in-scope element declarations">
                                 <term>In-scope element declarations.</term> Each element
declaration is identified either by an <termref def="dt-expanded-qname">expanded QName</termref> (for a top-level element
declaration) or by an <termref def="dt-implementation-dependent">implementation-dependent</termref> element identifier (for a
local element declaration). 
                           </termdef> An element
declaration includes information about the element’s <termref def="dt-substitution-group">substitution group</termref> affiliation.</p>
                           <p>
                              <termdef term="substitution group" id="dt-substitution-group">
                                 <term>Substitution groups</term> are defined in <xspecref spec="XS1-1" ref="Element_Equivalence_Class"/> and 
<xspecref spec="XS11-1" ref="Element_Equivalence_Class"/>. Informally, the substitution group headed by a given element (called the <term>head element</term>) consists of  the set of elements that can be substituted for the head element without affecting the outcome of schema validation.</termdef>
                           </p>
                        </item>
                        <item>
                           <p>
                              <termdef id="dt-is-attrs" term="in-scope attribute declarations">
                                 <term>In-scope attribute
declarations.</term> Each attribute declaration is identified either
by an <termref def="dt-expanded-qname">expanded QName</termref> (for a top-level attribute declaration) or by an
<termref def="dt-implementation-dependent">implementation-dependent</termref> attribute identifier (for a local attribute
declaration).  
                           </termdef>
                           </p>
                        </item>
                     </ulist>
                  </item>
                  <item>
                     <p>
                        <termdef id="dt-in-scope-variables" term="in-scope variables">
                           <term>In-scope variables.</term> 
                           This is a mapping from <termref def="dt-expanded-qname">expanded QNames</termref> to sequence types. It defines the
                           set of variables that are available for reference within an
                           expression. The <termref def="dt-expanded-qname">expanded QName</termref> is the name of the variable, and the type is the
                           <termref def="dt-static-type">static type</termref> of the
                           variable.</termdef>
                     </p>
                     <p>
                     
An expression that binds a variable extends the <termref def="dt-in-scope-variables">in-scope variables</termref>, within the scope of the variable, with the variable and its type. 
Within the body of an
<termref def="dt-inline-func">inline function expression</termref>, the
<termref def="dt-in-scope-variables">in-scope variables</termref> are extended
by the names and types of the <term>function
parameters</term>.</p>
                  </item>
                  <item diff="add" at="A">
                     <p>
                        <termdef id="dt-in-scope-named-item-types" term="in-scope named item types">
                           <term>In-scope named item types.</term> This is a mapping from 
                        <termref def="dt-expanded-qname">expanded QNames</termref> to 
                        <termref def="dt-named-item-type">named item types</termref>.</termdef>
                     </p>
                     <p>
                        <termdef id="dt-named-item-type" term="named item type">A <term>named item type</term>
                      is an <code nobreak="false">ItemType</code> identified by an <termref def="dt-expanded-qname"/>.</termdef>
                     </p>
                     <p>Named item types serve two purposes:</p>
                     <ulist>
                        <item>
                           <p>They allow frequently used item types, especially complex item types such as
                        record types, to be given simple names, to avoid repeating the definition 
                        every time it is used.</p>
                        </item>
                        <item>
                           <p>They allow the definition of recursive types, which are useful for
                     describing recursive data structures such as lists and trees. For details see
                     <specref ref="id-recursive-record-tests"/>. </p>
                        </item>
                     </ulist>
                     <p>Certain named item types (typically item types used in the signatures of built-in functions)
                  are always available in the static context. These are defined in <xspecref spec="FO40" ref="id-built-in-named-record-types"/>.</p>
                     <note>
                        <p role="xpath">Named item types can be defined in a <termref def="dt-host-language">host language</termref> 
                        such as XQuery 4.0 and in XSLT 4.0, but not in XPath 4.0 itself. They are available in XPath
                        only if the host language provides the ability to define them.</p>
                     </note>
                  </item>
                  <item diff="chg" at="variadicity">
                     <p>
                        <termdef id="dt-statically-known-function-definitions"
                                 term="statically known function definitions">
                           <term>Statically known function definitions.</term> This is a set of 
                           <termref def="dt-function-definition">function definitions</termref>.</termdef>
                     </p>
                     <p>Function definitions are described in <specref ref="id-function-definitions"/>.</p>
                  </item>
                  <item>
                     <p>
                        <termdef id="dt-static-collations" term="statically known collations">
                           <term>Statically known collations.</term> This is an <termref def="dt-implementation-defined">implementation-defined</termref>
        mapping from URI to collation. It defines the names of the collations that are available for
				use in processing  expressions.</termdef>
                        <termdef term="collation" id="dt-collation">A <term>collation</term> 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 <xspecref spec="FO40" ref="string-compare"/>.</termdef>
                     </p>
                  </item>
                  <item>
                     <p diff="chg" at="2023-05-19">
                        <termdef id="dt-static-base-uri" term="Static Base URI">
                           <term>Static Base URI.</term>
        This is an absolute URI, used to resolve relative URIs during static analysis.
                     </termdef>
                     For example, it is used to resolve module location URIs in XQuery, and 
                     the URIs in <code nobreak="false">xsl:import</code> and <code nobreak="false">xsl:include</code> in XSLT.
                     
                     <phrase role="xpath">
        If <var>E</var> is a subexpression of <var>F</var> then the Static 
        Base URI of <var>E</var> is the same as the Static Base URI of <var>F</var>.
        There are no constructs in XPath that require resolution of relative URI references 
        during static analysis.
      </phrase>
                     </p>
                     <p>
                        <phrase diff="del" at="2023-05-19">The Static Base URI is available during dynamic evaluation by use of the 
      <function>fn:static-base-uri</function> function, and is used implicitly during dynamic 
      evaluation by functions such as <function>fn:doc</function>. </phrase>Relative URI references are 
      resolved as described in <specref ref="id-resolve-relative-uri"/>.</p>
                     <p diff="add" at="2023-05-19">At execution time,
                  relative URIs supplied to functions such as <function>fn:doc</function>
                  are resolved against the <termref def="dt-executable-base-uri"/>,
                  which may or may not be the same as the Static Base URI.</p>
                  </item>
                  <item>
                     <p>
                        <termdef id="dt-static-decimal-formats" term="statically known decimal formats">
                           <term>Statically known decimal
		      formats.</term> 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 <function>fn:format-number</function> function.</termdef>
                     </p>
                     <p>Decimal formats are described in <specref ref="id-decimal-formats"/>.</p>
                  </item>
               </ulist>
               <div4 id="id-function-definitions">
                  <head>Function Definitions</head>
                  <p>
                     <termdef id="dt-function-definition" term="function definition">A <term>function definition</term>
                  contains information used to evaluate a static function call, including the name, parameters,
                  and return type of the function.</termdef>
                  </p>
                  <p>The properties of a <termref def="dt-function-definition"/> include:</p>
                  <ulist>
                     <item>
                        <p>The function name, which is an <termref def="dt-expanded-qname"/>.</p>
                     </item>
                     <item>
                        <p>Parameter definitions, specifically:</p>
                        <ulist>
                           <item>
                              <p>A (possibly empty) list of required parameters, each having:</p>
                              <ulist>
                                 <item>
                                    <p>a parameter name (an <termref def="dt-expanded-qname"/>)</p>
                                 </item>
                                 <item>
                                    <p>a required type (a <termref def="dt-sequence-type"/>)</p>
                                 </item>
                              </ulist>
                           </item>
                           <item>
                              <p>A (possibly empty) list of optional parameters, each having:</p>
                              <ulist>
                                 <item>
                                    <p>a parameter name (an <termref def="dt-expanded-qname"/>)</p>
                                 </item>
                                 <item>
                                    <p>a required type (a <termref def="dt-sequence-type"/>)</p>
                                 </item>
                                 <item>
                                    <p>a default value expression (an <term>expression</term>: see <specref ref="id-expressions"/>)</p>
                                 </item>
                              </ulist>
                           </item>
                        </ulist>
                        <p>The names of the parameters must be distinct.</p>
                        <p>
                           <termdef id="dt-arity-range" term="arity range">A <termref def="dt-function-definition"/> has an <term>arity range</term>,
                        which is a range of consecutive non-negative integers. If the function definition has <var>M</var> required parameters
                        and <var>N</var> optional parameters, then its arity range is from <var>M</var> to <var>M</var>+<var>N</var>
                        inclusive.</termdef>
                        </p>
                        <!--<p><termdef id="dt-variadic" term="variadic">A <termref def="dt-function-definition"/> may
                     be declared to be <term>variadic</term>. In a static call of a variadic function, multiple
                     arguments may be mapped to a single parameter in the function definition. In a variadic
                     function with <var>M</var> declared parameters, the arity range is from <var>M-1</var>
                     to positive infinity.</termdef></p>
                     
                     <p>For an overview of variadic functions, see <specref ref="id-variadic-functions-overview"/>.</p>
                     
                     <note><p>Examples of system functions defined to be variadic are <function>fn:concat</function>
                     and <function>fn:codepoints-to-string</function>. User-written functions in XQuery may
                     be declared as variadic by using the <code>%variadic</code> annotation; the equivalent
                     in XSLT is to use the attribute <code>xsl:function/@variadic = "yes"</code>.</p></note>
                     
                   -->
                        <p>The static context may contain several <termref def="dt-function-definition">function definitions</termref> with the
                        same name, but the <termref def="dt-arity-range">arity ranges</termref> of two such function definitions must not 
                        overlap. For example, if two function definitions <var>A</var> and <var>B</var> have the same function name, then:</p>
                        <ulist>
                           <item>
                              <p>It is acceptable for <var>A</var> to have two required parameters and no optional
                           parameters, while <var>B</var> has three required parameters and one optional
                           parameter.</p>
                           </item>
                           <item>
                              <p>It is not acceptable for <var>A</var> to have one required parameter while <var>B</var>
                           has three optional parameters.</p>
                           </item>
                           <!--<item><p>It is not possible for both <var>A</var> and <var>B</var> to be <termref def="dt-variadic"/>.</p></item>-->
                        </ulist>
                        <note>
                           <p>Implementations must ensure that no two <termref def="dt-function-definition">function definitions</termref> 
                        have the same <termref def="dt-expanded-qname">expanded QName</termref> and overlapping
                        arity ranges (even if the signatures are consistent).</p>
                           <p>XQuery and XSLT enforce this rule by defining a static error if the rule is violated; but further constraints
                           may be needed if an API allows external functions to be added to the static context.</p>
                        </note>
                     </item>
                     <item>
                        <p>A return type (a <termref def="dt-sequence-type"/>)</p>
                     </item>
                     <item>
                        <p diff="add" at="2023-03-11">The function category, which is one of application, system, or external:</p>
                        <ulist diff="add" at="2023-03-11">
                           <item>
                              <p>
                                 <termdef id="dt-application-function" term="application function">
                                    <term>Application functions</term> 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.</termdef>
                           The most common application functions are functions written by users in XQuery or XSLT.
                        </p>
                           </item>
                           <item>
                              <p>
                                 <termdef id="dt-system-function" term="system function">
                                    <term>System functions</term> include the functions defined in <bibref ref="xpath-functions-40"/>, functions defined by the specifications 
                           of a host language, <termref def="dt-constructor-function">constructor functions</termref> 
                           for atomic types, and any additional functions provided
                           by the implementation. System functions are sometimes called built-in
                           functions.</termdef>
                              </p>
                              <p>The behavior of system functions follows the rules given for the individual
                              function in this family of specifications, or in the specification of the
                              particular processor implementation. A system function may have behavior that depends on the
                              static or dynamic context of the caller (for example, comparing strings
                              using the default collation from the <phrase diff="chg" at="2023-05-19">dynamic</phrase> context of the caller). Such
                              functions are said to be <termref def="dt-context-dependent"/>.</p>
                           </item>
                           <item>
                              <p>
                                 <termdef id="dt-external-function" term="external function">
                                    <term>External functions</term> 
                           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 
                           <xspecref spec="XT30" ref="extension-functions">extension functions</xspecref>. </termdef>
                              </p>
                              <p>For example, an implementation might provide a mechanism allowing
                              external functions to be written in a language such as Java or Python.
                              The way in which argument and return values are converted between
                              the XDM type system and the type system of the external language is
                              implementation-defined.
                           </p>
                           </item>
                        </ulist>
                        <p diff="add" at="2023-03-11">
                           <termdef id="dt-context-dependent" term="context dependent">A 
                        <termref def="dt-function-definition"/> is said to be <term>context dependent</term>
                        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 <function>fn:name#0</function> is context-dependent
                        while <function>fn:name#1</function> is context-independent.</termdef>
                        </p>
                        <note diff="add" at="2023-03-11">
                           <p>Some system functions, such as <function>fn:position</function>, <function>fn:last</function>,
                        and <function>fn:static-base-uri</function>, exist for the sole purpose of providing information
                        about the static or dynamic context of their caller.</p>
                        </note>
                        <note>
                           <p diff="add" at="2023-03-11">
                              <termref def="dt-application-function">Application functions</termref> 
                        are context dependent only to the extent that they define optional parameters with default
                        values that are context dependent.</p>
                        </note>
                     </item>
                     <item>
                        <p>A (possibly empty) set of <term>function annotations</term>
                        </p>
                     </item>
                     <item>
                        <p diff="chg" at="2023-03-11">A body. The function 
                     body contains the logic that enables the function
                     result to be computed from the supplied arguments and information in the static and dynamic context.</p>
                     </item>
                  </ulist>
                  <!--<p diff="add" at="B"><termref def="dt-system-function">System functions</termref>
                  (also commonly called built-in functions) are <termref def="dt-function-definition">function definitions</termref> that are always
                  present in the static context by virtue of rules in the host language; they will typically include
                  the functions specified in <bibref ref="xpath-functions-40"/>.</p>
               
               -->
                  <p>The <termref def="dt-function-definition">function definitions</termref> 
                  present in the static context are available for reference from a 
                  <termref def="dt-static-function-call">static function call</termref>,
                  or from a 
                  <termref def="dt-named-function-ref">named function reference</termref>.
                  
               </p>
               </div4>
               <div4 id="id-decimal-formats">
                  <head>Decimal Formats</head>
                  <changes>
                     <change issue="1048" PR="1250" date="2024-06-03">
                           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.
                        </change>
                  </changes>
                  <p>Each decimal format defines a set of properties, which control the interpretation of characters
                        in the picture string supplied to the <function>fn:format-number</function>
                        function, and also specify characters to be used in the result
                        of formatting the number.</p>
                  <p>Each property potentially has two parts: a marker character <var>M</var> used
                     in the picture string to mark an insertion position, and a rendition string <var>R</var>
                     to indicate how the relevant property is to be rendered in the output of the 
                     <code nobreak="false">fn:format-number</code> function. In the list below properties are annotated
                     with <emph>(<var>M</var>)</emph>, <emph>(<var>R</var>)</emph>, or 
                     <emph>(<var>M</var>, <var>R</var>)</emph> to indicate whether the property includes a
                     marker character, a rendition string, or both.</p>
                  <p>In XQuery and XSLT declarations
                     defining the values of properties, a property where the marker character and the
                     rendition differ is indicated using the syntax <code nobreak="false">
                        <var>M</var>:<var>R</var>
                     </code>. For
                     example the <code nobreak="false">percent</code> property may be expressed as <code nobreak="false">%:pc</code>
                     to indicate that the character <code nobreak="false">%</code> will be used in the picture string,
                     and the string <code nobreak="false">pc</code> will be used in the function output.
                     In this example, the value <code nobreak="false">0.10</code>, formatted with the picture string 
                      <code nobreak="false">#0%</code>, results in the output <code nobreak="false">10pc</code>
                  </p>
                  <ulist>
                     <item>
                        <p>
                           <termdef id="id-static-decimal-format-decimal-separator"
                                    term="decimal-separator">
                              <term>decimal-separator</term>
                              <emph>(<var>M</var>, <var>R</var>)</emph> 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 <char>U+002E</char>.</termdef>
                        </p>
                     </item>
                     <item>
                        <p>
                           <termdef id="id-static-decimal-format-exponent-separator"
                                    term="exponent-separator">
                              <term>exponent-separator</term>
                              <emph>(<var>M</var>, <var>R</var>)</emph> is
                                 used to separate the mantissa from the exponent in
                                 scientific notation. The default value 
                                 for both the marker and the rendition is <char>U+0065</char>.</termdef>
                        </p>
                     </item>
                     <item>
                        <p>
                           <termdef id="id-static-decimal-format-grouping-separator"
                                    term="grouping-separator">
                              <term>grouping-separator</term>
                              <emph>(<var>M</var>, <var>R</var>)</emph> is used to 
                                 separate groups of digits (for example as a thousands separator).
                                 The default value for both the marker and the rendition is <char>U+002C</char>.</termdef>
                        </p>
                     </item>
                     <item>
                        <p>
                           <termdef id="id-static-decimal-format-percent" term="percent">
                              <term>percent</term>
                              <emph>(<var>M</var>, <var>R</var>)</emph> 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 <char>U+0025</char>.</termdef>
                        </p>
                     </item>
                     <item>
                        <p>
                           <termdef id="id-static-decimal-format-per-mille" term="per-mille">
                              <term>per-mille</term>
                              <emph>(<var>M</var>, <var>R</var>)</emph> 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 <char>U+2030</char>.</termdef>
                        </p>
                     </item>
                     <item>
                        <p>
                           <termdef id="id-static-decimal-format-zero-digit" term="zero-digit">
                              <term>zero-digit</term>
                              <emph>(<var>M</var>)</emph>
                                 is the character used in the picture string to represent the digit zero; the default
                                 value is <char>U+0030</char>. 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.</termdef>
                        </p>
                     </item>
                     <!--</ulist>
                     
                     <p>In the case of the properties <termref def="id-static-decimal-format-decimal-separator"/>,
                     <termref def="id-static-decimal-format-grouping-separator"/>,
                     <termref def="id-static-decimal-format-exponent-separator"/>,
                        <termref def="id-static-decimal-format-percent"/>
                        and <termref def="id-static-decimal-format-per-mille"/>, the property may take the form
                        <code>m:r</code>, where <code>m</code> is a single-character marker used in the picture
                        string to indicate where the relevant output should appear, and <code>r</code> is the
                        string used to represent the property in the result. .
                     </p>
                     
                     <p>The following properties specify 
                        characters to be used in the picture string supplied to the <function>fn:format-number</function>
                        function, but not in the formatted number. In each case the value must be a single character.
                     </p>
                     
                     <ulist>-->
                     <item>
                        <p>
                           <termdef id="id-static-decimal-format-digit" term="digit">
                              <term>digit</term>
                              <emph>(<var>M</var>)</emph>
                                 is a character used in the picture string to represent an optional digit; 
                                 the default value is <char>U+0023</char>.</termdef>
                        </p>
                     </item>
                     <item>
                        <p>
                           <termdef id="id-static-decimal-format-pattern-separator"
                                    term="pattern-separator">
                              <term>pattern-separator</term>
                              <emph>(<var>M</var>)</emph> is a character used
                                 to separate positive and negative sub-pictures
                                 in a picture string; the default value is <char>U+003B</char>.</termdef>
                        </p>
                     </item>
                     <!--                    </ulist>
                     
                     <p>The following properties specify characters or strings that
                        may appear in the result of formatting the number, but not in the picture string:</p>
                     
                     <ulist>-->
                     <item>
                        <p>
                           <termdef id="id-static-decimal-format-infinity" term="infinity">
                              <term>infinity</term>
                              <emph>(<var>R</var>)</emph>
                                 is the string used to represent the double value infinity (<code nobreak="false">INF</code>); the
                                 default value is the string <code nobreak="false">"Infinity"</code>
                           </termdef>
                        </p>
                     </item>
                     <item>
                        <p>
                           <termdef id="id-static-decimal-format-NaN" term="NaN">
                              <term>NaN</term>
                              <emph>(<var>R</var>)</emph>
                                 is the string used to
                                 represent the double value <code nobreak="false">NaN</code> (not a number); the default value is the string <code nobreak="false">"NaN"</code>
                           </termdef>
                        </p>
                     </item>
                     <item>
                        <p>
                           <termdef id="id-static-decimal-format-minus-sign" term="minus-sign">
                              <term>minus-sign</term>
                              <emph>(<var>R</var>)</emph> is the string used to mark negative numbers; the
                                 default value is <char>U+002D</char>.</termdef>
                        </p>
                     </item>
                  </ulist>
               </div4>
            </div3>
            <div3 id="eval_context">
               <head>Dynamic Context</head>
               <changes>
                  <change issue="129" PR="368" date="2023-09-14">
                  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.
               </change>
                  <change issue="1161" PR="1265" date="2024-06-11">
                  The rules regarding the <code nobreak="false">document-uri</code> property of nodes returned by the
                  <function>fn:collection</function> function have been relaxed.
               </change>
               </changes>
               <p>
                  <termdef id="dt-dynamic-context" term="dynamic context">The <term>dynamic
context</term> 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 <termref def="dt-static-context"/>.</termdef> If
evaluation of an expression relies on some part of the <termref def="dt-dynamic-context"/> that 
is <xtermref spec="DM40" ref="dt-absent"/>, a <termref def="dt-type-error"/> 
               is raised <errorref class="DY" code="0002"/>.</p>
               <note>
                  <p>In previous versions of the specification, this was classified as a
            <termref def="dt-dynamic-error"/>. The change allows the error to be raised during
            static analysis when possible; for example a function written as
            <code nobreak="false">fn($x) { @code }</code> can now be reported as an error whether or not
            the function is actually evaluated. The actual error code remains unchanged
            for backwards compatibility reasons.</p>
                  <p>There are other cases where static detection of the error is not possible.</p>
               </note>
               <p>The individual
components of the <termref def="dt-dynamic-context">dynamic context</termref> are described below.</p>
               <p>In general, the dynamic context for the outermost expression is supplied externally,
               often by some kind of application programming interface (API) allowing XPath 4.0
               expressions to be invoked from a host language. Application Programming Interfaces
               are outside the scope of this specification.  The dynamic context for inner subexpressions
               may be set by their containing expressions: for example in a mapping expression 
               <code nobreak="false">
                     <var>E1</var>!<var>E2</var>
                  </code>,
               the value of the <termref def="dt-focus"/> (part of the dynamic context) for evaluation
               of <var>E2</var> is defined by the evaluation of <var>E1</var>.</p>
               <p>Some aspects of the dynamic context are outside the direct control of the query author;
               they are defined by the implementation, which may or may not allow them to be configured by users.
               An example is <termref def="dt-available-docs"/>, which is an abstraction for the set of XML
               documents that can be retrieved by URI from within an expression. In some environments this may be
               the entire contents of the web; in others it may be constrained to documents that satisfy
               particular security constraints; and in some environments the set of available documents
               might even be empty. These components of the dynamic context are generally treated as being constant for
               the duration of the execution.</p>
               <p>
                  <phrase role="xpath">Further rules governing the semantics of these components can be found in <specref ref="id-xp-evaluation-context-components" role="xpath"/>.</phrase>
               </p>
               <p>The components of the 
           <termref def="dt-dynamic-context"/> are listed below.</p>
               <p>
                  <termdef id="dt-focus" term="focus">The first three components of
the <termref def="dt-dynamic-context">dynamic context</termref>
(context value, context position, and context size) are called the
<term>focus</term> of the expression. </termdef> The focus enables the
processor to keep track of which items are being processed by the
expression.



<phrase role="xpath">If any component in the focus is defined, both the context value and context position are known.</phrase>
               </p>
               <note role="xpath">
                  <p>If any component in the focus is defined, context size is usually defined as well.  However, when streaming, 
the context size cannot be determined without lookahead, so it may be undefined.  If so, expressions like <code nobreak="false">last()</code> will 
                     raise a dynamic error because the context size is undefined.</p>
               </note>
               <p>
                  <termdef id="dt-fixed-focus" term="fixed focus">A <term>fixed focus</term> 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.</termdef>
               </p>
               <p>
                  <termdef id="dt-singleton-focus" term="singleton focus">A <term>singleton focus</term> is a <termref def="dt-fixed-focus"/> in which the
                  <termref def="dt-context-value"/> is a <termref def="dt-singleton"/> item.</termdef>.
               With a singleton focus, the context value is a single item, the context position is 1, and the context size is 1.
               </p>
               <p>Certain language constructs, notably the <termref def="dt-path-expression">path operator</termref>
                  <code role="parse-test" nobreak="false">
                     <var>E1</var>/<var>E2</var>
                  </code>, the <nt def="doc-xpath40-SimpleMapExpr">simple map operator<!--$spec = xpath40--></nt>
                  <code role="parse-test" nobreak="false">
                     <var>E1</var>!<var>E2</var>
                  </code>, and the <termref def="dt-predicate">predicate</termref>
                  <code role="parse-test" nobreak="false">
                     <var>E1</var>[<var>E2</var>]</code>, create a new focus
for the evaluation of a sub-expression. In these constructs, <var role="parse-test">E2</var> is evaluated once for each item in the
sequence that results from evaluating <var role="parse-test">E1</var>. Each time <var role="parse-test">E2</var> is evaluated, it is evaluated with a
different focus. The focus for evaluating <var role="parse-test">E2</var> is referred to below as the <term>inner
focus</term>, while the focus for evaluating <var role="parse-test">E1</var> is referred to as the <term>outer
focus</term>. The inner focus is used only for the evaluation of <var role="parse-test">E2</var>. Evaluation of <var>E1</var> continues with its original focus unchanged.</p>
               <ulist>
                  <item>
                     <p>
                        <termdef id="dt-context-value" term="context value">The <term>context value</term>
is the <termref def="dt-value">value</termref> currently being processed.</termdef>
                     In many cases (but not always), the context value will be a single item.
                     <termdef id="dt-context-node" term="context node">When the context value is a single item, it can also be referred
                        to as the <term>context item</term>; when it is a single node,
it can also be referred to as the <term>context
node</term>.</termdef> The context value is returned by an expression
consisting of a single dot (<code role="parse-test" nobreak="false">.</code>). When an expression <code role="parse-test" nobreak="false">
                           <var>E1</var>/<var>E2</var>
                        </code> or <code role="parse-test" nobreak="false">
                           <var>E1</var>[<var>E2</var>]</code> is evaluated, each item in the
sequence obtained by evaluating <code role="parse-test" nobreak="false">
                           <var>E1</var>
                        </code>
becomes the context value in the inner focus for an evaluation of <var role="parse-test">E2</var>. </p>
                  </item>
                  <item>
                     <p>
                        <termdef id="dt-context-position" term="context position">The <term>context
position</term> is the position of the context value within the
series of values currently being processed.</termdef> It changes whenever the context value
changes. When the focus is defined, the value of the context position is an integer greater than zero. The context
position is returned by the expression <code role="parse-test" nobreak="false">fn:position()</code>. When an expression <code role="parse-test" nobreak="false">
                           <var>E1</var>/<var>E2</var>
                        </code> or <code role="parse-test" nobreak="false">
                           <var>E1</var>[<var>E2</var>]</code> is evaluated, the context position in
the inner focus for an evaluation of <code role="parse-test" nobreak="false">E2</code>
is the position of the context value in the sequence obtained by
evaluating <var role="parse-test">E1</var>. The position of the
first item in a sequence is always 1 (one). The context position is
always less than or equal to the context size.</p>
                  </item>
                  <item>
                     <p>
                        <termdef id="dt-context-size" term="context size">The <term>context
size</term> is the number of values in the series of values currently
being processed.</termdef> Its value is always an
integer greater than zero. The context size is returned by the
expression <code role="parse-test" nobreak="false">fn:last()</code>. When an expression
<code role="parse-test" nobreak="false">
                           <var>E1</var>/<var>E2</var>
                        </code> or <code role="parse-test" nobreak="false">
                           <var>E1</var>[<var>E2</var>]</code> is evaluated, the context size in the
inner focus for an evaluation of <var role="parse-test">E2</var> is
the number of items in the sequence obtained by evaluating <var role="parse-test">E1</var>. </p>
                  </item>
                  <item>
                     <p>
                        <termdef id="dt-variable-values" term="variable values">
                           <term>Variable values</term>. 
        This is a mapping from <termref def="dt-expanded-qname">expanded QNames</termref> to values. 
        It contains the
				same <termref def="dt-expanded-qname">expanded QNames</termref> as the <termref def="dt-in-scope-variables">in-scope variables</termref> in the
				<termref def="dt-static-context">static context</termref> for the expression. The <termref def="dt-expanded-qname">expanded QName</termref> is the name of the variable and the value is the dynamic value of the variable, which includes its <termref def="dt-dynamic-type">dynamic type</termref>.</termdef>
                     </p>
                  </item>
                  <item>
                     <p diff="chg" at="variadicity">
                        <termdef term="dynamically known function definitions"
                                 id="dt-dynamically-known-function-definitions">
                           <term>Dynamically known function definitions</term>.
        This is a set of <termref def="dt-function-definition">function definitions</termref>. It includes the
                        <termref def="dt-statically-known-function-definitions"/> as a subset, but may include
                        other function definitions that are not known statically.
      </termdef>
                     </p>
                     <p>The function definitions in the dynamic context are used primarily by the <function>fn:function-lookup</function>
                  function.</p>
                     <p>If two function definitions in the <termref def="dt-dynamically-known-function-definitions"/> have the same
                     name, then their <termref def="dt-arity-range">arity ranges</termref> must not overlap.</p>
                     <note>
                        <p>The reason for allowing named functions to be available dynamically beyond those that are
                  available statically is primarily to allow for cases where the run-time execution
                  environment is significantly different from the compile-time environment. This could happen, for example,
                  if a stylesheet or query is compiled within a web server and then executed in the web browser.
                  The <function>fn:function-lookup</function> function allows dynamic discovery of resources that were not
                  available statically.</p>
                     </note>
                     <!--                supplies a function for each signature in 
      <termref
                        def="dt-known-func-signatures"
                        >
        statically known function signatures
      </termref>
      and may supply other functions 
      (see <specref
                        ref="id-consistency-constraints"
                        />).  Named functions can include 
      
      
      <termref
                        def="dt-external-function">external functions</termref>.
      
                        id="dt-implementation-defined-function"
                        term="implementation-defined function"
                           >An <term>implementation-defined function</term> is an <termref
                           def="dt-external-function">external function</termref> that is <termref
                           def="dt-implementation-defined">implementation-defined</termref>
                     </termdef>.
        
        <phrase role="xpath">
                        <termdef id="dt-host-language-function" term="host language function"
                           role="xpath">A <term>host language function</term> is an <termref
                              def="dt-external-function"
                              >external function</termref> defined by the <termref
                              def="dt-host-language">host language</termref>.</termdef>
                     </phrase>
                  </p>-->
                  </item>
                  <item>
                     <p>
                        <termdef id="dt-date-time" term="current dateTime">
                           <term>Current dateTime.</term> This information represents
				an <termref def="dt-implementation-dependent">implementation-dependent</termref> point in time during the processing of 
                        <phrase role="xpath">an expression</phrase>, and includes an explicit timezone. It can be retrieved by the  <function>fn:current-dateTime</function> function. 
                        If called multiple times during the execution of 
                        <phrase role="xpath">an expression</phrase>,
				this function always returns the same result.</termdef>
                     </p>
                  </item>
                  <item>
                     <p>
                        <termdef id="dt-timezone" term="implicit timezone">
                           <term>Implicit timezone.</term> 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  <termref def="dt-implementation-defined">implementation-defined</termref> value of type
<code nobreak="false">xs:dayTimeDuration</code>. See <xspecref spec="XS1-2" ref="dateTime-timezones"/> or
<xspecref spec="XS11-2" ref="dateTime"/> for the range of valid values of a timezone.</termdef>
                     </p>
                  </item>
                  <item diff="add" at="2023-05-19">
                     <p>
                        <termdef id="dt-executable-base-uri" term="Executable Base URI">
                           <term>Executable Base URI.</term> 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 <function>fn:doc</function> or <function>fn:unparsed-text</function>
                     functions.
                  </termdef>
                     </p>
                     <p>URIs are resolved as described in <specref ref="id-resolve-relative-uri"/>.</p>
                     <p>The function <function>fn:static-base-uri</function>, despite its name, returns the
                     value of the <termref def="dt-executable-base-uri"/>.</p>
                     <p>In many straightforward processing scenarios, the <termref def="dt-executable-base-uri"/>
                  in the dynamic context will be the same as the <termref def="dt-static-base-uri"/> for the
                     corresponding expression in the static context. There are situations, however, where they may differ:</p>
                     <ulist>
                        <item>
                           <p>Some processors may allow the static analysis of a query or stylesheet
                     to take place on a development machine, while execution of the query or stylesheet
                     happens on a test or production server. In this situation, resources needed during
                     static analysis (such as other modules of the query or stylesheet) will be located
                     on the development machine, by reference to the <termref def="dt-static-base-uri"/>,
                     while resources needed during execution (such as reference data files) will be located
                     on the production machine, accessed via the <termref def="dt-executable-base-uri"/>.</p>
                        </item>
                        <item>
                           <p>When the <function>fn:static-base-uri</function> function is called within
                     the initializing expression of an optional parameter in a function declaration,
                     it returns the executable base URI of the relevant function call. This allows a user-written
                     function to accept two parameters: a required parameter containing a relative URI, and an
                     optional parameter containing a base URI. The optional parameter can be given a default
                     value of <code nobreak="false">fn:static-base-uri()</code>, allowing the code in the function body
                     to resolve the relative URI against the executable base URI of the caller.</p>
                        </item>
                     </ulist>
                  </item>
                  <item>
                     <p>
                        <termdef id="dt-def-collation" term="default collation">
                           <term>Default
                           collation.</term> This identifies one of the collations in <termref def="dt-static-collations">statically known collations</termref> as the  collation to be
                        used by functions and operators for comparing and ordering values of type <code nobreak="false">xs:string</code> and <code nobreak="false">xs:anyURI</code> (and types derived from them) when no
                        explicit collation is
                        specified.</termdef>
                     </p>
                     <note diff="add" at="2023-05-19">
                        <p>Although the default collation is defined (in 4.0) as a property of the
                     dynamic context, its value will in nearly all cases be known statically. The reason it is defined in the
                     dynamic context is to allow a call on the <function>fn:default-collation</function> function to be used when defining
                     the default value of an optional parameter to a user-defined function. In this situation,
                     the actual value supplied for the parameter is taken from the dynamic context of the relevant function call.</p>
                     </note>
                  </item>
                  <item>
                     <p>
                        <termdef id="dt-default-language" term="default language">
                           <term>Default language.</term>
  This is the natural language used when creating human-readable output
  (for example, by the functions <function>fn:format-date</function> and <function>fn:format-integer</function>)
  if no other language is requested. 
  The value is a language code as defined by the type <code nobreak="false">xs:language</code>.</termdef>
                     </p>
                  </item>
                  <item>
                     <p>
                        <termdef id="dt-default-calendar" term="default calendar">
                           <term>Default calendar.</term>
    This is the calendar used when formatting dates in human-readable output
    (for example, by the functions <function>fn:format-date</function> and <function>fn:format-dateTime</function>)
    if no other calendar is requested. 
    The value is a string.</termdef>
                     </p>
                  </item>
                  <item>
                     <p>
                        <termdef id="dt-default-place" term="default place">
                           <term>Default place.</term>
    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 <function>fn:format-date</function>, <function>fn:format-dateTime</function>,
     and <function>fn:civil-timezone</function>,
    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.</termdef>
                     </p>
                  </item>
                  <!--<item>
                  <p>
                     <termdef id="dt-available-docs" term="available documents">
                        <term>Available
    documents.</term> This is a mapping of strings to document nodes.  Each string
    represents the absolute URI of a resource. The document node is the root of a tree that represents that resource 
    using the <termref
                           def="dt-datamodel"
                           >data model</termref>. The document node is returned by the <function>fn:doc</function> 
    function when applied to that URI.</termdef> The set of available documents may be empty.</p>
                  <!-\-<p>If there are one or more 
    URIs in <termref def="dt-available-docs"
                        >available documents</termref> that map to a document
    node <code>D</code>, then the document-uri property of <code>D</code> must either be absent, or must
    be one of these URIs.</p>
                  <note>
                     <p>This means that given a document node <code>$N</code>, the result of
    <code
                           role="parse-test"
                           >fn:doc(fn:document-uri($N)) is $N</code> will always be <code>true</code>, unless
  <code
                           role="parse-test">fn:document-uri($N)</code> is an empty sequence.</p>
                  </note>-\->
               </item>


               <item>
                  <p>
                     <termdef id="dt-available-text-resources" term="available text resources">
                        <term>Available text resources</term>. 
  This is a mapping of strings to text resources. Each string
  represents the absolute URI of a resource. The resource is returned
  by the <function>fn:unparsed-text</function> function when applied to that
  URI.</termdef> The set of available text resources may be empty.</p>
               </item>
               
               <item>
                  <p>
                     <termdef id="dt-available-binary-resources" term="available binary resources">
                        <term>Available binary resources</term>. 
  This is a mapping of strings to binary resources. Each string
  represents the absolute URI of a resource. The resource is returned
  by the <code>fn:unparsed-binary</code> function when applied to that
  URI.</termdef> The set of available binary resources may be empty.</p>
               </item>


               <item>
                  <p>
                     <termdef id="dt-available-collections" term="available item collections">
                        <term>Available
                           collections.</term> This is a mapping of
                         strings to sequences of items. Each string
                         represents the absolute URI of a
                         resource. The sequence of items represents
                         the result of the <function>fn:collection</function>
                         function when that URI is supplied as the
                         argument. </termdef> The set of available
                            collections may be empty.</p>

                  <p>Ideally, for every document node <code>D</code> that is in the target of a 
                     mapping in <termref def="dt-available-collections"/>, or that is the root of a tree containing 
                     such a node, the document-uri property of <code>D</code> should either be absent, 
                     or should be a URI <code>U</code> such that <termref
                        def="dt-available-docs"/> contains a mapping from <code>U</code> to <code>D</code>.

</p>
                  <note>
                     <p>That is to say, the <code>document-uri</code> property of nodes returned
                        by the <function>fn:collection</function> function should be such that
                        calling <function>fn:doc</function> with that URI returns the relevant node.</p>
                     <p>It is not always possible to ensure this, especially in cases where 
                        dereferencing of document or collection URIs is configurable using
                        configuration files or user-supplied resolver code.</p>
                  </note>
               </item>
-->
                  <item>
                     <p>
                        <termdef id="dt-default-collection" term="default collection">
                           <term>Default  collection.</term>
    This is the sequence of items  that would result from calling the <function>fn:collection</function> function
    with no arguments.</termdef> The value of <term>default   collection</term> may be initialized by the
    implementation.</p>
                  </item>
                  <!--<item>
                  <p>
                     <termdef id="dt-available-uri-collections" term="available uri collections">
                        <term>Available
    URI collections.</term> This is a mapping of
    strings to sequences of URIs. The string
    represents the absolute URI of a
    resource which can be interpreted as an aggregation of a number of individual resources each of which
    has its own URI. The sequence of URIs represents
    the result of the <function>fn:uri-collection</function>
    function when that URI is supplied as the
    argument. </termdef> There is no implication that the URIs in this sequence
    can be successfully dereferenced, or that the resources they refer to have any particular media type.</p>
                  <note>
                     <p>An implementation <rfc2119>may</rfc2119> maintain some consistent relationship between the available
    collections and the available URI collections, for example by ensuring that the result of
  <code>fn:uri-collection(X)!fn:doc(.)</code> is the same as the result of <code>fn:collection(X)</code>.
    However, this is not required. The <function>fn:uri-collection</function> function is more 
    general than <function>fn:collection</function> in that <phrase diff="del" at="A">it allows access to resources other 
    than XML documents; at the same time,</phrase> <function>fn:collection</function> allows access to 
    nodes that might lack individual URIs, for example nodes corresponding 
    to XML fragments stored in the rows of a relational database.</p>
                  </note>
               </item>
-->
                  <item>
                     <p>
                        <termdef id="dt-default-uri-collection" term="default URI collection">
                           <term>Default URI collection.</term>
    This is the sequence of URIs that would result from calling the <function>fn:uri-collection</function> function
    with no arguments.</termdef> The value of <term>default URI collection</term> may be initialized by the
    implementation.</p>
                  </item>
                  <item>
                     <p>
                        <termdef id="dt-environment-variables" term="environment variables">
                           <term>Environment variables.</term>
  This is a mapping from names to values. 
    Both the names and the values are strings. The names are compared using an
    <termref def="dt-implementation-defined">implementation-defined</termref> collation, and are unique under this collation. The set of environment variables is
  <termref def="dt-implementation-defined">implementation-defined</termref> and <rfc2119>may</rfc2119> be empty.</termdef>
                     </p>
                     <note>
                        <p>A possible implementation is to provide the set of POSIX environment variables (or their equivalent on other
      operating systems) appropriate to the process in which the 
                        <phrase role="xpath">expression is evaluated</phrase>.</p>
                     </note>
                  </item>
               </ulist>
            </div3>
         </div2>
         <div2 id="id-security-resources">
            <head>External Resources and Security</head>
            <changes>
               <change issue="2047" PR="2213" date="2025-10-23">This section 
               (<quote>External Resources and Security</quote>) is new.</change>
            </changes>
            <p>The XPath, XQuery, and XSLT languages provide a number of capabilities
         to access external resources. These include:</p>
            <ulist>
               <item>
                  <p>Functions such as <function>doc</function>, <function>doc-available</function>,
            <function>unparsed-text</function>, <function>unparsed-text-lines</function>, 
               <function>unparsed-text-available</function>, <function>collection</function>
                     <function>uri-collection</function>, and <function>unparsed-binary</function>, and in XSLT,
            the <code nobreak="false">document</code> function and the <code nobreak="false">xsl:source-document</code>
            and <code nobreak="false">xsl:merge</code> instructions.</p>
               </item>
               <item>
                  <p>Static inclusion of code using <code nobreak="false">import module</code> in XQuery,
            or <code nobreak="false">xsl:include</code>, <code nobreak="false">xsl:import</code>, and <code nobreak="false">xsl:use-package</code>
            in XSLT.</p>
               </item>
               <item>
                  <p>Dynamic inclusion and execution of external code using the functions
               <function>transform</function> and <function>load-xquery-module</function>,
            and in XSLT, the <code nobreak="false">xsl:evaluate</code> instruction.</p>
               </item>
               <item>
                  <p>The ability to write to external resources using the 
               <code nobreak="false">xsl:result-document</code> instruction in XSLT, or the <function>put</function>
            function in the XQuery Update Facility.</p>
               </item>
               <item>
                  <p>The ability to invoke arbitrary user-defined external functions (called
            extension functions in XSLT).</p>
               </item>
               <item>
                  <p>The ability to invoke vendor-defined external/extension functions;
            a notable example being the EXPath File library.</p>
               </item>
               <item>
                  <p>Access to environment variables and system properties using functions such
            as <function>environment-variable</function>, <function>available-environment-variables</function>,
            and (in XSLT) <code nobreak="false">system-property</code>.</p>
               </item>
               <item>
                  <p>Static inclusion of XSD schemas and schema documents using 
               <code nobreak="false">import schema</code>in XQuery or <code nobreak="false">xsl:import-schema</code> in XSLT,
            or indirectly using <code nobreak="false">xs:import</code>, <code nobreak="false">xs:include</code>,
            <code nobreak="false">xs:redefine</code>, or <code nobreak="false">xs:override</code> in XSD schema documents.</p>
               </item>
               <item>
                  <p>Dynamic loading of XSD schema documents (directly or indirectly) 
               using the <function>xsd-validator</function> function.</p>
               </item>
               <item>
                  <p>The ability to parse XML or HTML documents that contain references to external 
               entities, for example by using the <code nobreak="false">parse-xml</code> and <code nobreak="false">parse-html</code>
            functions.</p>
               </item>
               <item>
                  <p>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 
               <code nobreak="false">xsi:schema-location</code>.</p>
               </item>
               <item>
                  <p>Implicit access to third-party libraries supporting (for example) collations
            or localization.</p>
               </item>
            </ulist>
            <p>External resources are always referenced by means of a URI. The way in which a URI
         is dereferenced to obtain a resource is <termref def="dt-implementation-defined"/>.
         It is <rfc2119>recommended</rfc2119> that popular URI schemes such as <code nobreak="false">http</code>, <code nobreak="false">https</code>,
         and <code nobreak="false">file</code> should be supported, but this <rfc2119>may</rfc2119> 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.</p>
            <p>
               <termdef id="dt-trusted" term="trusted">The static context 
            includes a boolean property called <term>trusted</term> that determines whether 
            external resources are available.</termdef> This may take the following values:</p>
            <olist>
               <item>
                  <p>
                     <term>false</term>: No external resources are available other than
               resources explicitly made available by the caller through some trusted implementation-defined
               mechanism.</p>
                  <p>
                     <termdef id="dt-untrusted" term="untrusted">Code executing 
                  with <termref def="dt-trusted"/> set to <code nobreak="false">false</code> is said to be <term>untrusted</term>.</termdef>
                  </p>
               </item>
               <item>
                  <p>
                     <term>true</term>: Trusted code has access to all the resources
               available to its immediate caller.</p>
               </item>
            </olist>
            <p>The functions <function>transform</function> and <function>load-xquery-module</function>,
            and the XSLT instruction <code nobreak="false">xsl:evaluate</code>, have an option
            allowing the trust level of the executed code to be set:</p>
            <olist>
               <item>
                  <p>If <code nobreak="false">trusted</code> is set to <code nobreak="false">true</code>, the invoked code executes
               with the same trust level as its caller.</p>
               </item>
               <item>
                  <p>If <code nobreak="false">trusted</code> is set to <code nobreak="false">false</code>, the invoked code is not able
               to access any external resources other than resources explicitly made available using
               an <termref def="dt-implementation-defined"/> mechanism under the control
               of the caller.</p>
               </item>
            </olist>
            <p>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 <function>parse-xml</function>, <code nobreak="false">doc</code>,
         or <code nobreak="false">collection</code>) therefore have a <code nobreak="false">trusted</code> option indicating
            whether the document being parsed is trusted to access external entities.
         Such access is allowed only if (a) the <code nobreak="false">trusted</code> option is set to <code nobreak="false">true</code>, 
         or (b) access to the external entity in question is explicitly enabled by the caller.</p>
            <note>
               <p>The term <term>explicitly enabled</term> 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.</p>
            </note>
            <p>It is <rfc2119>recommended</rfc2119> 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 <termref def="dt-trusted"/>.</p>
            <p>In the interests of security, the default for these options is <term>false</term>.
         However, for backwards compatibility reasons, processors <rfc2119>may</rfc2119> provide
         an option whereby a trusted user can change the default.</p>
            <p>In general, when an application requests access to an external resource which is
         not available because the application is untrusted, the processor <rfc2119>should</rfc2119> behave
         in the same way as if the resource did not exist. However, the processor <rfc2119>may</rfc2119>
         choose to disclose in its diagnostics why the request was unsuccessful.</p>
            <p>A processor <rfc2119>may</rfc2119> (but is not <rfc2119>required</rfc2119> to) 
            limit an application’s consumption of resources such as CPU cycles
         and memory when the application is untrusted.</p>
            <p>
               <termdef id="dt-available-docs" term="available documents">The term
         <term>available documents</term> refers (TODO: for the time being) to the set
         of XML documents that an application is able to access by URI.</termdef>
            </p>
         </div2>
         <div2 id="id-processing-model">
            <head>Processing Model</head>
            <changes>
               <change issue="1343" PR="1344" date="2024-09-03">
             The static typing option has been dropped.
           </change>
            </changes>
            <p>The semantics of XPath 4.0 are defined in terms
                         of the <termref def="dt-datamodel">data
                         model</termref> and the <termref def="dt-expression-context">expression
                         context</termref>.</p>
            <graphic xmlns:xlink="http://www.w3.org/1999/xlink"
                     source="procmod-xpath.svg"
                     alt="Processing                          Model Overview"
                     role="xpath"
                     xlink:type="simple"
                     xlink:show="embed"
                     xlink:actuate="onLoad"/>
            <p>Figure 1:
                         Processing Model Overview</p>
            <p>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 <term>external processing</term>. The external processing
domain includes generation of <termref def="dt-data-model-instance">XDM instances</termref> that represent the data to be queried (see <specref ref="id-data-model-generation"/>), schema import processing (see
<specref ref="id-schema-import-processing"/>), and serialization. The area inside the boundaries of
the language is known as the <phrase role="xpath">
                  <term>XPath processing domain</term>
               </phrase>, which includes the static
analysis and dynamic evaluation phases (see <specref ref="id-expression-processing"/>).  Consistency constraints on the

            <phrase role="xpath">XPath</phrase> processing domain are defined in <specref ref="id-consistency-constraints"/>.</p>
            <div3 id="id-data-model-generation">
               <head>Data Model Generation</head>
               <p>The input data for 
               <phrase role="xpath">an expression</phrase> must be represented as one or more <termref def="dt-data-model-instance">XDM instances</termref>. This process occurs outside
the domain of XPath 4.0, which is why Figure 1 represents it in the
external processing domain.</p>
               <p>In many cases the input data might originate as XML.
               Here are some steps by which an XML
document might be converted to an <termref def="dt-data-model-instance">XDM instance</termref>:</p>
               <olist>
                  <item>
                     <p id="DM1">A document may be parsed using an XML parser that
generates an <term>XML Information Set</term> (see <bibref ref="XINFO"/>). The parsed document may then be validated against one
or more schemas. This process, which is described in <loc xmlns:xlink="http://www.w3.org/1999/xlink"
                             href="http://www.w3.org/TR/xmlschema-1/"
                             xlink:type="simple"
                             xlink:show="replace"
                             xlink:actuate="onRequest">[XML Schema 1.0 Part 1]</loc> or
<loc xmlns:xlink="http://www.w3.org/1999/xlink"
                             href="http://www.w3.org/TR/xmlschema11-1/"
                             xlink:type="simple"
                             xlink:show="replace"
                             xlink:actuate="onRequest">[XML Schema 1.1 Part 1]</loc>, results in an abstract information structure called
the <term>Post-Schema Validation Infoset</term> (PSVI). If a document
has no associated schema, its Information Set is preserved. (See DM1
in Figure 1)</p>
                  </item>
                  <item>
                     <p id="DM2">The Information Set or PSVI may be
transformed into an <termref def="dt-data-model-instance">XDM instance</termref>
by a process described in <bibref ref="xpath-datamodel-40"/>. (See DM2 in
Figure 1)</p>
                  </item>
               </olist>
               <p id="DM3">The above steps provide an example of how an <termref def="dt-data-model-instance">XDM instance</termref> might be constructed. An XDM instance might
also be constructed in some other way (see DM3 in Figure 1), for example it might be 
synthesized directly from a relational database, or
derived by parsing a JSON text or a CSV file. Whatever the origin, XPath 4.0 is defined in terms
of the <termref def="dt-datamodel">data model</termref>,
but it does not place any constraints on how XDM instances are constructed.</p>
               <p>The remainder of this section is concerned with the common case where XML data is being processed.</p>
               <p>
                  <termdef term="type annotation" id="dt-type-annotation">Each element node and attribute node in an <termref def="dt-data-model-instance">XDM instance</termref> has a <term>type annotation</term> (described in <xspecref spec="DM40" ref="types"/>). 
The type annotation of a node is a reference to a <termref def="dt-schema-type"/>. 
</termdef>  The <code nobreak="false">type-name</code> of a node is the name of the type referenced by its <termref def="dt-type-annotation">type annotation</termref> (but note that the
               type annotation can be a reference to an anonymous type). 
If the <termref def="dt-data-model-instance">XDM instance</termref> was derived from a validated XML document as described in <xspecref spec="DM40" ref="const-psvi"/>, the type annotations of the element and attribute nodes are derived from schema
validation. XPath 4.0 does
not provide a way to directly access the type annotation of an element
or attribute node.</p>
               <p>The value of an attribute is represented directly within the
attribute node. An attribute node whose type is unknown (such as might
occur in a schemaless document) is given the <termref def="dt-type-annotation">type annotation</termref>
                  <code nobreak="false">xs:untypedAtomic</code>.</p>
               <p>The value of an element is represented by the children of the
element node, which may include text nodes and other element
nodes. The <termref def="dt-type-annotation">type annotation</termref> of an element node indicates how the values in
its child text nodes are to be interpreted. An element that has not been validated (such as might occur in a schemaless document) is annotated
with the <termref def="dt-schema-type"/>
                  <code nobreak="false">xs:untyped</code>. An element that has been validated and found to be partially valid is annotated with the schema type <code nobreak="false">xs:anyType</code>. If an element node is annotated as <code nobreak="false">xs:untyped</code>, all its descendant element nodes are also annotated as <code nobreak="false">xs:untyped</code>. However, if an element node is annotated as <code nobreak="false">xs:anyType</code>, some of its descendant element nodes may have a more specific <termref def="dt-type-annotation">type annotation</termref>.</p>
            </div3>
            <div3 id="id-schema-import-processing">
               <head>Schema Import Processing</head>
               <p role="xpath">The <termref def="dt-issd">in-scope schema
definitions</termref> in the <termref def="dt-static-context">static
context</termref> are provided by the host language (see step SI1 in
Figure 1) and must satisfy the consistency constraints defined in
<specref ref="id-consistency-constraints"/>.

</p>
            </div3>
            <div3 id="id-expression-processing">
               <head>Expression
Processing</head>
               <p>XPath 4.0 defines two phases of processing called
the <termref def="dt-static-analysis">static analysis phase</termref>
and the <termref def="dt-dynamic-evaluation">dynamic evaluation
phase</termref> (see Figure 1).  During the static analysis phase, <termref def="dt-static-error">static errors</termref>,  <termref def="dt-dynamic-error">dynamic errors</termref>, or <termref def="dt-type-error">type errors</termref> may be raised. During the dynamic evaluation phase, only <termref def="dt-dynamic-error">dynamic errors</termref> or <termref def="dt-type-error">type errors</termref> may be raised. These kinds of errors are defined in <specref ref="id-kinds-of-errors"/>.  </p>
               <p>Within each phase, an implementation is free to use any
strategy or algorithm whose result conforms to the
specifications in this document.</p>
               <div4 id="id-static-analysis">
                  <head>Static Analysis Phase</head>
                  <p>
                     <termdef id="dt-static-analysis" term="static analysis phase">The
<term>static analysis phase</term> depends on the expression itself
and on the <termref def="dt-static-context">static context</termref>. The <term>static analysis phase</term> does
not depend on input data (other than schemas).</termdef>
                  </p>
                  <p id="SQ1234">During the static analysis phase, the 
                  <phrase role="xpath">XPath expression</phrase> is typically parsed into an
internal representation called the <term>operation tree</term> (step
SQ1 in Figure 1).  A parse error is raised as a <termref def="dt-static-error">static error</termref>
                     <errorref class="ST" code="0003"/>. The <termref def="dt-static-context">static context</termref> is initialized by the implementation (step SQ2).  The <termref def="dt-static-context">static context</termref> 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 <term>operation tree</term> is
not found in the <termref def="dt-static-context">static context</termref>, a <termref def="dt-static-error">static error</termref> (<errorref class="ST" code="0008"/> or <errorref class="ST" code="0017"/>) is raised (however, see exceptions to this rule in <specref ref="id-element-test"/> and <specref ref="id-attribute-test"/>.)</p>
                  <p id="SQ5">The <term>operation tree</term> is then typically
normalized by making explicit the implicit operations
such as <termref def="dt-atomization">atomization</termref> and extraction of <termref def="dt-ebv">effective boolean values</termref> (step SQ5).</p>
                  <p>During the <termref def="dt-static-analysis">static analysis
phase</termref>, a processor may perform type analysis. The
effect of type analysis is to assign a <termref def="dt-static-type">static type</termref> to each expression in the
operation tree. <termdef id="dt-static-type" term="static type">The
<term>static type</term> of an expression is the best inference that
the processor is able to make statically about the type of the result
of the expression.</termdef> 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.</p>
                  <p>Examples of inferred static types might be:</p>
                  <ulist>
                     <item>
                        <p>For the expression <code nobreak="false">concat(a,b)</code> the inferred static type is <code nobreak="false">xs:string</code>
                        </p>
                     </item>
                     <item>
                        <p>For the expression <code nobreak="false">$a = $v</code> the inferred static type is <code nobreak="false">xs:boolean</code>
                        </p>
                     </item>
                     <item>
                        <p>For the expression <code nobreak="false">$s[exp]</code> the inferred static
    type has the same item type as the static type of <code nobreak="false">$s</code>,
    but a cardinality that allows the empty sequence even if the
    static type of <code nobreak="false">$s</code> does not allow the empty
    sequence.</p>
                     </item>
                     <item>
                        <p>The inferred static type of the expression <code nobreak="false">data($x)</code> (whether written
    explicitly or inserted into the operation tree in places where atomization
    is implicit) depends on the inferred static type of <code nobreak="false">$x</code>: for example, if <code nobreak="false">$x</code>
    has type <code nobreak="false">element(*, xs:integer)</code> then <code nobreak="false">data($x)</code> has static type <code nobreak="false">xs:integer</code>.</p>
                     </item>
                  </ulist>
                  <p>In XQuery 1.0 and XPath 2.0, rules for static type inferencing were published
normatively in <bibref ref="xquery-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.</p>
                  <p>Every kind of expression also imposes requirements on the type of its
operands. For example, with the expression <code nobreak="false">substring($a, $b, $c)</code>, <code nobreak="false">$a</code> must be
of type <code nobreak="false">xs:string</code> (or something that can be converted to <code nobreak="false">xs:string</code> by the
function calling rules), while <code nobreak="false">$b</code> and <code nobreak="false">$c</code> must be numeric.</p>
                  <p>A processor <rfc2119>may</rfc2119> 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 <termref def="dt-coercion-rules"/>. For example,
                     given the call <code nobreak="false">fn:upper-case($s)</code>, the processor <rfc2119>may</rfc2119> raise an error if the
                     declared or inferred type of <code nobreak="false">$s</code> is <code nobreak="false">xs:integer</code>, 
                     but not if it is <code nobreak="false">xs:anyAtomicType</code>.
                  </p>
                  <p>In addition, type analysis <rfc2119>may</rfc2119> conclude that an expression is <termref def="dt-implausible"/>.
               Implausible expressions may be considered erroneous unless such checks have been disabled.
               For example, the expression <code nobreak="false">round(tokenize($input))</code> is implausible because 
                  the required type for <function>fn:round</function> is <code nobreak="false">xs:numeric?</code>,
                  while the static type of <code nobreak="false">tokenize($input)</code> is <code nobreak="false">xs:string*</code>,
                  and these two sequence types are <termref def="dt-substantively-disjoint"/>.
               This topic is described further in <specref ref="id-implausible-expressions"/>.</p>
                  <p>Alternatively, the processor
                  <rfc2119>may</rfc2119> defer all type checking until the dynamic evaluation phase.</p>
               </div4>
               <div4 id="id-dynamic-evaluation">
                  <head>Dynamic Evaluation Phase</head>
                  <p id="DQ12345">
                     <termdef id="dt-dynamic-evaluation" term="dynamic evaluation phase">The <term>dynamic evaluation phase</term> is the phase during which the value of an expression is computed.</termdef> It is dependent on successful completion of the <termref def="dt-static-analysis">static analysis phase</termref>.</p>
                  <p>The dynamic evaluation phase can occur only if no errors were detected during the <termref def="dt-static-analysis">static analysis phase</termref>.</p>
                  <p>The dynamic evaluation phase depends on the <term>operation
tree</term> of the expression being evaluated (step DQ1), on the input
data (step DQ4), and on the <termref def="dt-dynamic-context">dynamic context</termref> (step DQ5), which in turn draws information from  the external environment (step DQ3) and the <termref def="dt-static-context">static context</termref> (step DQ2). The dynamic evaluation phase may create new data-model values (step DQ4) and it may extend the <termref def="dt-dynamic-context">dynamic context</termref> (step DQ5)—for example, by binding values to variables.</p>
                  <p diff="chg" at="B">
                     <termdef term="dynamic type" id="dt-dynamic-type">
                  Every value matches one or more <termref def="dt-sequence-type">sequence types</termref>. 
                     A value is said to have a <term>dynamic type</term>
                        <var>T</var> if it matches (or <term>is an instance of</term>) 
                     the sequence type <var>T</var>.</termdef>
                  </p>
                  <p diff="chg" at="B">In many cases (but not all), one of the dynamic types that a value matches will 
                     be a subtype of all the others, in which case it makes sense to speak of “the dynamic type” of the value as 
                     meaning this single most specific type. In other cases (examples are 
                     <xtermref spec="DM40" ref="dt-empty-map">empty maps</xtermref> and 
                     <xtermref spec="DM40" ref="dt-empty-array">empty arrays</xtermref>) none of the 
                     dynamic types is more specific than all the others.</p>
                  <note diff="chg" at="B">
                     <p>An atomic item has a <termref def="dt-type-annotation"/> which will always be
                  a <termref def="dt-subtype"/> of all the other types that it matches; we can therefore refer to 
                  this as the <termref def="dt-dynamic-type"/> of the atomic item without ambiguity.</p>
                  </note>
                  <p diff="chg" at="B">A value may match a dynamic type that is more specific than the <termref def="dt-static-type"/> 
                  of the expression that computed it (for example, the static type of an expression might be <code nobreak="false">xs:integer*</code>, 
                  denoting a sequence of zero or more integers, but at evaluation time its value may be an instance of <code nobreak="false">xs:integer</code>, 
                  denoting exactly one integer).
               </p>
                  <p diff="chg" at="B">If an operand of an expression does not have a <termref def="dt-dynamic-type">dynamic type</termref> that is a <termref def="dt-subtype"/> of the <termref def="dt-static-type"/>
                  required for that operand, a <termref def="dt-type-error">type error</termref> is
                  raised <errorref class="TY" code="0004"/>.</p>
                  <p>Even though static typing can catch many <termref def="dt-type-error">type errors</termref> before an expression is executed, it is possible for an expression to raise an error during evaluation that was not detected by static  analysis. For example, an expression may contain a cast of a string into an integer, which is statically valid. However, if the actual value of the string at run time cannot be cast into an integer, a <termref def="dt-dynamic-error">dynamic error</termref> will result. Similarly, an expression may apply an arithmetic operator to a value whose <termref def="dt-static-type">static type</termref> is <code nobreak="false">xs:untypedAtomic</code>. This is not a <termref def="dt-static-error">static error</termref>, but at run time, if the value cannot be successfully cast to a <termref def="dt-numeric">numeric</termref> type, a <termref def="dt-dynamic-error">dynamic error</termref> will be raised.</p>
               </div4>
            </div3>
            <div3 id="id-input-sources">
               <head>Input Sources</head>
               <p>XPath 4.0 has a set of functions that provide access to XML documents (<function>fn:doc</function>, <function>fn:doc-available</function>), collections (<function>fn:collection</function>, <function>fn:uri-collection</function>), text files (<function>fn:unparsed-text</function>, <function>fn:unparsed-text-lines</function>, <function>fn:unparsed-text-available</function>), and environment variables (<function>fn:environment-variable</function>, <function>fn:available-environment-variables</function>).  These functions are defined in <xspecref spec="FO40" ref="fns-on-docs"/>.</p>
               <p>An expression can access input data either by calling one
               of these input functions or by referencing some part of the
               <termref def="dt-dynamic-context">dynamic context</termref> that is initialized by the external
               environment, such as a <termref def="dt-variable-values">variable</termref> or
               <termref def="dt-context-value"/>.</p>
               <note>
                  <p>The <loc xmlns:xlink="http://www.w3.org/1999/xlink"
                          href="http://expath.org"
                          xlink:type="simple"
                          xlink:show="replace"
                          xlink:actuate="onRequest">EXPath Community Group</loc> has developed a <loc xmlns:xlink="http://www.w3.org/1999/xlink"
                          href="http://expath.org/spec/file"
                          xlink:type="simple"
                          xlink:show="replace"
                          xlink:actuate="onRequest">File Module</loc>, which some implementations use to perform file system related operations 
                  such as reading or writing files and directories. Multiple files can be read or written 
                  from a single query.</p>
               </note>
            </div3>
            <div3 id="id-serialization">
               <head>Serialization</head>
               <p>
                  <termdef id="dt-serialization" term="serialization">
                     <term>Serialization</term> is the process of
converting an <termref def="dt-data-model-instance">XDM
instance</termref> to a sequence of octets (step DM4 in Figure 1.),
as described in <bibref ref="xslt-xquery-serialization-40"/>.</termdef>
               </p>
               <note>
                  <p>This definition of serialization is the definition
used in this specification. Any form of serialization that is
not based on <bibref ref="xslt-xquery-serialization-40"/> is outside
the scope of the XPath 4.0 specification.</p>
               </note>
               <p role="xpath">Serialization is outside the scope of the XPath specification, except
               to the extent that there is a function <function>fn:serialize</function> that enables
               serialization to be invoked.</p>
            </div3>
            <div3 id="id-consistency-constraints">
               <head>Consistency Constraints</head>
               <p>In order for XPath 4.0 to
be well defined, the input <termref def="dt-data-model-instance">XDM instances</termref>, the <termref def="dt-static-context">static context</termref>, and the <termref def="dt-dynamic-context">dynamic context</termref> must be mutually
consistent. The consistency constraints listed below are prerequisites
for correct functioning of an XPath 4.0 implementation. Enforcement
of these consistency constraints is beyond the scope of this
specification. This specification does not
define the result of  
               <phrase role="xpath">an expression</phrase> under any condition in which one
or more of these constraints is not satisfied.</p>
               <ulist>
                  <item>
                     <p>For every  node that has a type annotation, if that type annotation is found in the <termref def="dt-issd">in-scope schema definitions</termref> (ISSD), then its definition in the ISSD must be 
                     <phrase diff="chg" at="Issue451">
                           <xtermref ref="dt-schema-compatible" spec="DM40">compatible</xtermref>
                        </phrase> with its definition 
                     in the <xtermref ref="dt-schema" spec="DM40">schema</xtermref> that was used to validate the node. 
                  </p>
                  </item>
                  <item>
                     <p>Every element name, attribute name, or schema type name referenced in <termref def="dt-in-scope-variables"/> or <termref def="dt-statically-known-function-definitions"/>
                         must be in the <termref def="dt-issd">in-scope schema definitions</termref>, unless it is an element name referenced as part of an <nt def="doc-xpath40-ElementNodeType"><!--$spec = xpath40--></nt> or an attribute name referenced as part of an <nt def="doc-xpath40-AttributeNodeType"><!--$spec = xpath40--></nt>.</p>
                  </item>
                  <item>
                     <p>Any reference to a global element, attribute, or type name in
the <termref def="dt-issd">in-scope schema definitions</termref> must have a corresponding element, attribute or type
definition in the <termref def="dt-issd">in-scope schema definitions</termref>.</p>
                  </item>
                  <item>
                     <p>For each (variable, type) pair in <termref def="dt-in-scope-variables">in-scope variables</termref> and the corresponding (variable, value) pair in <termref def="dt-variable-values">variable values</termref> such that the variable names are equal, the value must match the type, using the matching rules in  <specref ref="id-sequencetype-matching"/>.</p>
                  </item>
                  <item>
                     <p>In the <termref def="dt-static-namespaces">statically known namespaces</termref>, the prefix <code nobreak="false">xml</code> must not be bound to any namespace URI other than <code nobreak="false">http://www.w3.org/XML/1998/namespace</code>, and no prefix other than <code nobreak="false">xml</code> may be bound to this namespace URI.
The prefix <code nobreak="false">xmlns</code> must not be bound to any namespace URI, and no prefix may be bound to the namespace URI <code nobreak="false">http://www.w3.org/2000/xmlns/</code>.</p>
                  </item>
               </ulist>
            </div3>
         </div2>
         <div2 id="errors">
            <head>Error Handling</head>
            <div3 id="id-kinds-of-errors">
               <head>Kinds of Errors</head>
               <p>
As described in <specref ref="id-expression-processing"/>, XPath 4.0
defines a <termref def="dt-static-analysis">static analysis phase</termref>, which does not depend on input
data, and a <termref def="dt-dynamic-evaluation">dynamic evaluation
phase</termref>, which does depend on input
data.  Errors may be raised during each phase.</p>
               <p>
                  <termdef id="dt-static-error" term="static error">
An error that can be detected during the static analysis phase, and is not a type error, is a <term>static error</term>.</termdef> A syntax error is an example of a <termref def="dt-static-error">static error</termref>.</p>
               <p>
                  <termdef id="dt-dynamic-error" term="dynamic error">A <term>dynamic
error</term> is an error that
must be detected during the dynamic evaluation phase and may be detected
during the static analysis phase.</termdef>
Numeric overflow is an example of a <termref def="dt-dynamic-error">dynamic error</termref>.
            </p>
               <p>
                  <termdef id="dt-type-error" term="type error">A <term>type
error</term> may be raised during the static analysis phase or the dynamic evaluation phase.
During the static analysis phase, a <termref def="dt-type-error">type error</termref> occurs
when the <termref def="dt-static-type">static type</termref> of an expression does not match the expected type
of the context in which the expression occurs.
During the dynamic evaluation phase, a <termref def="dt-type-error">type error</termref> occurs
when the <termref def="dt-dynamic-type">dynamic type</termref> of a value does not match the expected type of
the context in which the value occurs.</termdef>
               </p>
               <p>The outcome of the <termref def="dt-static-analysis">static analysis
phase</termref> is either success or one or more <termref def="dt-type-error">type errors</termref>, <termref def="dt-static-error">static errors</termref>, or statically detected <termref def="dt-dynamic-error">dynamic errors</termref>. The result of the <termref def="dt-dynamic-evaluation">dynamic evaluation
phase</termref> is either a result value, a <termref def="dt-type-error">type
error</termref>, or a <termref def="dt-dynamic-error">dynamic error</termref>.</p>
               <p>If more than one error is present, or if an error condition comes within the
scope of more than one error defined in this specification, then any non-empty
subset of these errors may be reported.</p>
               <p>If an implementation can determine during the
<termref def="dt-static-analysis">static
analysis phase</termref> that 
               <phrase role="xpath">an XPath expression</phrase>, if evaluated, would necessarily
raise a <termref def="dt-dynamic-error">dynamic error</termref> or that an expression, if evaluated, would necessarily raise a <termref def="dt-type-error">type error</termref>, the implementation may (but is not required to) report that
error during the <termref def="dt-static-analysis">static
analysis phase</termref>.</p>
               <p>An implementation can raise a <termref def="dt-dynamic-error">dynamic error</termref> for 
               <phrase role="xpath">an XPath expression</phrase> statically only if the 
               <phrase role="xpath">expression</phrase> can never execute without raising that error, as in the following example:</p>
               <eg role="parse-test" xml:space="preserve">
error()
</eg>
               <p>The following example contains a type error, which can be reported statically even if the implementation can not prove that the expression will actually be evaluated.</p>
               <eg role="parse-test" xml:space="preserve">
if (empty($arg))
then "cat" * 2
else 0
</eg>
               <p>
                  <termdef id="dt-warning" term="warning">In addition to <termref def="dt-static-error">static errors</termref>, <termref def="dt-dynamic-error">dynamic errors</termref>, and <termref def="dt-type-error">type
errors</termref>, an XPath 4.0
implementation may raise <term>warnings</term>, either during the <termref def="dt-static-analysis">static analysis
phase</termref> or the
<termref def="dt-dynamic-evaluation">dynamic evaluation
phase</termref>. The circumstances in which warnings are raised, and
the ways in which warnings are handled, are <termref def="dt-implementation-defined">implementation-defined</termref>.</termdef>
               </p>
               <p>In addition to the errors defined in this
specification, an implementation may raise a <termref def="dt-dynamic-error">dynamic error</termref> for a reason beyond the scope of this specification. For
example, limitations may exist on the maximum
numbers or sizes of various objects. 
<phrase id="id-error-limit-exceeded">An error must be raised if such a limitation is exceeded  <errorref class="DY" code="0130"/>.</phrase>
               </p>
            </div3>
            <div3 id="id-identifying-errors">
               <head>Identifying and Reporting Errors</head>
               <p>The errors defined in this specification are identified by QNames that have the form <code role="xpath" nobreak="false">err:XPYYnnnn</code>
               , where:</p>
               <ulist>
                  <item>
                     <p>
                        <code nobreak="false">err</code> denotes the namespace for XPath and XQuery errors, <code nobreak="false">http://www.w3.org/2005/xqt-errors</code>. This binding of the namespace prefix <code nobreak="false">err</code> is used for convenience in this document, and is not normative.</p>
                  </item>
                  <item role="xpath">
                     <p>
                        <code nobreak="false">XP</code> identifies the error as an XPath error (some errors, originally defined by XQuery and later added to XPath, use the code <code nobreak="false">XQ</code> instead).</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">YY</code> denotes the error category, using the following encoding:</p>
                     <ulist>
                        <item>
                           <p>
                              <code nobreak="false">ST</code> denotes a static error.</p>
                        </item>
                        <item>
                           <p>
                              <code nobreak="false">DY</code> denotes a dynamic error.</p>
                        </item>
                        <item>
                           <p>
                              <code nobreak="false">TY</code> denotes a type error.</p>
                        </item>
                     </ulist>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">nnnn</code> is a unique numeric code.</p>
                  </item>
               </ulist>
               <note>
                  <p>The namespace URI for  XPath and XQuery errors is not expected to
change from one version of 
                  <phrase role="xpath">XPath</phrase> to another. However, the contents of this
namespace may be extended to include additional error definitions.</p>
               </note>
            </div3>
            <div3 id="id-handling-dynamic">
               <head>Handling Dynamic Errors</head>
               <p>Except as noted in this document, if any operand of an expression
raises a <termref def="dt-dynamic-error">dynamic error</termref>, the expression also raises a <termref def="dt-dynamic-error">dynamic error</termref>.
If an expression can validly return a value or raise a dynamic
error, the implementation may choose to return the value or raise
the dynamic error (see <specref ref="id-errors-and-opt"/>).  For example, the logical expression
<code nobreak="false">expr1 and expr2</code> may return the value <code nobreak="false">false</code>
if either operand returns <code nobreak="false">false</code>,
or may raise a dynamic error if either operand raises a dynamic
error.</p>
               <p> If more than one operand of an expression raises
an error, the
implementation may choose which error is raised by the expression.
For example, in this expression:

</p>
               <eg role="parse-test" xml:space="preserve">($x div $y) + xs:decimal($z)</eg>
               <p>

both the sub-expressions <code role="parse-test" nobreak="false">($x div $y)</code> and <code role="parse-test" nobreak="false">xs:decimal($z)</code> may
raise an error.  The
implementation may choose which error is raised by the <code nobreak="false">+</code>
expression.  Once one operand raises an error, the implementation is
not required, but is permitted, to evaluate any other operands.</p>
               <p>
                  <termdef id="dt-error-value" term="error value">In addition to its identifying QName, a dynamic error may also carry a descriptive string and one or more additional values called <term>error values</term>.</termdef> An implementation may provide a mechanism whereby an application-defined error handler can process error values and produce diagnostic messages. 
  
  <phrase role="xpath">The host language may also provide error handling mechanisms.</phrase>
               </p>
               <p>A dynamic error may be raised by a <termref def="dt-system-function">system
function</termref> or operator.  For example,
the <code nobreak="false">div</code> operator raises an error if its operands are <code nobreak="false">xs:decimal</code> values and its second operand
is equal to zero. Errors raised by system functions and operators are defined in <bibref ref="xpath-functions-40"/> or the host language.</p>
               <p>A dynamic error can also be raised explicitly by calling the
<function>fn:error</function> function, which always raises a dynamic error and never
returns a value.  This function is defined in <xspecref spec="FO40" ref="func-error"/>. For example, the following
function call raises a dynamic
error, providing a QName that identifies the error, a descriptive string, and a diagnostic value (assuming that the prefix <code nobreak="false">app</code> is bound to a namespace containing application-defined error codes):</p>
               <eg role="parse-test" xml:space="preserve">error( #app:err057, "Unexpected value", string($v) )</eg>
            </div3>
            <div3 id="id-errors-and-opt">
               <head>Errors and
      Optimization</head>
               <p>Because different implementations may
      choose to evaluate or optimize an expression in different ways,
      certain aspects of raising <termref def="dt-dynamic-error">dynamic errors</termref> are <termref def="dt-implementation-dependent">implementation-dependent</termref>, as described in this section.</p>
               <p>An implementation is always free to evaluate the operands of an operator in any order.</p>
               <p>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 <termref def="dt-filter-expression">filter expressions</termref> suggests that <code role="parse-test" nobreak="false">$s[1]</code> should be evaluated by examining all the items in sequence <code nobreak="false">$s</code>, and selecting all those that satisfy the predicate <code role="parse-test" nobreak="false">position()=1</code>. In practice, many implementations will recognize that they can evaluate this expression by taking the first item in the sequence and then exiting. If <code nobreak="false">$s</code> is defined by an expression such as <code role="parse-test" nobreak="false">//book[author eq 'Berners-Lee']</code>, 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 <code nobreak="false">book</code> element in the input data with more than one <code nobreak="false">author</code> subelement.</p>
               <p>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.</p>
               <p>Consider an expression <emph>Q</emph> that has an operand (sub-expression) <emph>E</emph>. In general the value of <emph>E</emph> 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 <emph>Q</emph>, namely the value <emph>V</emph> or an error, then the processor may deliver the result <emph>V</emph> without evaluating further items in the operand <emph>E</emph>. 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.</p>
               <p>There is an exception to this rule: If a processor evaluates an operand <emph>E</emph> (wholly or in part), then it  is required to establish that the actual value of the operand <emph>E</emph> does not violate any constraints on its cardinality. For example, the expression <code role="parse-test" nobreak="false">$e eq 0</code> results in a type error if the value of <code nobreak="false">$e</code> contains two or more items. A processor is not allowed to decide, after evaluating the first item in the value of <code nobreak="false">$e</code> and finding it equal to zero, that the only possible outcomes are the value <code nobreak="false">true</code> or a type error caused by the cardinality violation. It must establish that the value of <code nobreak="false">$e</code> contains no more than one item.</p>
               <p>These rules apply to all the operands of an expression considered in combination: thus if an expression has two operands <emph>E1</emph> and <emph>E2</emph>, it may be evaluated using any samples of the respective sequences that satisfy the above rules.</p>
               <p>The rules cascade: if <emph>A</emph> is an operand of <emph>B</emph> and <emph>B</emph> is an operand of <emph>C</emph>, then the processor needs to evaluate only a sufficient sample of <emph>B</emph> to determine the value of <emph>C</emph>, and needs to evaluate only a sufficient sample of <emph>A</emph> to determine this sample of <emph>B</emph>.</p>
               <p>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 <code nobreak="false">true</code> as the result of the expression <code role="parse-test" nobreak="false">S1 = S2</code> as soon as it finds a pair of equal values from the two sequences.</p>
               <p>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 the empty sequence is not permitted in the relevant context, then the processor must ensure that the operand is not the empty sequence.</p>
               <p>Examples:</p>
               <ulist>
                  <item>
                     <p>If an implementation can find (for example, by using an index) that at
least one item returned by <code nobreak="false">$expr1</code> in the following example has the value <code nobreak="false">47</code>, it is allowed to
return <code nobreak="false">true</code> as the result of the <code nobreak="false">some</code> expression, without searching for
another item returned by <code nobreak="false">$expr1</code> that would raise an error if it were evaluated.
</p>
                     <eg role="parse-test" xml:space="preserve">some $x in $expr1 satisfies $x = 47</eg>
                  </item>
                  <item>
                     <p>In the following example, if an implementation can find (for example, by using an index) the
<code nobreak="false">product</code> element-nodes that have an <code nobreak="false">id</code> child with the value <code nobreak="false">47</code>, it is allowed to return these nodes as the
result of the <termref def="dt-path-expression">path expression</termref>, without searching for another <code nobreak="false">product</code> node that
would raise an error because it has an <code nobreak="false">id</code> child whose value is not an integer.</p>
                     <eg role="parse-test" xml:space="preserve">//product[id = 47]</eg>
                  </item>
               </ulist>
               <!-- <change diff="chg" at="XQ.E4 and XP.E4"> -->
               <p>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:
          </p>
               <ulist>
                  <item>
                     <p>
                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.
             </p>
                     <note>
                        <p>
                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.
             </p>
                     </note>
                     <note>
                        <p>
                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
                <termref def="dt-implementation-dependent">implementation-dependent</termref>
                or <termref def="dt-implementation-defined">implementation-defined</termref>.
             </p>
                     </note>
                  </item>
                  <item>
                     <p diff="add" at="B">
                     The rules described in <specref ref="id-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.</p>
                  </item>
                  <item>
                     <p>
                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.</p>
                  </item>
                  <item>
                     <p>
                     As stated earlier, an expression
                     must not be rewritten to dispense with a
                     required cardinality check: for example, <code role="parse-test" nobreak="false">string-length(//title)</code>
                     must raise an
                     error if the document contains more than one title element.
                  </p>
                  </item>
               </ulist>
            </div3>
            <div3 id="id-guarded-expressions" diff="add" at="B">
               <head>Guarded Expressions</head>
               <changes>
                  <change issue="71" PR="230" date="2022-11-15">
                  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 <code nobreak="false">and</code> and <code nobreak="false">or</code>,
                  and of predicates in filter expressions, in a way that might allow the processor to raise dynamic
                  errors that the author intended to prevent.
               </change>
               </changes>
               <p>
                  <termdef id="dt-guarded" term="guarded">An expression <var>E</var> is said to be <term>guarded</term>
               by some governing condition <var>C</var> if evaluation of <var>E</var> is not allowed to fail
               with a <termref def="dt-dynamic-error"/> except when <var>C</var> applies.</termdef>
               </p>
               <p>For example, in a conditional expression <code nobreak="false">if (P) then T else F</code>, the subexpression
               <var>T</var> is guarded by <var>P</var>, and the subexpression <var>F</var> is guarded by
               <code nobreak="false">not(P)</code>. One way an implementation can satisfy this rule is by not evaluating <var>T</var> unless <var>P</var>
               is true, and likewise not evaluating <var>F</var> unless <var>P</var> 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.
            </p>
               <p>The existence of this rule enables errors to be prevented by writing expressions such as
            <code nobreak="false">if ($y eq 0) then "N/A" else ($x div $y)</code>. This example will never fail with a divide-by-zero
            error because the <code nobreak="false">else</code> branch of the conditional is <termref def="dt-guarded"/>.</p>
               <p>Similarly, in the mapping expression <code nobreak="false">
                     <var>E1</var>!<var>E2</var>
                  </code>, the subexpression <var>E2</var> is guarded
            by the existence of an item from <var>E1</var>. This means, for example, that the expression <code nobreak="false">(1 to $n)!doc('bad.xml')</code>
            must not raise a dynamic error if <code nobreak="false">$n</code> 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.</p>
               <p>The complete list of expressions that have guarded subexpressions is as follows:</p>
               <ulist>
                  <item>
                     <p>In a conditional expression (<nt def="doc-xpath40-IfExpr">IfExpr<!--$spec = xpath40--></nt>) the <code nobreak="false">then</code> branch
                  is guarded by the condition being true, and the <code nobreak="false">else</code> branch
                  is guarded by the condition being false.</p>
                  </item>
                  <item>
                     <p>In an <termref def="dt-and-expression"/>, the second operand
               is guarded by the value of the first operand being true.</p>
                  </item>
                  <item>
                     <p>In an <termref def="dt-or-expression"/>, the second operand
                  is guarded by the value of the first operand being false.</p>
                  </item>
                  <item>
                     <p>In an <code nobreak="false">otherwise</code> expression (<nt def="doc-xpath40-OtherwiseExpr">OtherwiseExpr<!--$spec = xpath40--></nt>), the second operand
                  is guarded by the value of the first operand being the empty sequence.</p>
                  </item>
                  <item>
                     <p>In a path expression of the form <code nobreak="false">
                           <var>E1</var>/<var>E2</var>
                        </code> 
                  or <code nobreak="false">
                           <var>E1</var>//<var>E2</var>
                        </code>, and in a mapping
               expression of the form <code nobreak="false">
                           <var>E1</var>!<var>E2</var>
                        </code>, the right-hand operand <var>E2</var> is guarded by
               the existence of at least one item in the result of evaluating <var>E1</var>.</p>
                     <p>This rule applies even if <var>E2</var> does not reference the context value.
                     For example, no dynamic error can be thrown by the expression 
               <code nobreak="false">(1 to $n)!doc('bad.xml')</code> in the case where <code nobreak="false">$n</code> is zero.</p>
                  </item>
                  <item>
                     <p>In a filter expression of the form <code nobreak="false">
                           <var>E</var>[<var>P</var>]</code>, 
                  the predicate <var>P</var> is guarded by
                  the existence of at least one item in the result of evaluating <var>E</var>.</p>
                     <p>This rule has the consequence that in a filter expression with multiple predicates, 
                  such as <code nobreak="false">
                           <var>E</var>[<var>P1</var>][<var>P2</var>]</code>,
               evaluation of <var>P2</var> must not raise a dynamic error unless <var>P1</var> returns <code nobreak="false">true</code>. 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.</p>
                  </item>
                  <item>
                     <p role="xpath">In a <code nobreak="false">for</code> expression (<nt def="doc-xpath40-ForExpr">ForExpr<!--$spec = xpath40--></nt>) such
                  as <code nobreak="false">for $x in <var>S</var> return <var>E</var>
                        </code>, 
                  the expression <var>E</var> is guarded by the existence of
                  an item bound to <code nobreak="false">$x</code>.</p>
                     <p>This means that the expression <code nobreak="false">for $x in 1 to $n return doc('bad.xml')</code>
               must not raise a dynamic error in the case where <code nobreak="false">$n</code> is zero.</p>
                  </item>
                  <item>
                     <p>In a <code nobreak="false">quantified</code> expression (<nt def="doc-xpath40-QuantifiedExpr">QuantifiedExpr<!--$spec = xpath40--></nt>) such
                  as <code nobreak="false">some $x in <var>S</var> satisfies <var>P</var>
                        </code>, the expression 
                  <var>P</var> is guarded by the existence of
                     an item bound to <code nobreak="false">$x</code>.</p>
                  </item>
               </ulist>
               <p>The fact that an expression is <termref def="dt-guarded"/> does not remove the obligation to report
            <termref def="dt-static-error">static errors</termref> in the expression; nor does it remove the option
            to report statically detectable <termref def="dt-type-error">type errors</termref>.</p>
               <note>
                  <p>These rules do not constrain the order of evaluation of subexpressions. For example, given an expression
                  such as <code nobreak="false">//person[@first = "Winston"][@last = "Churchill"]</code>, or equivalently
                  <code nobreak="false">//person[@first = "Winston" and @last = "Churchill"]</code>, an implementation might use an index on the value of
                  <code nobreak="false">@last</code> 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: 
                  <code nobreak="false">//person[string-length(@first) + string-length(@last) = 16][@first = "Winston"][@last = "Churchill"]</code>.
                  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.</p>
               </note>
               <note>
                  <p>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
                  <code nobreak="false">("A", 3)[. instance of xs:integer][. eq 3]</code> will not raise an error caused by the comparison
                  <code nobreak="false">("A" eq 3)</code>, but they
                  do not guarantee the converse: the expression <code nobreak="false">("A", 3)[. eq 3][. instance of xs:integer]</code>
                  may or may not raise a dynamic error.</p>
               </note>
               <note>
                  <p>The rules in this section do not disallow all expression rewrites that might result in dynamic
                  errors. For example, rewriting <code nobreak="false">($x - $y + $z)</code> as <code nobreak="false">($x + $z - $y)</code> is permitted
               even though it might result in an arithmetic overflow.</p>
               </note>
               <note>
                  <p>Some implementations allow calls on external functions that have side-effects. The semantics of
               such function calls are entirely <termref def="dt-implementation-defined"/>. Processors <rfc2119>may</rfc2119>
               choose to reference the rules for <termref def="dt-guarded"/> expressions when defining the behavior
               of such function calls, but this is outside the scope of the language specification.</p>
               </note>
            </div3>
            <div3 id="id-implausible-expressions" diff="add" at="Issue602">
               <head>Implausible Expressions</head>
               <changes>
                  <change issue="602" PR="603" date="2023-07-25">
                  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 <code nobreak="false">@price/@value</code>, even though dynamic evaluation
                  is defined to return the empty sequence rather than an error.
               </change>
               </changes>
               <p>
                  <termdef id="dt-implausible" term="implausible">Certain expressions, while not
            erroneous, are classified as being <term>implausible</term>,
            because they achieve no useful effect.</termdef>
               </p>
               <p>An example of an implausible expression is <code nobreak="false">@code/text()</code>. This expression
            will always evaluate to the 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 the empty sequence, there would be easier ways to write it.</p>
               <p>Where an expression is classified (by rules in this specification) as being
            <termref def="dt-implausible"/>, a processor <rfc2119>may</rfc2119> (but is
            not <rfc2119>required</rfc2119> to) raise a static error.</p>
               <p>For reasons of backwards compatibility and interoperability, and to facilitate
            automatic generation of XPath 4.0 code, a processor <rfc2119>must</rfc2119> 
            provide a mode of operation in which <termref def="dt-implausible"/>
            expressions are not treated as static errors, but are evaluated
            with the defined semantics for the expression.</p>
               <p>Some other examples of implausible expressions include:</p>
               <ulist>
                  <item>
                     <p>
                        <code nobreak="false">round(tokenize($input))</code>. The result of <function>fn:tokenize</function>
               is a sequence of strings (<code nobreak="false">xs:string*</code>), while the required type for the
               first argument of <function>fn:round</function> is optional numeric (<code nobreak="false">xs:numeric?</code>).
               The expression can succeed only in the exceptional case where the result of <function>fn:tokenize</function>
               is the empty sequence, in which case the result of <function>fn:round</function> will also be
               the empty sequence; it is therefore highly likely that the expression was written in error.</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">parse-csv($input)?column-names</code>. The signature of the <code nobreak="false">parse-csv</code>
               function declares its return type as <code nobreak="false">record(columns, rows)</code>. There is no field in this
               record named <code nobreak="false">column-names</code>, and therefore the lookup expression will always
               return the empty sequence. Again, there is no good reason that a user would write this,
               so it is likely that it was written in error.</p>
                  </item>
               </ulist>
               <note>
                  <p>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.</p>
               </note>
               <note>
                  <p>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.</p>
               </note>
            </div3>
         </div2>
         <div2 id="id-important-concepts">
            <head>Concepts</head>
            <p>This section explains some concepts that are important to the processing of XPath 4.0 expressions.</p>
            <div3 id="id-document-order">
               <head>Document Order</head>
               <p>An ordering called <term>document order</term> is defined among all the 
               nodes accessible during processing of a given 
               <phrase role="xpath">expression</phrase>, which may consist of one or more <term>trees</term> (documents or fragments).</p>
               <p>Document order applies both to <termref def="dt-XNode">XNodes</termref> (typically
               corresponding to nodes in an XML document, and generally referred to simply as <term>nodes</term>),
               and also to <termref def="dt-JNode">JNodes</termref>, often corresponding to the contents
               of a JSON source text. These are known collectively as 
               <termref def="dt-GNode">GNodes</termref> (for "generalized node").</p>
               <p>Document order is defined in <xspecref spec="DM40" ref="document-order"/>, and its definition is repeated here for convenience. 

Document order is a total ordering, although the relative order of some nodes is <termref def="dt-implementation-dependent">implementation-dependent</termref>.  

<termdef term="document order" id="dt-document-order">Informally, <term>document order</term> is the order in which nodes appear in the XML serialization of a document.</termdef>
                  <termdef term="stable" id="stable">Document order is <term>stable</term>, which means that the relative order of two nodes will not change during the processing of a given 
                  <phrase role="xpath">expression</phrase>, even if this order is <termref def="dt-implementation-dependent">implementation-dependent</termref>.</termdef>
                  <termdef term="reverse document order" id="dt-reverse-document-order">The node ordering that is the reverse of document order is called <term>reverse document order</term>.</termdef>
               </p>
               <p>Within an <xtermref spec="DM40" ref="dt-XTree"/>,
               (that is, a tree consisting of XNodes), document order satisfies the following constraints:</p>
               <olist>
                  <item>
                     <p>The root node precedes all other nodes.</p>
                  </item>
                  <item>
                     <p>A parent node precedes its children (and therefore its descendants).</p>
                  </item>
                  <item>
                     <p>The children of a node <var>N</var> precede the following siblings of <var>N</var>.</p>
                  </item>
                  <item role="xpath">
                     <p>Namespace nodes immediately follow the element node with
which they are associated. The relative order of namespace nodes is
stable but <termref def="dt-implementation-dependent">implementation-dependent</termref>.</p>
                  </item>
                  <item>
                     <p>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 <termref def="dt-implementation-dependent">implementation-dependent</termref>.</p>
                  </item>
                  <item>
                     <p>The relative order of siblings is the order in which they occur
in the <code nobreak="false">children</code> property of their parent node.</p>
                  </item>
               </olist>
               <p>Similarly, within an <xtermref spec="DM40" ref="dt-JTree"/>,
               (that is, a tree consisting of JNodes), document order satisfies the following constraints:</p>
               <olist>
                  <item>
                     <p>The root JNode precedes all other JNodes.</p>
                  </item>
                  <item>
                     <p>A parent JNode precedes its children (and therefore its descendants).</p>
                  </item>
                  <item>
                     <p>The children of a JNode <var>N</var> precede the following siblings of <var>N</var>.</p>
                  </item>
                  <item>
                     <p>The children of a JNode that wraps an array follow the ordering of the members of the array.</p>
                  </item>
                  <item>
                     <p>The children of a JNode that wraps a map follow the ordering of the entries in the map.</p>
                  </item>
               </olist>
               <p>The relative order of nodes in distinct trees is stable but
<termref def="dt-implementation-dependent">implementation-dependent</termref>,
subject to the following constraint: If any node in a given tree <var>T1</var> is before
any node in a different tree <var>T2</var>, then all nodes in tree <var>T1</var> are before all nodes in
tree <var>T2</var>.</p>
            </div3>
            <div3 id="id-typed-value">
               <head>Typed Value and String Value</head>
               <p>Every node (that is, every <xtermref spec="DM40" ref="dt-XNode"/>)
               has a <term>typed value</term> and a <term>string value</term>, except for nodes whose value is <xtermref spec="DM40" ref="dt-absent"/>.
               
               <termdef term="typed value" id="dt-typed-value">The <term>typed
                     value</term> of a node is a sequence of atomic items and can be
                  extracted by applying the <function>data</function> function to the
                  node.</termdef>
                  <termdef id="dt-string-value" term="string value">The
                  <term>string value</term> of a node is a string and can be extracted
                  by applying the <function>string</function>
                  function to the node.</termdef>
               </p>
               <p>An implementation may store both the <termref def="dt-typed-value">typed value</termref> and the <termref def="dt-string-value">string value</termref> of a node, or it may store only one of these and derive the other as needed.
               The string value of a node must be a valid lexical representation of the typed value of the node,
               but the node is not required to preserve the string representation from the original source document.
               For example, if the typed value of a node is the <code nobreak="false">xs:integer</code> value <code nobreak="false">30</code>,
               its string value might be <code nobreak="false">"30"</code> or <code nobreak="false">"0030"</code>.</p>
               <p role="xpath">The <termref def="dt-typed-value">typed value</termref>, <termref def="dt-string-value">string value</termref>, and <termref def="dt-type-annotation">type annotation</termref> of a node are closely related.  If the node was created by mapping from an Infoset or PSVI, the relationships among these properties are defined by rules in <xspecref spec="DM40" ref="types"/>.</p>
               <p>The relationship between <termref def="dt-typed-value">typed value</termref> and
               <termref def="dt-string-value">string value</termref> for various kinds of nodes is summarized and illustrated
               by examples below.</p>
               <olist>
                  <item>
                     <p>For text and document nodes, the typed value of the node is the same as its
                     string value, as an instance of  the type <code nobreak="false">xs:untypedAtomic</code>. The
                     string value of a document node is formed by concatenating the string
                     values of all its descendant text nodes, in <termref def="dt-document-order">document
                        order</termref>.</p>
                  </item>
                  <item>
                     <p>The typed value of a comment<phrase role="xpath">, namespace,</phrase> or processing instruction node is the same as its string value. It is an instance of the type <code nobreak="false">xs:string</code>.</p>
                  </item>
                  <item>
                     <p>The typed value of an attribute node with
                     the <termref def="dt-type-annotation">type annotation</termref>
                        <code nobreak="false">xs:anySimpleType</code> or <code nobreak="false">xs:untypedAtomic</code> is the same as its
                     string value, as an instance of <code nobreak="false">xs:untypedAtomic</code>. The
                     typed value of an attribute node with any other type annotation is
                     derived from its string value and type annotation using the lexical-to-value-space mapping defined in <bibref ref="XMLSchema10"/> or <bibref ref="XMLSchema11"/> Part 2 for
                     the relevant type.</p>
                     <p>Example: A1 is an attribute
                     having string value <code nobreak="false">"3.14E-2"</code> and type annotation
                     <code nobreak="false">xs:double</code>.  The typed value of A1 is the
                     <code nobreak="false">xs:double</code> value whose lexical representation is
                     <code nobreak="false">3.14E-2</code>. </p>
                     <p>Example: A2 is an attribute with type
                     annotation <code nobreak="false">xs:IDREFS</code>, which is a list datatype whose item type is the atomic datatype <code nobreak="false">xs:IDREF</code>. Its string value is
                     <code nobreak="false">"bar baz faz"</code>. The typed value of A2 is a sequence of
                     three atomic items (<code nobreak="false">"bar"</code>, <code nobreak="false">"baz"</code>",
                     <code nobreak="false">"faz"</code>"), each of type <code nobreak="false">xs:IDREF</code>. The typed
                     value of a node is never treated as an instance of a named list
                     type. Instead, if the type annotation of a node is a list type (such
                     as <code nobreak="false">xs:IDREFS</code>), its typed value is treated as a sequence
                     of the <termref def="dt-generalized-atomic-type">generalized atomic type</termref> from which it is derived (such as
                     <code nobreak="false">xs:IDREF</code>).</p>
                  </item>
                  <item>
                     <p>For an element node, the
                     relationship between typed value and string value depends on the
                     node’s <termref def="dt-type-annotation">type annotation</termref>, as follows:</p>
                     <olist>
                        <item>
                           <p>If the type annotation is <code nobreak="false">xs:untyped</code> or <code nobreak="false">xs:anySimpleType</code> or
                           denotes a complex type with mixed content (including <code nobreak="false">xs:anyType</code>), then the typed value of the
                           node is equal to its string value, as an instance of
                           <code nobreak="false">xs:untypedAtomic</code>.  However, if the <code nobreak="false">nilled</code>
                           property of the node is <code nobreak="false">true</code>, then its typed value is the empty sequence.</p>
                           <p>Example: E1 is an element node
                           having type annotation <code nobreak="false">xs:untyped</code> and string value
                           <code nobreak="false">"1999-05-31"</code>. The typed value of E1 is
                           <code nobreak="false">"1999-05-31"</code>, as an instance of
                           <code nobreak="false">xs:untypedAtomic</code>.</p>
                           <p>Example: E2 is an element node
                           with the type annotation <code nobreak="false">formula</code>, which is a complex type
                           with mixed content. The content of E2 consists of the character
                           <code nobreak="false">H</code>, a child element named <code nobreak="false">subscript</code> with
                           string value <code nobreak="false">"2"</code>, and the character <code nobreak="false">O</code>. The
                           typed value of E2 is <code nobreak="false">"H2O"</code> as an instance of
                           <code nobreak="false">xs:untypedAtomic</code>.</p>
                        </item>
                        <item>
                           <p>If the type
                           annotation denotes a simple type or a complex type with simple
                           content, then the typed value of the node is derived from its string
                           value and its type annotation in a way that is consistent with schema
                           validation. However, if the <code nobreak="false">nilled</code>
                           property of the node is <code nobreak="false">true</code>, then its typed value is the empty sequence.</p>
                           <p>Example: E3 is an element node with the type
                           annotation <code nobreak="false">cost</code>, which is a complex type that has several
                           attributes and a simple content type of <code nobreak="false">xs:decimal</code>. The
                           string value of E3 is <code nobreak="false">"74.95"</code>. The typed value of E3 is
                           <code nobreak="false">74.95</code>, as an instance of
                           <code nobreak="false">xs:decimal</code>.</p>
                           <p>Example: E4 is an element node with the
                           type annotation <code nobreak="false">hatsizelist</code>, which is a simple type
                           derived from the <termref def="dt-atomic-type"/>
                              <code nobreak="false">hatsize</code>, which in turn is
                           derived from <code nobreak="false">xs:integer</code>. The string value of E4 is
                           <code nobreak="false">"7 8 9"</code>. The typed value of E4 is a sequence of three
                           values (<code nobreak="false">7</code>, <code nobreak="false">8</code>, <code nobreak="false">9</code>), each of type
                           <code nobreak="false">hatsize</code>.</p>
                           <p>Example: E5 is an element node with the type annotation <code nobreak="false">my:integer-or-string</code>
                           which is a union type with member types <code nobreak="false">xs:integer</code> and <code nobreak="false">xs:string</code>.
                           The string value of E5 is <code nobreak="false">"47"</code>. The typed value of E5 is <code nobreak="false">47</code> as a
                           <code nobreak="false">xs:integer</code>, since <code nobreak="false">xs:integer</code> is the member type that validated the
                           content of E5. In general, when the type annotation of a node is a union type,
                           the typed value of the node will be an instance of one of the member types of the union.</p>
                           <note>
                              <p>If an implementation stores only the string value of a node, and the type annotation of the node is a union type, the implementation must be able to deliver the typed value of the node as an instance of the appropriate member type.</p>
                           </note>
                        </item>
                        <item>
                           <p>If the type annotation
                           denotes a complex type with empty content, then the typed value of the
                           node is the empty sequence and its string value is the zero-length string.</p>
                        </item>
                        <item>
                           <p>If the type annotation
                           denotes a complex type with element-only content, then the typed value
                           of the node is <xtermref spec="DM40" ref="dt-absent"/>. The <function>fn:data</function> function raises a
                           <termref def="dt-type-error">type error</termref>
                              <xerrorref spec="FO40" class="TY" code="0012"/> when applied to such a node. The string value of such a node is equal to the concatenated string values of all its text node descendants, in document order.</p>
                           <p>Example: E6 is an
                           element node with the type annotation <code nobreak="false">weather</code>, which is a
                           complex type whose content type specifies
                           <code nobreak="false">element-only</code>. E6 has two child elements named
                           <code nobreak="false">temperature</code> and <code nobreak="false">precipitation</code>. The typed
                           value of E6 is <xtermref spec="DM40" ref="dt-absent"/>, and the <function>fn:data</function> function
                           applied to E6 raises an error.
                        </p>
                        </item>
                     </olist>
                  </item>
               </olist>
            </div3>
            <div3 id="id-atomization">
               <head>Atomization</head>
               <p>The semantics of some
XPath 4.0 operators depend on a process called <termref def="dt-atomization">atomization</termref>. Atomization is
applied to a value when the value is used in a context in which a
sequence of atomic items is required. The result of atomization is
either a sequence of atomic items or a <termref def="dt-type-error">type error</termref>
                  <xerrorref spec="FO40" class="TY" code="0012"/>.  <termdef id="dt-atomization" term="atomization">
                     <term>Atomization</term> of a sequence
is defined as the result of invoking the <function>fn:data</function> function, as defined in <xspecref spec="FO40" ref="func-data"/>.</termdef>
               </p>
               <p> The semantics of
<function>fn:data</function> are repeated here for convenience. The result of
<function>fn:data</function> is the sequence of atomic items produced by
applying the following rules to each item in the input
sequence:</p>
               <ulist>
                  <item>
                     <p>If the item is an atomic item, it is
returned.</p>
                  </item>
                  <item>
                     <p>If the item is a node (specifically, an <termref def="dt-XNode"/>),
its <termref def="dt-typed-value">typed value</termref> is returned (a <termref def="dt-type-error">type error</termref>
                        <xerrorref spec="FO40" class="TY" code="0012"/> is raised if the node has no typed value.)</p>
                  </item>
                  <item>
                     <p>If the item is a <xtermref spec="DM40" ref="dt-JNode"/>,
                  its <term>·jvalue·</term> property is atomized and the result is returned.</p>
                  </item>
                  <item>
                     <p>If the item is a <termref def="dt-function-item">function item</termref> (other than an array) or map a <termref def="dt-type-error">type error</termref>
                        <xerrorref spec="FO40" class="TY" code="0013"/> is raised.</p>
                  </item>
                  <item>
                     <p>If the item is an array <code nobreak="false">$a</code>, atomization is defined as <code nobreak="false">$a?* ! fn:data(.)</code>, which is equivalent to atomizing the members of the array.</p>
                     <note>
                        <p>This definition recursively atomizes members that are arrays. Hence, the result of atomizing the array <code nobreak="false">[ [ 1, 2, 3 ], [ 4, 5, 6 ] ]</code> is the sequence <code nobreak="false">(1, 2, 3, 4, 5, 6)</code>.</p>
                     </note>
                  </item>
               </ulist>
               <p>Atomization is used in
processing many expressions that are designed to operate on atomic items, including: </p>
               <ulist>
                  <item>
                     <p>Arithmetic expressions</p>
                  </item>
                  <item>
                     <p>Comparison expressions</p>
                  </item>
                  <item>
                     <p>Function calls and returns</p>
                  </item>
                  <item>
                     <p>Cast expressions</p>
                  </item>
               </ulist>
               <p>Atomization plays an important role in the <termref def="dt-coercion-rules"/> used
            when converting a supplied argument in a function call to the type declared
            in the function signature.</p>
            </div3>
            <div3 id="id-ebv">
               <head>Effective Boolean Value</head>
               <p>Under certain circumstances (some of which are listed below), it is necessary to find
the <termref def="dt-ebv">effective boolean value</termref> of a
value. <termdef id="dt-ebv" term="effective boolean value">The
<term>effective boolean value</term> of a value is defined as the result
of applying the <function>fn:boolean</function> function to the value.</termdef>
               </p>
               <p>The dynamic semantics of <function>fn:boolean</function> are repeated here for convenience:</p>
               <olist>
                  <item>
                     <p>If its operand is the empty sequence, <function>fn:boolean</function> returns <code nobreak="false">false</code>.</p>
                  </item>
                  <item>
                     <p>If its operand is a sequence whose first item is a 
                     <termref def="dt-GNode"/>, <function>fn:boolean</function> returns 
                     <code nobreak="false">true</code>.</p>
                  </item>
                  <item>
                     <p>If its operand is a <termref def="dt-singleton"/> value of 
                     type <code nobreak="false">xs:boolean</code> or derived from <code nobreak="false">xs:boolean</code>, 
                     <function>fn:boolean</function> returns the value of its operand unchanged.</p>
                  </item>
                  <item>
                     <p>If its operand is a <termref def="dt-singleton"/> value of 
                     type <code nobreak="false">xs:string</code>, <code nobreak="false">xs:anyURI</code>, 
                     <code nobreak="false">xs:untypedAtomic</code>, or a type derived from one of these,
                     <function>fn:boolean</function> returns <code nobreak="false">false</code> 
                     if the operand value has zero length; otherwise it returns <code nobreak="false">true</code>.</p>
                  </item>
                  <item>
                     <p>If its operand is a <termref def="dt-singleton"/> value of 
                     any <termref def="dt-numeric"/> type or derived from a numeric
                     type, <function>fn:boolean</function> returns <code nobreak="false">false</code> 
                     if the operand value is <code nobreak="false">NaN</code> or is numerically 
                     equal to zero; otherwise it returns <code nobreak="false">true</code>.</p>
                  </item>
                  <item>
                     <p>In all other cases, <function>fn:boolean</function> raises a type error <xerrorref spec="FO40" class="RG" code="0006"/>.</p>
                     <note>
                        <p>For instance, <function>fn:boolean</function> raises a type error if the operand is a function, a map, or an array.</p>
                     </note>
                  </item>
               </olist>
               <p>The <termref def="dt-ebv">effective boolean value</termref> of a sequence is computed implicitly during  processing of the following types of expressions: </p>
               <ulist>
                  <item>
                     <p>Logical expressions (<code nobreak="false">and</code>, <code nobreak="false">or</code>)</p>
                  </item>
                  <item>
                     <p>The <function>fn:not</function> function</p>
                  </item>
                  <item>
                     <p>Certain types of <termref def="dt-predicate">predicates</termref>, such as <code nobreak="false">a[b]</code>
                     </p>
                  </item>
                  <item>
                     <p>Conditional expressions (<code nobreak="false">if</code>)</p>
                  </item>
                  <item>
                     <p>Quantified expressions (<code nobreak="false">some</code>, <code nobreak="false">every</code>)</p>
                  </item>
                  <item role="xpath">
                     <p>General comparisons, in <termref def="dt-xpath-compat-mode">XPath 1.0
		compatibility mode</termref>.</p>
                  </item>
               </ulist>
               <note>
                  <p>The definition of <termref def="dt-ebv">effective boolean
  value</termref> is <emph>not</emph> used when casting a value to the
  type <code nobreak="false">xs:boolean</code>, for example in a <code nobreak="false">cast</code>
  expression. It also plays no role in the <termref def="dt-coercion-rules"/>
  used when passing a value to a function whose signature declares a
  parameter of type <code nobreak="false">xs:boolean</code>.</p>
               </note>
            </div3>
            <div3 id="id-uri-literals">
               <head>URI Literals</head>
               <p>XPath 4.0 requires a statically known, valid URI in a <nt def="prod-xpath40-BracedURILiteral">BracedURILiteral<!--$spec = xpath40--></nt>. 

      An implementation may raise a <termref def="dt-static-error">static error</termref>
                  <errorref class="ST" code="0046"/> if the value of  a Braced URI Literal is of nonzero length
      and is neither an
      absolute URI nor a relative URI.</p>
               <note>
                  <p>The <code nobreak="false">xs:anyURI</code>
      type is designed to anticipate the introduction of
      Internationalized Resource Identifiers (IRIs) as defined in
      <bibref ref="RFC3987"/>.</p>
               </note>
               <p>Whitespace is normalized using the whitespace normalization rules
      of <function>fn:normalize-space</function>. If the result of whitespace
      normalization contains only whitespace, the corresponding URI
      consists of the empty string.  
            </p>
               <p>A Braced URI Literal or URI Literal is not
      subjected to percent-encoding
      or decoding as defined in <bibref ref="RFC3986"/>.</p>
            </div3>
            <div3 id="id-constants">
               <head>Constants</head>
               <p>Some grammatical contexts allow a <nt def="doc-xpath40-Constant">Constant<!--$spec = xpath40--></nt> to appear.
            A constant may be a string or numeric literal, but it also allows negative numbers
            and booleans.</p>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-Constant">
                     <lhs>Constant</lhs>
                     <rhs>
                        <nt def="doc-xpath40-StringLiteral">StringLiteral<!--$idref_lang_part = xpath40- --></nt>  |  ("-"?  <nt def="prod-xpath40-NumericLiteral">NumericLiteral<!--$idref_lang_part = xpath40- --></nt>)  |  <nt def="prod-xpath40-QNameLiteral">QNameLiteral<!--$idref_lang_part = xpath40- --></nt>  |  ("true"  "("  ")")  |  ("false"  "("  ")")</rhs>
                  </prod>

                  <prod id="doc-xpath40-Constant-StringLiteral">
                     <lhs>StringLiteral</lhs>
                     <rhs>
                        <nt def="prod-xpath40-AposStringLiteral">AposStringLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-QuotStringLiteral">QuotStringLiteral<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="doc-xpath40-Constant-NumericLiteral">
                     <lhs>NumericLiteral</lhs>
                     <rhs>
                        <nt def="prod-xpath40-IntegerLiteral">IntegerLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-HexIntegerLiteral">HexIntegerLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-BinaryIntegerLiteral">BinaryIntegerLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-DecimalLiteral">DecimalLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-DoubleLiteral">DoubleLiteral<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-Constant-QNameLiteral">
                     <lhs>QNameLiteral</lhs>
                     <rhs>"#"  <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>
               </scrap>
               <p>A constant may take any of the following forms:</p>
               <ulist diff="chg" at="issue637">
                  <item>
                     <p>A string literal, for example <code nobreak="false">"Paris"</code> or <code nobreak="false">'London'</code>, denoting
                 a value of type <code nobreak="false">xs:string</code>.</p>
                  </item>
                  <item>
                     <p>A numeric literal, for example <code nobreak="false">0</code>, <code nobreak="false">0.1</code>, <code nobreak="false">0x7FFF</code>,
                   or <code nobreak="false">1e-6</code>,
                   denoting a value of type <code nobreak="false">xs:decimal</code>, <code nobreak="false">xs:integer</code>, 
                   or <code nobreak="false">xs:double</code>. The literal may be preceded by a minus sign to represent a negative
                   number.</p>
                  </item>
                  <item>
                     <p>One of the constructs <code nobreak="false">true()</code> or <code nobreak="false">false()</code>, denoting
                 the <code nobreak="false">xs:boolean</code> values <code nobreak="false">true</code> and <code nobreak="false">false</code> respectively.</p>
                     <note diff="add" at="issue637">
                        <p>The constructs <code nobreak="false">true()</code> and <code nobreak="false">false()</code> must be written as
                  prescribed by the grammar. No namespace prefix is allowed. Although the values resemble calls to
                  functions in the default function namespace, they are unaffected by the namespace
                  context.</p>
                     </note>
                  </item>
                  <item>
                     <p>A QName literal, for example <code nobreak="false">#div</code> or <code nobreak="false">#xml:space</code>, denoting
                 a value of type <code nobreak="false">xs:QName</code>.</p>
                  </item>
               </ulist>
            </div3>
            <div3 id="id-resolve-relative-uri">
               <head>Resolving a Relative URI Reference</head>
               <p>
                  <termdef id="dt-resolve-relative-uri" term="resolve">To
      <term>resolve a relative URI</term>
                     <code nobreak="false">$rel</code> against a
      base URI <code nobreak="false">$base</code> is to expand it to an absolute URI,
      as if by calling the function <code nobreak="false">fn:resolve-uri($rel,
      $base)</code>.</termdef> During static analysis, the base URI is
      the Static Base URI. During dynamic evaluation, the base URI
      used to resolve a relative URI reference depends on the semantics of the
      expression.</p>
               <p>Any process that attempts to <termref def="dt-resolve-relative-uri">resolve a URI</termref> against a
      base URI, or to dereference the URI, may apply percent-encoding
      or decoding as defined in the relevant RFCs.</p>
            </div3>
         </div2>
      </div1>
      <div1 id="id-types">
         <head>Types</head>
         <p>As noted in <specref ref="id-values"/>, every value in XPath 4.0 is regarded
      as a <termref def="dt-sequence"/> of zero, one, or more <termref def="dt-item">items</termref>.
      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.</p>
         <p>The type system of XPath 4.0 is related to the type system of
		<bibref ref="XMLSchema10"/> or <bibref ref="XMLSchema11"/> in two ways:</p>
         <ulist>
            <item>
               <p>atomic items in XPath 4.0 (which are one kind of <termref def="dt-item"/>)
               have <termref def="dt-atomic-type">atomic types</termref> such as <code nobreak="false">xs:string</code>,
               <code nobreak="false">xs:boolean</code>, and <code nobreak="false">xs:integer</code>. These types are taken directly
               from their definitions in <bibref ref="XMLSchema10"/> or <bibref ref="XMLSchema11"/>.</p>
            </item>
            <item>
               <p>
                  <termref def="dt-XNode">XNodes</termref> 
               (which are another kind of <termref def="dt-item"/>) have a property
            called a <termref def="dt-type-annotation"/> which determines the type of their content.
            The type annotation is a <termref def="dt-schema-type"/>. The type annotation of a node
            must not be confused with the item type of the node. For example, an element 
            <code nobreak="false">&lt;age&gt;23&lt;/age&gt;</code> might have been validated against a schema
               that defines this element as having <code nobreak="false">xs:integer</code> content. If this
               is the case, the <termref def="dt-type-annotation"/> of the node will be
               <code nobreak="false">xs:integer</code>, and in the XPath 4.0 type system, the node will
               match the <termref def="dt-item-type"/>
                  <code nobreak="false">element(age, xs:integer)</code>.
            </p>
            </item>
         </ulist>
         <p>This chapter of the specification starts by defining 
            <termref def="dt-sequence-type">sequence types</termref> and 
         <termref def="dt-item-type">item types</termref>, which describe the range of
            <termref def="dt-value">values</termref> that can be bound to variables, used in 
            expressions, or passed to functions. It then describes how these
            relate to <termref def="dt-schema-type">schema types</termref>,
            that is, the simple and complex types defined in an XSD schema.</p>
         <note>
            <p>In many situations the terms <term>item type</term> and 
         <term>sequence type</term> are used interchangeably to refer either to the type itself,
         or to the syntactic construct that designates the type: so in the expression
         <code nobreak="false">$x instance of xs:string*</code>, the construct <code nobreak="false">xs:string*</code>
         uses the <nt def="doc-xpath40-SequenceType">SequenceType<!--$spec = xpath40--></nt> syntax to designate a
         <termref def="dt-sequence-type"/> whose instances are sequences of strings.
         When more precision is required, the specification is careful to use the terms
         <termref def="dt-item-type"/> and <termref def="dt-sequence-type"/> to
         refer to the actual types, while using the production names <nt def="doc-xpath40-ItemType">ItemType<!--$spec = xpath40--></nt>
         and <nt def="doc-xpath40-SequenceType">SequenceType<!--$spec = xpath40--></nt> to refer to the syntactic
         designators of these types.</p>
         </note>
         <div2 id="id-sequencetype-syntax">
            <head>Sequence Types</head>
            <p>
               <termdef id="dt-sequence-type" term="sequence type">A <term>sequence type</term> is a type that can be expressed using the <nt def="doc-xpath40-SequenceType">SequenceType<!--$spec = xpath40--></nt>
                  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 <term>sequence types</term>.</termdef>
            </p>
            <p>Whenever it is necessary to refer to a <term>sequence type</term> 
            in an XPath 4.0 expression, the <nt def="doc-xpath40-SequenceType">SequenceType<!--$spec = xpath40--></nt> syntax is used.</p>
            <scrap headstyle="show">
               <prod id="doc-xpath40-SequenceType">
                  <lhs>SequenceType</lhs>
                  <rhs>("empty-sequence"  "("  ")")<br/>|  (<nt def="prod-xpath40-ItemType">ItemType<!--$idref_lang_part = xpath40- --></nt>
                     <nt def="prod-xpath40-OccurrenceIndicator">OccurrenceIndicator<!--$idref_lang_part = xpath40- --></nt>?)</rhs>
               </prod>

               <prod id="doc-xpath40-SequenceType-ItemType">
                  <lhs>ItemType</lhs>
                  <rhs>
                     <nt def="prod-xpath40-RegularItemType">RegularItemType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-FunctionType">FunctionType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-TypeName">TypeName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ChoiceItemType">ChoiceItemType<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-SequenceType-OccurrenceIndicator">
                  <lhs>OccurrenceIndicator</lhs>
                  <rhs>"?"  |  "*"  |  "+"</rhs>
                  <com>
                     <loc href="#parse-note-occurrence-indicators">xgc: occurrence-indicators</loc>
                  </com>
               </prod>
            </scrap>
            <p>
               <termdef id="dt-sequence-type-designator" term="sequence type designator">A
      <term>sequence type designator</term> is a syntactic construct conforming to the grammar rule
         <nt def="doc-xpath40-SequenceType">SequenceType<!--$spec = xpath40--></nt>. A sequence type designator is said
      to <term>designate</term> a <termref def="dt-sequence-type"/>.</termdef>
            </p>
            <p>With the exception of the special type
<code nobreak="false">empty-sequence()</code>, a <termref def="dt-sequence-type">sequence type</termref> consists of an
<termref def="dt-item-type"/> that constrains the type of each item in the
sequence, and a <term>cardinality</term> that constrains the number of
items in the sequence. Apart from the item type <code nobreak="false">item()</code>,
which permits any kind of item, item types divide into <term>node
types</term> (such as <code nobreak="false">element()</code>), <term>generalized atomic
types</term> (such as <code nobreak="false">xs:integer</code>) and function types
(such as <code nobreak="false">function() as item()*</code>).</p>
            <p>The cardinality of a <termref def="dt-sequence-type"/> is represented
               in the <termref def="dt-sequence-type-designator"/> syntax by
               an <nt def="prod-xpath40-OccurrenceIndicator">OccurrenceIndicator<!--$spec = xpath40--></nt>. 
               The occurrence indicators <code nobreak="false">+</code>, <code nobreak="false">*</code>, and <code nobreak="false">?</code> 
               bind to the last <nt def="doc-xpath40-ItemType">ItemType<!--$spec = xpath40--></nt> in the <nt def="doc-xpath40-SequenceType">SequenceType<!--$spec = xpath40--></nt>, as described in the <loc xmlns:xlink="http://www.w3.org/1999/xlink"
                    href="#parse-note-occurrence-indicators"
                    xlink:type="simple"
                    xlink:show="replace"
                    xlink:actuate="onRequest">occurrence-indicators</loc> constraint.</p>
            <div3 id="id-sequence-type-examples">
               <head>Examples of Sequence Types</head>
               <p>Here are some examples of <termref def="dt-sequence-type">sequence types</termref> that
		  might be used in XPath 4.0:</p>
               <ulist>
                  <item>
                     <p>
                        <code nobreak="false">xs:date</code> refers to the built-in atomic schema type named <code nobreak="false">xs:date</code>
                     </p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">attribute()?</code> refers to an optional attribute node</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">element()</code> refers to any element node</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">element(po:shipto, po:address)</code> refers to an element node that has the name <code nobreak="false">po:shipto</code> and has the type annotation <code nobreak="false">po:address</code> (or a schema type derived from <code nobreak="false">po:address</code>)</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">element(*, po:address)</code> refers to an element node of any name that has the type annotation <code nobreak="false">po:address</code> (or a type derived from <code nobreak="false">po:address</code>)</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">element(customer)</code> refers to an element node named <code nobreak="false">customer</code> with any type annotation</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">schema-element(customer)</code> refers to an element node whose name is <code nobreak="false">customer</code> (or is in the substitution group headed by <code nobreak="false">customer</code>) and whose type annotation matches the schema type declared for a <code nobreak="false">customer</code> element in the <termref def="dt-is-elems">in-scope element declarations</termref>
                     </p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">node()*</code> refers to a sequence of zero or more nodes of any kind</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">item()+</code> refers to a sequence of one or more <termref def="dt-item">items</termref>
                     </p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">function(*)</code> refers to any <termref def="dt-function-item">function item</termref>, regardless of arity or type</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">function(node()) as xs:string*</code> refers to a <termref def="dt-function-item"/> that takes a single argument whose value is a single node,
        and returns a sequence of zero or more <code nobreak="false">xs:string</code> values</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">(fn(node()) as xs:string)*</code> refers to a sequence of zero or more <termref def="dt-function-item">function items</termref>, each of which takes a single
        argument whose value is a single node, and returns as its result a single <code nobreak="false">xs:string</code> value</p>
                  </item>
               </ulist>
            </div3>
            <div3 id="id-sequencetype-matching">
               <head>Sequence Type Matching</head>
               <p diff="chg" at="B">
                  <termdef id="dt-sequencetype-matching" term="SequenceType matching">
                     <term>SequenceType matching</term> compares a value with an expected <termref def="dt-sequence-type">sequence type</termref>. </termdef> For example, an <code nobreak="false">instance of</code> expression 
               returns <code nobreak="false">true</code> if a given value matches a given <termref def="dt-sequence-type">sequence type</termref>, and <code nobreak="false">false</code> if it does not.</p>
               <p>An XPath 4.0 implementation must be able to determine relationships among the types in type annotations in an <termref def="dt-data-model-instance">XDM instance</termref> and the types in the  <termref def="dt-issd">in-scope schema definitions</termref> (ISSD). 
            </p>
               <p diff="chg" at="B">
                  <termdef term="subtype substitution" id="dt-subtype-substitution">The use of a value that has a <termref def="dt-dynamic-type"/>
                      that is a <termref def="dt-subtype"/> of the
		  expected type is known as <term>subtype substitution</term>.</termdef>
		  Subtype substitution does not change the actual type of a value. For
		  example, if an <code nobreak="false">xs:integer</code> value is used where an
		  <code nobreak="false">xs:decimal</code> value is expected, the value retains its type
		  as <code nobreak="false">xs:integer</code>.</p>
               <!--    <p>The definition of <termref def="dt-sequencetype-matching"
                  >SequenceType matching</termref> relies
		  on a pseudo-function named <code>derives-from(</code>
               <emph>AT</emph>,
		  <emph>ET</emph>
               <code>)</code>, which takes an actual simple or complex
		  schema type <emph>AT</emph> and an expected simple or complex schema
		  type <emph>ET</emph>, and either returns a boolean value or raises a
		  <termref
                  def="dt-type-error">type error</termref>
               <errorref class="TY" code="0004"/>.  This function is defined as follows:</p>

            <ulist>

               <item>
                  <p>
                     <code>derives-from(</code>
                     <emph>AT</emph>, <emph>ET</emph>
                     <code>)</code> raises a type error <errorref class="TY" code="0004"
                        /> if <emph>ET</emph> is
		    not present in the <termref def="dt-issd"
                        >in-scope schema definitions</termref> (ISSD). </p>
               </item>

               <item>
                  <p>
                     <code>derives-from(</code>
                     <emph>AT</emph>,
		    <emph>ET</emph>
                     <code>)</code> returns <code>true</code>  
		    if any of the following conditions applies:

		    <ulist> <item>
                           <p>
                              <emph>AT</emph> is <emph>ET</emph>
                           </p>
                        </item> <item>
                           <p>
                              <emph>ET</emph> is the base type of <emph>AT</emph>
                           </p>
                        </item> <item>
                           <p>
                              <emph>ET</emph> is a pure union type of which <emph>AT</emph> is a member type</p>
                        </item> <item>
                           <p>There is a type <emph>MT</emph> such that <code>derives-from(</code>
                              <emph>AT</emph>, <emph>MT</emph>
                              <code>)</code> 
		      and <code>derives-from(</code>
                              <emph>MT</emph>, <emph>ET</emph>
                              <code>)</code>
                           </p>
                        </item> </ulist>
                  </p>
               </item>

               <item>
                  <p>Otherwise, <code>derives-from(</code>
                     <emph>AT</emph>, <emph>ET</emph>
                     <code>)</code> returns <code>false</code>
                  </p>
               </item>

            </ulist>-->
               <p>The rules for <termref def="dt-sequencetype-matching">SequenceType
		  matching</termref> are given below, with examples (the examples are
		  for purposes of illustration, and do not cover all possible
		  cases).</p>
               <ulist>
                  <item>
                     <p>The <termref def="dt-sequence-type">sequence type</termref>
                        <code nobreak="false">empty-sequence()</code> matches a value that is the empty sequence.</p>
                  </item>
                  <item>
                     <p>An <nt def="doc-xpath40-ItemType">ItemType<!--$spec = xpath40--></nt> with no <nt def="prod-xpath40-OccurrenceIndicator">OccurrenceIndicator<!--$spec = xpath40--></nt> matches any value that contains exactly one item if the <nt def="doc-xpath40-ItemType">ItemType<!--$spec = xpath40--></nt> matches that item (see <specref ref="id-matching-item"/>).</p>
                  </item>
                  <item>
                     <p>An <nt def="doc-xpath40-ItemType">ItemType<!--$spec = xpath40--></nt> with an <nt def="prod-xpath40-OccurrenceIndicator">OccurrenceIndicator<!--$spec = xpath40--></nt> matches a value if the number of items in the value matches the <nt def="prod-xpath40-OccurrenceIndicator">OccurrenceIndicator<!--$spec = xpath40--></nt> and the <nt def="doc-xpath40-ItemType">ItemType<!--$spec = xpath40--></nt> matches each of the items in the value.</p>
                  </item>
               </ulist>
               <p>An <nt def="prod-xpath40-OccurrenceIndicator">OccurrenceIndicator<!--$spec = xpath40--></nt> specifies the number of items in
		    a sequence, as follows:</p>
               <ulist>
                  <item>
                     <p>
                        <code nobreak="false">?</code> matches zero or one items</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">*</code> matches zero or more items</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">+</code> matches one or more items</p>
                  </item>
               </ulist>
               <p>As a consequence of these rules, any <termref def="dt-sequence-type">sequence type</termref> whose
		    <nt def="prod-xpath40-OccurrenceIndicator">OccurrenceIndicator<!--$spec = xpath40--></nt> is <code nobreak="false">*</code> or <code nobreak="false">?</code> matches a
		    value that is the empty sequence.</p>
            </div3>
            <div3 id="id-schema-type-derivation">
               <head>Schema Type Relationships</head>
               <p>Some <termref def="dt-item-type">item types</termref> are defined in terms
            of <termref def="dt-schema-type">schema types</termref>, and the matching
            rules for such item types depend on the rules defining relationships between
            schema types in the XSD specification.</p>
               <p>
                  <termdef id="dt-derives-from" term="derives from" open="true">A 
               <termref def="dt-schema-type"/>
                     <var>S1</var> is said to <term>derive from</term>
                     <termref def="dt-schema-type"/>
                     <var>S2</var> if any of the following
               conditions is true:</termdef>
               </p>
               <ulist>
                  <item>
                     <p>
                        <var>S1</var> is the same type as <var>S2</var>.</p>
                  </item>
                  <item>
                     <p>
                        <var>S2</var> is the base type of <var>S1</var>.</p>
                  </item>
                  <item>
                     <p>
                        <var>S2</var> is a <termref def="dt-pure-union-type"/>
                     of which <var>S1</var> is a member type.</p>
                  </item>
                  <item>
                     <p>There is a <termref def="dt-schema-type"/>
                        <var>M</var> such that 
                     <var>S1</var>
                        <termref def="dt-derives-from"/>
                        <var>M</var>
                     and <var>M</var>
                        <termref def="dt-derives-from"/>
                        <var>S2</var>.</p>
                  </item>
               </ulist>
               <p role="closetermdef"/>
               <note>
                  <p>The XML Schema specification does not completely specify the circumstances
               under which <var>S1</var> and <var>S2</var> are considered to be the same
               type. For example, if both are anonymous union types with the same member types,
               but defined in different places in the schema, then schema processors have
               discretion whether to treat them as the same type.</p>
               </note>
            </div3>
         </div2>
         <div2 id="id-matching-item">
            <head>Item Types</head>
            <p diff="add" at="B">
               <termdef id="dt-item-type" term="item type">An <term>item type</term> is a type that can be expressed using the <nt def="doc-xpath40-ItemType">ItemType<!--$spec = xpath40--></nt> syntax, which forms part of the <nt def="doc-xpath40-SequenceType">SequenceType<!--$spec = xpath40--></nt>
            syntax. Item types match individual <termref def="dt-item">items</termref>.</termdef>
            </p>
            <note>
               <p>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.</p>
            </note>
            <p>In most cases, the set of items matched by an item type consists either
         exclusively of <termref def="dt-atomic-item">atomic items</termref>,
         exclusively of <termref def="dt-node">nodes</termref>, 
         or exclusively of <xtermref spec="DM40" ref="dt-function-item">function items</xtermref>.
         Exceptions include the generic types <code nobreak="false">item()</code>, which matches all items, <code nobreak="false">xs:error</code>,
         which matches no items, and <termref def="dt-choice-item-type">choice item types</termref>,
         which can match any combination of types.
      </p>
            <p>
               <termdef id="dt-item-type-designator" term="item type designator">An
         <term>item type designator</term> is a syntactic construct conforming to the grammar rule
         <nt def="doc-xpath40-ItemType">ItemType<!--$spec = xpath40--></nt>. An item type designator is said
         to <term>designate</term> an <termref def="dt-item-type"/>.</termdef>
            </p>
            <note>
               <p>Two <termref def="dt-item-type-designator">item type designators</termref> may designate the
      same item type. For example, <code nobreak="false">element()</code> and <code nobreak="false">element(*)</code> are equivalent,
      as are <code nobreak="false">attribute(A)</code> and <code nobreak="false">attribute(A, xs:anySimpleType)</code>.</p>
            </note>
            <p>
               <termref def="dt-qname">Lexical QNames</termref> appearing in an <termref def="dt-item-type-designator"/>  are expanded using the 
                  <termref def="dt-default-type-namespace-rule"/>.
      Equality of QNames is defined by the <code nobreak="false">eq</code> operator.</p>
            <scrap headstyle="show">
               <prod id="doc-xpath40-ItemType">
                  <lhs>ItemType</lhs>
                  <rhs>
                     <nt def="prod-xpath40-RegularItemType">RegularItemType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-FunctionType">FunctionType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-TypeName">TypeName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ChoiceItemType">ChoiceItemType<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-ItemType-RegularItemType">
                  <lhs>RegularItemType</lhs>
                  <rhs>
                     <nt def="prod-xpath40-AnyItemType">AnyItemType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-XNodeType">XNodeType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-GNodeType">GNodeType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-JNodeType">JNodeType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-MapType">MapType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ArrayType">ArrayType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-RecordType">RecordType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-EnumerationType">EnumerationType<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-ItemType-AnyItemType">
                  <lhs>AnyItemType</lhs>
                  <rhs>"item"  "("  ")"</rhs>
               </prod>

               <prod id="doc-xpath40-ItemType-XNodeType">
                  <lhs>XNodeType</lhs>
                  <rhs>
                     <nt def="prod-xpath40-DocumentNodeType">DocumentNodeType<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-ElementNodeType">ElementNodeType<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="doc-xpath40-AttributeNodeType">AttributeNodeType<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-SchemaElementNodeType">SchemaElementNodeType<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-SchemaAttributeNodeType">SchemaAttributeNodeType<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-ProcessingInstructionNodeType">ProcessingInstructionNodeType<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-CommentNodeType">CommentNodeType<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-TextNodeType">TextNodeType<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-NamespaceNodeType">NamespaceNodeType<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-AnyXNodeType">AnyXNodeType<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-ItemType-DocumentNodeType">
                  <lhs>DocumentNodeType</lhs>
                  <rhs>"document-node"  "("  (<nt def="prod-xpath40-ElementNodeType">ElementNodeType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-SchemaElementNodeType">SchemaElementNodeType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-NameTestUnion">NameTestUnion<!--$idref_lang_part = xpath40- --></nt>)?  ")"</rhs>
               </prod>

               <prod id="doc-xpath40-ItemType-ElementNodeType">
                  <lhs>ElementNodeType</lhs>
                  <rhs>"element"  "("  (<nt def="prod-xpath40-NameTestUnion">NameTestUnion<!--$idref_lang_part = xpath40- --></nt>  (","  <nt def="prod-xpath40-TypeName">TypeName<!--$idref_lang_part = xpath40- --></nt>  "?"?)?)?  ")"</rhs>
               </prod>

               <prod id="doc-xpath40-ItemType-SchemaElementNodeType">
                  <lhs>SchemaElementNodeType</lhs>
                  <rhs>"schema-element"  "("  <nt def="prod-xpath40-ElementName">ElementName<!--$idref_lang_part = xpath40- --></nt>  ")"</rhs>
               </prod>

               <prod id="doc-xpath40-ItemType-NameTestUnion">
                  <lhs>NameTestUnion</lhs>
                  <rhs>(<nt def="prod-xpath40-NameTest">NameTest<!--$idref_lang_part = xpath40- --></nt> ++ "|")</rhs>
               </prod>

               <prod id="doc-xpath40-ItemType-NameTest">
                  <lhs>NameTest</lhs>
                  <rhs>
                     <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-Wildcard">Wildcard<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-ItemType-AttributeNodeType">
                  <lhs>AttributeNodeType</lhs>
                  <rhs>"attribute"  "("  (<nt def="prod-xpath40-NameTestUnion">NameTestUnion<!--$idref_lang_part = xpath40- --></nt>  (","  <nt def="prod-xpath40-TypeName">TypeName<!--$idref_lang_part = xpath40- --></nt>)?)?  ")"</rhs>
               </prod>

               <prod id="doc-xpath40-ItemType-SchemaAttributeNodeType">
                  <lhs>SchemaAttributeNodeType</lhs>
                  <rhs>"schema-attribute"  "("  <nt def="prod-xpath40-AttributeName">AttributeName<!--$idref_lang_part = xpath40- --></nt>  ")"</rhs>
               </prod>

               <prod id="doc-xpath40-ItemType-ProcessingInstructionNodeType">
                  <lhs>ProcessingInstructionNodeType</lhs>
                  <rhs>"processing-instruction"  "("  (<nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="doc-xpath40-StringLiteral">StringLiteral<!--$idref_lang_part = xpath40- --></nt>)?  ")"</rhs>
               </prod>

               <prod id="doc-xpath40-ItemType-StringLiteral">
                  <lhs>StringLiteral</lhs>
                  <rhs>
                     <nt def="prod-xpath40-AposStringLiteral">AposStringLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-QuotStringLiteral">QuotStringLiteral<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
                  <com>
                     <loc href="#ws-explicit">ws: explicit</loc>
                  </com>
               </prod>

               <prod id="doc-xpath40-ItemType-CommentNodeType">
                  <lhs>CommentNodeType</lhs>
                  <rhs>"comment"  "("  ")"</rhs>
               </prod>

               <prod id="doc-xpath40-ItemType-TextNodeType">
                  <lhs>TextNodeType</lhs>
                  <rhs>"text"  "("  ")"</rhs>
               </prod>

               <prod id="doc-xpath40-ItemType-NamespaceNodeType">
                  <lhs>NamespaceNodeType</lhs>
                  <rhs>"namespace-node"  "("  ")"</rhs>
               </prod>

               <prod id="doc-xpath40-ItemType-AnyXNodeType">
                  <lhs>AnyXNodeType</lhs>
                  <rhs>"node"  "("  ")"</rhs>
               </prod>

               <prod id="doc-xpath40-ItemType-GNodeType">
                  <lhs>GNodeType</lhs>
                  <rhs>"gnode"  "("  ")"</rhs>
               </prod>

               <prod id="doc-xpath40-ItemType-JNodeType">
                  <lhs>JNodeType</lhs>
                  <rhs>"jnode"  "("  (("*"  |  <nt def="prod-xpath40-JRootSelector">JRootSelector<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-Constant">Constant<!--$idref_lang_part = xpath40- --></nt>)  (","  <nt def="prod-xpath40-SequenceType">SequenceType<!--$idref_lang_part = xpath40- --></nt>)?)?  ")"</rhs>
               </prod>

               <prod id="doc-xpath40-ItemType-MapType">
                  <lhs>MapType</lhs>
                  <rhs>
                     <nt def="prod-xpath40-AnyMapType">AnyMapType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-TypedMapType">TypedMapType<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-ItemType-ArrayType">
                  <lhs>ArrayType</lhs>
                  <rhs>
                     <nt def="prod-xpath40-AnyArrayType">AnyArrayType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-TypedArrayType">TypedArrayType<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-ItemType-RecordType">
                  <lhs>RecordType</lhs>
                  <rhs>"record"  "("  (<nt def="prod-xpath40-FieldDeclaration">FieldDeclaration<!--$idref_lang_part = xpath40- --></nt> ** ",")  ")"</rhs>
               </prod>

               <prod id="doc-xpath40-ItemType-EnumerationType">
                  <lhs>EnumerationType</lhs>
                  <rhs>"enum"  "("  (<nt def="doc-xpath40-StringLiteral">StringLiteral<!--$idref_lang_part = xpath40- --></nt> ++ ",")  ")"</rhs>
               </prod>

               <prod id="doc-xpath40-ItemType-FunctionType">
                  <lhs>FunctionType</lhs>
                  <rhs>
                     <nt def="prod-xpath40-AnyFunctionType">AnyFunctionType<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-TypedFunctionType">TypedFunctionType<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-ItemType-TypeName">
                  <lhs>TypeName</lhs>
                  <rhs>
                     <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-ItemType-EQName">
                  <lhs>EQName</lhs>
                  <rhs>
                     <nt def="prod-xpath40-QName">QName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-ItemType-ChoiceItemType">
                  <lhs>ChoiceItemType</lhs>
                  <rhs>"("  (<nt def="prod-xpath40-ItemType">ItemType<!--$idref_lang_part = xpath40- --></nt> ++ "|")  ")"</rhs>
               </prod>
            </scrap>
            <p>This section defines the syntax and semantics of different <code nobreak="false">ItemTypes</code>
               in terms of the values that they match.</p>
            <note>
               <p>For an explanation of the EBNF grammar notation (and in particular, the operators
               <code nobreak="false">++</code> and <code nobreak="false">**</code>), see <specref ref="id-grammar"/>.</p>
            </note>
            <p diff="add" at="A">An <termref def="dt-item-type-designator"/> written simply 
               as an <code nobreak="false">EQName</code>
               (that is, a <code nobreak="false">TypeName</code>) is interpreted as follows:</p>
            <olist diff="add" at="A">
               <item>
                  <p>If the name is written as a lexical QName, then it is expanded using the
               <termref def="dt-default-type-namespace-rule"/>.</p>
               </item>
               <item>
                  <p>If the expanded name matches a <termref def="dt-named-item-type"/> in the <termref def="dt-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.</p>
               </item>
               <item>
                  <p>Otherwise, it must match the name of a type in the <termref def="dt-is-types">in-scope schema types</termref>
                  in the <termref def="dt-static-context"/>: specifically, an <termref def="dt-atomic-type"/>
                  or a <termref def="dt-pure-union-type"/>.
                  See <specref ref="id-predefined-types"/> for details.
                  </p>
                  <note>
                     <p>A name in the <code nobreak="false">xs</code> namespace will always fall into this category, since the namespace
               is reserved. See <specref ref="id-namespaces-and-qnames"/>.</p>
                  </note>
               </item>
               <item>
                  <p>If the name cannot be resolved to a type, a <termref def="dt-static-error">static error</termref> 
                  is raised <errorref class="ST" code="0051"/>.</p>
               </item>
            </olist>
            <div3 id="general-item-types">
               <head>General item types</head>
               <ulist>
                  <item>
                     <p>
                        <code nobreak="false">item()</code> matches
                        any single <termref def="dt-item">item</termref>.</p>
                     <p>For example, <code nobreak="false">item()</code> matches the atomic
                        item <code nobreak="false">1</code>, the element <code nobreak="false">&lt;a/&gt;</code>, or the function <function>fn:concat#3</function>.</p>
                  </item>
                  <item>
                     <p>A <nt def="prod-xpath40-ChoiceItemType">ChoiceItemType<!--$spec = xpath40--></nt> lists a number of alternative item types in parentheses,
                        separated by <code nobreak="false">"|"</code>. An item matches a <code nobreak="false">ChoiceItemType</code>
                        it if matches any of the alternatives.</p>
                     <p>For example, <code nobreak="false">(map(*) | array(*))</code> matches any item that
                     is a map or an array.</p>
                     <note>
                        <p>If there is only one alternative, the <code nobreak="false">ChoiceItemType</code>
                         designates the same <termref def="dt-item-type"/>
                         as the <nt def="doc-xpath40-ItemType">ItemType<!--$spec = xpath40--></nt> that is in parentheses.
                         A singleton choice (that is, a parenthesized item type) is used primarily 
                         when defining nested item types in a function
                      signature. For example, a sequence of functions that each return a single boolean might be denoted
                      <code nobreak="false">(fn() as xs:boolean)*</code>. In this example the parentheses
                      are needed to indicate where the occurrence indicator belongs.</p>
                     </note>
                  </item>
               </ulist>
            </div3>
            <div3 id="id-atomic-types">
               <head>Atomic Types</head>
               <p>Atomic types in the XPath 4.0 type system correspond directly to atomic types
                  as defined in the <bibref ref="XMLSchema10"/> or <bibref ref="XMLSchema11"/>
                 type system.</p>
               <p>Atomic types are either built-in atomic types such as <code nobreak="false">xs:integer</code>,
               or user-defined atomic types imported from a schema. Atomic types are identified
               by a QName: see <specref ref="id-namespaces-and-qnames"/>.</p>
               <note>
                  <p>A schema may also include anonymous atomic types. Such types are
               not usable directly in XPath 4.0, though they may appear as the values
               of <termref def="dt-type-annotation">type annotations</termref> on nodes.</p>
               </note>
               <p>
                  <termdef id="dt-generalized-atomic-type" term="generalized atomic type">A <term>generalized atomic type</term> is an 
                        <termref def="dt-item-type"/> whose instances are all
                        atomic items. Generalized atomic types include (a) 
                        <termref def="dt-atomic-type">atomic types</termref>, either built-in
                        (for example <code nobreak="false">xs:integer</code>) or imported from a schema, 
                        (b) <termref def="dt-pure-union-type">pure union types</termref>, either built-in
                        (<code nobreak="false">xs:numeric</code> and <code nobreak="false">xs:error</code>) or imported from a schema,
                        (c) <termref def="dt-choice-item-type">choice item types</termref> if their alternatives
                        are all generalized atomic types, and 
                        (d) <termref def="dt-enumeration-type">enumeration types</termref>.
                     </termdef>.</p>
               <!-- <p>
                     <termref def="dt-atomic-type">Atomic types</termref>
                     and <termref def="dt-pure-union-type">pure union types</termref>
                     are usable both as <termref def="dt-schema-type">schema types</termref>
                     and as <termref def="dt-item-type">item types</termref>.</p>-->
               <p>A <termref def="dt-generalized-atomic-type"/> may be designated by 
                     an <nt def="doc-xpath40-ItemType">ItemType<!--$spec = xpath40--></nt> in any of the following ways:</p>
               <ulist>
                  <item>
                     <p>Using the QName of a type in the <termref def="dt-issd"/> that is an 
                        <termref def="dt-atomic-type"/>
                     or a <termref def="dt-pure-union-type"/>.</p>
                  </item>
                  <item>
                     <p>Using a QName that identifies a <termref def="dt-named-item-type"/> that resolves
                        to a <termref def="dt-generalized-atomic-type"/>.</p>
                  </item>
                  <item>
                     <p>Using a <nt def="prod-xpath40-ChoiceItemType">ChoiceItemType<!--$spec = xpath40--></nt> where every alternative
                        is itself a <termref def="dt-generalized-atomic-type"/>.</p>
                  </item>
                  <!--<item><p>Using a <nt def="LocalUnionType">LocalUnionType</nt> as described below.</p></item>-->
                  <item>
                     <p>Using an <nt def="doc-xpath40-EnumerationType">EnumerationType<!--$spec = xpath40--></nt> as described below.</p>
                  </item>
               </ulist>
               <p diff="add" at="2023-02-20">An atomic item <var>A</var> matches the 
                     <termref def="dt-generalized-atomic-type"/>
                  <var>GAT</var> 
                     if the <termref def="dt-type-annotation">type annotation</termref> of <var>A</var>
                  <termref def="dt-derives-from"/>
                  <var>GAT</var>.</p>
               <p>Example: The <nt def="doc-xpath40-ItemType">ItemType<!--$spec = xpath40--></nt>
                  <code nobreak="false">xs:decimal</code> matches any value of type
    <code nobreak="false">xs:decimal</code>.  It also matches any value of type
                        <code nobreak="false">shoesize</code>, if <code nobreak="false">shoesize</code> is an <termref def="dt-atomic-type"/>
    derived by restriction from <code nobreak="false">xs:decimal</code>.</p>
               <p>Example: Suppose <nt def="doc-xpath40-ItemType">ItemType<!--$spec = xpath40--></nt>
                  <code nobreak="false">dress-size</code> is a union type that allows
    either <code nobreak="false">xs:decimal</code> values for numeric sizes (for example: 4, 6, 10, 12),
    or one of an enumerated set of <code nobreak="false">xs:strings</code>
    (for example: <code nobreak="false">small</code>, <code nobreak="false">medium</code>, <code nobreak="false">large</code>). The <nt def="doc-xpath40-ItemType">ItemType<!--$spec = xpath40--></nt>
                  <code nobreak="false">dress-size</code> matches any of these values.</p>
               <note>
                  <p>The names of <phrase diff="chg" at="A">list</phrase>
    types such as <code nobreak="false">xs:IDREFS</code> are not accepted in this context,
    but can often be replaced by a <termref def="dt-generalized-atomic-type">generalized atomic type</termref> with an occurrence indicator, such as
    <code nobreak="false">xs:IDREF+</code>.</p>
               </note>
            </div3>
            <div3 id="id-union-types">
               <head>Union Types</head>
               <p>Union types, as defined in XSD, are a variety of simple types. The membership of
                  a union type in XSD may include list types as well as atomic types and other union types.</p>
               <p>
                  <termdef id="dt-pure-union-type" term="pure union type">A <term>pure union type</term> is a <phrase diff="chg" at="2023-02-20">
                        <term>simple type</term>
                     </phrase> 
                     that satisfies the following constraints:
                     (a) <xtermref spec="XS11-1" ref="std-variety">{variety}</xtermref> is <code nobreak="false">union</code>, 
                     (b) the <xtermref spec="XS11-1" ref="std-facets">{facets}</xtermref> property is empty, 
                     (c) no type in the transitive membership of the union type has 
                     <xtermref spec="XS11-1" ref="std-variety">{variety}</xtermref>
                     <code nobreak="false">list</code>, and 
                     (d) no type in the transitive membership of the union type is a type with 
                     <xtermref spec="XS11-1" ref="std-variety">{variety}</xtermref>
                     <code nobreak="false">union</code> having a non-empty <xtermref spec="XS11-1" ref="std-facets">{facets}</xtermref> property</termdef>.</p>
               <note>
                  <p>The definition of <termref def="dt-pure-union-type">pure union type</termref>
                     excludes union types derived by non-trivial restriction from other
                     union types, as well as union types that include list types in their
                     membership. Pure union types have the property that every
                     instance of an <termref def="dt-atomic-type"/> defined as one of the member types of the
                     union is also a valid instance of the union type.</p>
               </note>
               <note>
                  <p>The current (second) edition of XML Schema 1.0 contains an
                     error in respect of the substitutability of a union type by one of its
                     members: it fails to recognize that this is unsafe if the union is
                     derived by restriction from another union.</p>
                  <p>This problem is fixed in XSD 1.1, but the effect of the resolution
                     is that an atomic item labeled with an atomic type cannot be treated
                     as being substitutable for a union type without explicit validation.
                     This specification therefore allows union types to be used as item
                     types only if they are defined directly as the union of a number of
                     atomic types.</p>
               </note>
               <note>
                  <p>Local union types (see <specref ref="id-choice-item-types"/>) and 
                  <termref def="dt-enumeration-type">enumeration types</termref> cannot be
                  used as the target for schema validation.</p>
               </note>
               <p>
                  <termdef id="dt-numeric" term="numeric">The type <code nobreak="false">xs:numeric</code>
               is defined as a union type with member types <code nobreak="false">xs:double</code>, 
               <code nobreak="false">xs:float</code>, and <code nobreak="false">xs:decimal</code>. An item that
               is an instance of any of these types is referred to as a <term>numeric value</term>,
               and a type that is a subtype of <code nobreak="false">xs:numeric</code> is referred to
               as a <term>numeric type</term>.</termdef>
               </p>
            </div3>
            <div3 id="id-namespace-sensitive">
               <head>Namespace-sensitive Types</head>
               <p>
                  <termdef term="namespace-sensitive" id="dt-namespace-sensitive">The <term>namespace-sensitive</term>
                     types are <code nobreak="false">xs:QName</code>, <code nobreak="false">xs:NOTATION</code>, types
                     derived by restriction from <code nobreak="false">xs:QName</code> or
                     <code nobreak="false">xs:NOTATION</code>, list types that have a namespace-sensitive
                     item type, and union types with a namespace-sensitive type in their
                     transitive membership.</termdef>
               </p>
               <p>It is not possible to preserve the type of a <termref def="dt-namespace-sensitive">namespace-sensitive</termref> value without also preserving the <termref def="dt-namespace-binding"/> 
                  that defines the meaning of each namespace prefix used in the value. Therefore, XPath 4.0 defines 
                  some error conditions that occur only with <termref def="dt-namespace-sensitive">namespace-sensitive</termref> values. For instance, casting to a <termref def="dt-namespace-sensitive">namespace-sensitive</termref> type raises 
                  a <termref def="dt-type-error">type error</termref>
                  <xerrorref spec="FO40" class="NS" code="0004"/> if the namespace bindings for the result cannot be determined. </p>
            </div3>
            <div3 id="id-choice-item-types">
               <head>Choice Item Types</head>
               <changes>
                  <change issue="122" PR="1132" date="2024-04-09">
                     Choice item types (an item type allowing a set of alternative item types)
                     are introduced.
                  </change>
               </changes>
               <p>
                  <termdef id="dt-choice-item-type" term="choice item type">A 
                  <term>choice item type</term> defines an item type that is the union
               of a number of alternatives. For example the type 
               <code nobreak="false">(xs:hexBinary | xs:base64Binary)</code> defines the union of 
                  these two primitive <termref def="dt-atomic-type">atomic types</termref>, 
                  while the type <code nobreak="false">(map(*) | array(*))</code>
               matches any item that is either a map or an array.</termdef>
               </p>
               <p>An item matches a <code nobreak="false">ChoiceItemType</code> if it matches any of the 
                  alternatives listed within the parentheses.</p>
               <p>For example, the type <code nobreak="false">(xs:NCName | enum(""))</code> matches any value that is either
                  an instance of <code nobreak="false">xs:NCName</code>, or a zero-length string. This might be a suitable type for
                  a variable that holds a namespace prefix.</p>
               <p>If all the alternatives are <termref def="dt-generalized-atomic-type">generalized atomic types</termref>
                  then the <termref def="dt-choice-item-type"/> is itself a generalized atomic type,
               which means, for example, that it can be used as the target of a cast expression.</p>
               <note>
                  <p>A <termref def="dt-choice-item-type"/> in which all the alternatives are atomic
                  behaves in most respects like a schema-defined <termref def="dt-pure-union-type"/>.
                     However, because it can be defined at the point of use (for example,
                     within a function signature), it may be more convenient than defining the type in an
                     imported schema.</p>
               </note>
               <note>
                  <p>Choice item types are particularly useful in function signatures, 
                     allowing a function to take arguments
                  of a variety of types. If the choice item type is a local union type, 
                  then the semantics are identical to using a named union type, but a local union type is more
                  convenient because it does not need to be defined in a schema, and does not require a schema-aware processor.</p>
                  <p>A local union type can also be used in a cast expression: <code nobreak="false">cast @when as (xs:date | xs:dateTime)</code>
                  allows the attribute <code nobreak="false">@when</code> to be either an <code nobreak="false">xs:date</code>, or an <code nobreak="false">xs:dateTime</code>.</p>
                  <p>An <code nobreak="false">instance of</code> expression can be used to test whether a value belongs to one
                  of a number of specified types: <code nobreak="false">$x instance of (xs:string | xs:anyURI | xs:untypedAtomic)</code>
                  returns <code nobreak="false">true</code> if <code nobreak="false">$x</code> is an instance of any of these three atomic types,
                  while <code nobreak="false">$x instance of (map(*) | array(*))</code> tests whether <code nobreak="false">$x</code> is
                  a map or array.</p>
               </note>
            </div3>
            <div3 id="id-enumeration-types" diff="add" at="A">
               <head>Enumeration Types</head>
               <changes>
                  <change issue="688 2152" PR="691 2154" date="2023-10-10">Enumeration types are added as a new kind of <code nobreak="false">ItemType</code>, constraining
                     the value space of strings.</change>
               </changes>
               <p>
                  <termdef id="dt-enumeration-type" term="enumeration type">An <term>EnumerationType</term>
                  accepts a fixed set of string values.</termdef>
               </p>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-EnumerationType">
                     <lhs>EnumerationType</lhs>
                     <rhs>"enum"  "("  (<nt def="doc-xpath40-StringLiteral">StringLiteral<!--$idref_lang_part = xpath40- --></nt> ++ ",")  ")"</rhs>
                  </prod>

                  <prod id="doc-xpath40-EnumerationType-StringLiteral">
                     <lhs>StringLiteral</lhs>
                     <rhs>
                        <nt def="prod-xpath40-AposStringLiteral">AposStringLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-QuotStringLiteral">QuotStringLiteral<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>
               </scrap>
               <p>An <termref def="dt-enumeration-type"/> has a value space consisting of a set of <code nobreak="false">xs:string</code>
                  values. When matching strings against an enumeration type, strings are always compared
               using the Unicode codepoint collation.</p>
               <p>For example, if an argument of a function declares the required type 
                  as <code nobreak="false">enum("red", "green", "blue")</code>, then the string <code nobreak="false">"green"</code> is accepted,
                  while <code nobreak="false">"yellow"</code> is rejected with a type error.</p>
               <p>Technically, enumeration types are defined as follows:</p>
               <ulist>
                  <item>
                     <p>
                        <termdef id="dt-singleton-enumeration-type" term="singleton enumeration type">An 
                     enumeration type with a single enumerated value <var>E</var> (such as
                     <code nobreak="false">enum("red")</code>) matches an item <var>S</var> if and only if (a) <var>S</var>
                     is an instance of <code nobreak="false">xs:string</code>, and (b) <var>S</var> is equal
                     to <var>E</var> when compared using Unicode codepoint collation. This is referred to
                     as a <term>singleton enumeration type</term>.</termdef>
                     </p>
                     <note>
                        <p>When matching a string <var>S</var> against an enumeration type,
                     then apart from the requirement that <var>S</var> is an instance of
                     <code nobreak="false">xs:string</code>, the type annotation of <var>S</var> is immaterial.</p>
                     </note>
                  </item>
                  <item>
                     <p>A <termref def="dt-singleton-enumeration-type"/> whose enumerated value
                  is <var>E</var> is a subtype of <code nobreak="false">xs:string</code>.</p>
                  </item>
                  <item>
                     <p>Two <termref def="dt-singleton-enumeration-type">singleton enumeration types</termref> 
                     are the same type if and only
                  if they have the same (single) enumerated value, as determined using the Unicode
                  codepoint collation.</p>
                  </item>
                  <item>
                     <p>An enumeration type with multiple
                     enumerated values is a union of <termref def="dt-singleton-enumeration-type">singleton enumeration types</termref>, 
                     so <code nobreak="false">enum("red", "green", "blue")</code>
                     is equivalent to <code nobreak="false">(enum("red") | enum("green") | enum("blue"))</code>.</p>
                  </item>
                  <item>
                     <p>In consequence, an enumeration type <var>T</var> is a subtype
                  of an enumeration type <var>U</var> if the enumerated values of <var>T</var>
                  are a subset of the enumerated values of <var>U</var>: 
                     see <specref ref="id-itemtype-subtype"/>.</p>
                  </item>
               </ulist>
               <p>An enumeration type is a <termref def="dt-generalized-atomic-type"/>.</p>
               <p>It follows from these rules that the expression <code nobreak="false">"red" instance of enum("red", "green", "blue")</code>
               returns <code nobreak="false">true</code>. By contrast, <code nobreak="false">xs:untypedAtomic("red") 
                  instance of enum("red", "green", "blue")</code> returns false; but the
                  <termref def="dt-coercion-rules"/> ensure that where a variable
               or function declaration specifies an enumeration type as the required type, 
               an <code nobreak="false">xs:untypedAtomic</code> or <code nobreak="false">xs:anyURI</code> value equal
               to one of the enumerated values will be accepted.</p>
               <note>
                  <p>Some consequences of these rules may not be immediately apparent.</p>
                  <p>Suppose that an XQuery query contains the declarations:</p>
                  <eg xml:space="preserve">
declare type my:color := enum("red", "green", "orange");
declare type my:fruit := enum("apple", "orange", "banana");
declare variable $orange-color as my:color := "orange";
declare variable $orange-fruit as my:fruit := "orange";
                  </eg>
                  <p>The same applies with the equivalent XSLT syntax:</p>
                  <eg xml:space="preserve">
&lt;xsl:item-type name="my:color" as="enum('red', 'green', 'orange')"/&gt;
&lt;xsl:item-type name="my:fruit" as="enum('apple', 'orange', 'banana')"/&gt;
&lt;xsl:variable name="orange-color" as="my:color" select="'orange'"/&gt;
&lt;xsl:variable name="orange-fruit" as="my:fruit" select="'orange'"/&gt;
                     </eg>
                  <p>Now, the value of <code nobreak="false">$orange-color</code> is an atomic item whose datum
                  is the string <code nobreak="false">"orange"</code>, and whose type annotation is <code nobreak="false">xs:string</code>. 
                     Similarly, the value of 
                     <code nobreak="false">$orange-fruit</code> is an atomic item whose datum
                  is the string <code nobreak="false">"orange"</code>, and whose type annotation is <code nobreak="false">xs:string</code>. That is, the values of the two
                     variables are indistinguishable and interchangeable in every way. In particular,
                  both values are instances of <code nobreak="false">my:color</code>,
                  and both are instances of <code nobreak="false">my:fruit</code>.</p>
                  <p>This way of handling enumeration values has advantages and disadvantages.
                  On the positive side, it means that enumeration subsets and supersets work
                  cleanly: a value that is an instance of <code nobreak="false">enum("red", "green", "orange")</code>
                  can be used where an instance of <code nobreak="false">enum("red", "orange", "yellow", "green", "blue", "indigo",
                     "violet")</code> is expected. The downside is that labeling a string as an instance
                  of an enumeration type does not provide type safety: a function that expects an instance
                  of <code nobreak="false">my:color</code> can be called with any string that matches one of the required
                  colors, whether or not it has an appropriate type annotation. A function that expects a color
                  can be successfully called passing a fruit, if they happen to have the same name.</p>
                  <p>In the terminology of computer science, XDM atomic types derived by restriction
                  are <emph>nominative</emph> types, allowing two types with identical properties
                  but different names to be treated as different types with different instances. By
                  contrast, enumeration types are <emph>structural</emph> types, where membership
                  of the type is determined purely by a predicate applied to the value.</p>
                  <p>In consequence, instances of an enumeration type are not annotated as such.
                  The type annotation of such an instance may be <code nobreak="false">xs:string</code> or any type
                  derived by restriction from <code nobreak="false">xs:string</code>, but it will not be the
                  enumeration type itself, which is anonymous.</p>
               </note>
            </div3>
            <div3 id="node-types">
               <head>Node Types</head>
               <changes>
                  <change issue="107" PR="286" date="2023-01-17">
                     Element and attribute tests can include alternative names: <code nobreak="false">element(chapter|section)</code>,
                     <code nobreak="false">attribute(role|class)</code>.
                  </change>
                  <change issue="107" PR="286" date="2023-01-17">
                     The <code nobreak="false">NodeTest</code> in an <code nobreak="false">AxisStep</code> now allows alternatives: 
                     <code nobreak="false">ancestor::(section|appendix)</code>
                  </change>
                  <change issue="1593" date="2024-11-24">
                     The syntax <code nobreak="false">document-node(<var>N</var>)</code>, where <var>N</var> is a <code nobreak="false">NameTestUnion</code>,
                     is introduced as an abbreviation for <code nobreak="false">document-node(element(<var>N</var>))</code>. For example,
                     <code nobreak="false">document-node(*)</code> matches any well-formed XML document (as distinct from a document fragment).
                  </change>
               </changes>
               <p>Node types are <termref def="dt-item-type">item types</termref> whose 
                  instances are all <termref def="dt-node">nodes</termref>.</p>
               <p>The syntax for node types is also used for <termref def="dt-node-test">node tests</termref>
               within path expressions. This explains why the production rules have names such as
               <code nobreak="false">NodeTest</code> rather than <code nobreak="false">NodeType</code>.</p>
               <p>Some of the constructs described in this section include a <nt def="prod-xpath40-TypeName">TypeName<!--$spec = xpath40--></nt>. This appears 
                  as <var>T</var> in:</p>
               <ulist>
                  <item>
                     <p>
                        <code nobreak="false">element(N, T)</code>
                     </p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">attribute(N, T)</code>
                     </p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">document-node(element(N, T))</code>
                     </p>
                  </item>
               </ulist>
               <p>The type name <var>T</var> is expanded using the <termref def="dt-default-type-namespace-rule"/>. The resulting
               <termref def="dt-expanded-qname"/> must identify a type in the <termref def="dt-issd"/>. This can be any <termref def="dt-schema-type"/>: either a simple type,
               or (except in the case of attributes) a complex type. If it is a simple type then it can be an atomic, union, or
               list type. It can be a built-in type (such as <code nobreak="false">xs:integer</code>) or a user-defined type. It must however
               be the name of a type defined in a schema; it cannot be a <termref def="dt-named-item-type"/>.</p>
               <div4 id="id-simple-node-tests">
                  <head>Simple Node Types</head>
                  <ulist>
                     <item>
                        <p>
                           <code nobreak="false">node()</code>
    matches any node.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">text()</code> matches any
    text node.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">processing-instruction()</code>
    matches any processing instruction
    node.</p>
                     </item>
                     <item>
                        <p at="XQ.E27 and XP.E19">
                           <code nobreak="false">processing-instruction(</code>
                           <emph>N</emph>
                           <code nobreak="false">)</code>
    matches any processing instruction node whose PITarget is equal to <code role="parse-test" nobreak="false">fn:normalize-space(N)</code>. If the result of <code nobreak="false">fn:normalize-space(N)</code> is not in the lexical space of NCName, a type error is raised <errorref class="TY" code="0004"/>
                        </p>
                        <p>Example:
    <code role="parse-test" nobreak="false">processing-instruction(xml-stylesheet)</code> matches any
    processing instruction whose PITarget is
    <code nobreak="false">xml-stylesheet</code>.</p>
                        <p>For backward compatibility with
    XPath 1.0, the PITarget of a
    processing instruction may also be expressed as a
    string literal, as in this example:
    <code role="parse-test" nobreak="false">processing-instruction("xml-stylesheet")</code>.</p>
                        <p>If the specified PITarget is not a syntactically valid NCName, a type error is raised <errorref class="TY" code="0004"/>.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">comment()</code> matches any comment node.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">namespace-node()</code> matches any
    namespace node.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">document-node()</code> matches any document
    node.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">document-node(</code>
                           <emph>E</emph>
                           <code nobreak="false">)</code>, where <var>E</var> is an <nt def="doc-xpath40-ElementNodeType"><!--$spec = xpath40--></nt> or <nt def="doc-xpath40-SchemaElementNodeType"><!--$spec = xpath40--></nt> (see <specref ref="id-element-test"/> and <specref ref="id-schema-element-test"/>)
    matches any document node whose children comprise (in any order) zero or more
    comment and processing instruction nodes, zero text nodes, and exactly one element node,
    which itself must match <var>E</var>.</p>
                        <p>Example:
    <code role="parse-test" nobreak="false">document-node(element(book))</code> matches a document node
    containing
    exactly one element node that is matched by the <nt def="doc-xpath40-ElementNodeType"><!--$spec = xpath40--></nt>
                           <code role="parse-test" nobreak="false">element(book)</code>.</p>
                     </item>
                     <item>
                        <p>The construct <code nobreak="false">document-node(<var>NTU</var>)</code>, where
                  <var>NTU</var> is a <nt def="prod-xpath40-NameTestUnion">NameTestUnion<!--$spec = xpath40--></nt>, is
                  an abbreviation for <code nobreak="false">document-node(element(<var>NTU</var>))</code>.
                  For example, <code nobreak="false">document-node(*)</code> is an abbreviation for
                  <code nobreak="false">document-node(element(*))</code>, which matches any document node
                  corresponding to a well-formed XML document, that is, one that has
                  one element child, zero or more comment and processing instruction children,
                  and no text node children.</p>
                     </item>
                     <item>
                        <p>An <nt def="doc-xpath40-ItemType">ItemType<!--$spec = xpath40--></nt> that is an
                     <nt def="doc-xpath40-ElementNodeType"><!--$spec = xpath40--></nt>, <nt def="doc-xpath40-SchemaElementNodeType"><!--$spec = xpath40--></nt>, 
                        <nt def="doc-xpath40-AttributeNodeType"><!--$spec = xpath40--></nt>,
                     <nt def="doc-xpath40-SchemaAttributeNodeType"><!--$spec = xpath40--></nt>, or <nt def="doc-xpath40-FunctionType"><!--$spec = xpath40--></nt> 
                        matches an item as described in the following sections.
                     </p>
                     </item>
                  </ulist>
               </div4>
               <div4 id="id-element-test">
                  <head>Element Types</head>
                  <changes>
                     <change issue="107" PR="286" date="2023-01-17">
                     Element and attribute tests of the form <code nobreak="false">element(N)</code>
                     and <code nobreak="false">attribute(N)</code> now allow <code nobreak="false">N</code> to be any <code nobreak="false">NameTest</code>,
                     including a wildcard.
                  </change>
                     <change issue="23" PR="606" date="2023-01-17">
                     Element and attribute tests of the form <code nobreak="false">element(A|B)</code>
                     and <code nobreak="false">attribute(A|B)</code> are now allowed.
                  </change>
                     <change>
                     Setting the default namespace for elements and types to the special value
                     <code nobreak="false">##any</code> causes an unprefixed element name to act as a wildcard,
                     matching by local name regardless of namespace.
                  </change>
                  </changes>
                  <scrap headstyle="show">
                     <prod id="doc-xpath40-ElementNodeType">
                        <lhs>ElementNodeType</lhs>
                        <rhs>"element"  "("  (<nt def="prod-xpath40-NameTestUnion">NameTestUnion<!--$idref_lang_part = xpath40- --></nt>  (","  <nt def="prod-xpath40-TypeName">TypeName<!--$idref_lang_part = xpath40- --></nt>  "?"?)?)?  ")"</rhs>
                     </prod>

                     <prod id="doc-xpath40-ElementNodeType-NameTestUnion">
                        <lhs>NameTestUnion</lhs>
                        <rhs>(<nt def="prod-xpath40-NameTest">NameTest<!--$idref_lang_part = xpath40- --></nt> ++ "|")</rhs>
                     </prod>

                     <prod id="doc-xpath40-ElementNodeType-NameTest">
                        <lhs>NameTest</lhs>
                        <rhs>
                           <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-Wildcard">Wildcard<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-ElementNodeType-EQName">
                        <lhs>EQName</lhs>
                        <rhs>
                           <nt def="prod-xpath40-QName">QName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-ElementNodeType-Wildcard">
                        <lhs>Wildcard</lhs>
                        <rhs>"*"<br/>|  (<nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>  ":*")<br/>|  ("*:"  <nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>)<br/>|  (<nt def="prod-xpath40-BracedURILiteral">BracedURILiteral<!--$idref_lang_part = xpath40- --></nt>  "*")</rhs>
                        <com>
                           <loc href="#ws-explicit">ws: explicit</loc>
                        </com>
                     </prod>

                     <prod id="doc-xpath40-ElementNodeType-TypeName">
                        <lhs>TypeName</lhs>
                        <rhs>
                           <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>
                  </scrap>
                  <p>
    An <nt def="doc-xpath40-ElementNodeType"><!--$spec = xpath40--></nt> is used to match an
    element node by its name and/or <termref def="dt-type-annotation">type annotation</termref>.
  </p>
                  <p diff="chg" at="Issue372">An unprefixed <nt def="doc-xpath40-EQName">EQName<!--$spec = xpath40--></nt>
                  within the <code nobreak="false">NameTestUnion</code> is expanded using the
                  <termref def="dt-element-name-matching-rule"/>.
                  The name need not be present in the <termref def="dt-is-attrs">in-scope element declarations</termref>.
               </p>
                  <note>
                     <p>This means that when the 
                  <termref def="dt-default-namespace-elements-and-types"/>
               has the special value <code nobreak="false">##any</code>, an unprefixed name
               <var>N</var> is interpreted as a wildcard <code nobreak="false">*:<var>N</var>
                        </code>.</p>
                     <p>It is always possible to match no-namespace names explicitly
               by using the form <code nobreak="false">Q{}<var>N</var>
                        </code>
                     </p>
                  </note>
                  <p diff="chg" at="Issue23">An unprefixed <nt def="prod-xpath40-TypeName">TypeName<!--$spec = xpath40--></nt> is expanded using the
                  <termref def="dt-default-type-namespace-rule"/>.
                  The <nt def="prod-xpath40-TypeName">TypeName<!--$spec = xpath40--></nt> must be present in the <termref def="dt-is-types">in-scope schema types</termref>
                     <errorref class="ST" code="0008"/>
                  </p>
                  <note>
                     <p>If the <termref def="dt-default-namespace-elements-and-types"/>
                  has the special value <code nobreak="false">##any</code>, then an unprefixed type name
                  <var>T</var> is interpreted as <code nobreak="false">Q{http://www.w3.org/2001/XMLSchema}<var>T</var>
                        </code>.</p>
                  </note>
                  <note>
                     <p>
                        <termref def="dt-substitution-group">Substitution groups</termref> do not affect the semantics of <nt def="doc-xpath40-ElementNodeType"><!--$spec = xpath40--></nt>.</p>
                  </note>
                  <p diff="chg" at="Issue23">An <nt def="doc-xpath40-ElementNodeType"><!--$spec = xpath40--></nt>
                     <var>ET</var> matches an item <var>E</var> if the following conditions
                  are satisfied:</p>
                  <olist>
                     <item>
                        <p>
                           <var>E</var> is an element node.</p>
                     </item>
                     <item>
                        <p>If <var>ET</var> includes a <nt def="prod-xpath40-NameTestUnion">NameTestUnion<!--$spec = xpath40--></nt>,
                           then the name of the element node <var>E</var> matches one or more of
                           the <nt def="prod-xpath40-NameTest">NameTests<!--$spec = xpath40--></nt> in the <nt def="prod-xpath40-NameTestUnion">NameTestUnion<!--$spec = xpath40--></nt>.
                           A name <var>N</var> matches a <nt def="prod-xpath40-NameTest">NameTest<!--$spec = xpath40--></nt>
                           <var>NT</var> if one of the following
                           conditions is true:</p>
                        <olist>
                           <item>
                              <p>
                                 <var>NT</var> is <code nobreak="false">*</code>
                              </p>
                           </item>
                           <item>
                              <p>
                                 <var>NT</var> is <code nobreak="false">*:<emph>local</emph>
                                 </code> and the local part
                                 of <var>N</var> is <var>local</var>.</p>
                           </item>
                           <item>
                              <p>
                                 <var>NT</var> is <code nobreak="false">
                                    <emph>prefix</emph>:*</code> and the namespace URI
                                 of <var>N</var> matches the namespace URI bound to <var>prefix</var> in the static
                                 context.</p>
                           </item>
                           <item>
                              <p>
                                 <var>NT</var> is <code nobreak="false">
                                    <emph>BracedURILiteral</emph>*</code> and the namespace URI
                                 of <var>N</var> matches the namespace URI found in the <code nobreak="false">BracedURILiteral</code>.</p>
                           </item>
                           <item>
                              <p>
                                 <var>NT</var> is an <code nobreak="false">EQName</code> equal to <var>N</var>.</p>
                           </item>
                        </olist>
                     </item>
                     <item>
                        <p>If <var>ET</var> includes a <nt def="prod-xpath40-TypeName">TypeName<!--$spec = xpath40--></nt>
                           <var>T</var>,
                           then the <termref def="dt-type-annotation"/> of the element node <var>E</var>
                           <termref def="dt-derives-from"/>
                           <var>T</var>.</p>
                     </item>
                     <item>
                        <p>If <var>E</var> has the <code nobreak="false">nilled</code> property, then <var>ET</var>
                           either includes no <nt def="prod-xpath40-TypeName">TypeName<!--$spec = xpath40--></nt>, 
                           or includes a <nt def="prod-xpath40-TypeName">TypeName<!--$spec = xpath40--></nt> followed by the symbol <code nobreak="false">?</code>.</p>
                     </item>
                  </olist>
                  <p>Here are some examples of <nt def="doc-xpath40-ElementNodeType">ElementNodeTypes<!--$spec = xpath40--></nt>:</p>
                  <olist>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">element()</code> and

<code role="parse-test" nobreak="false">element(*)</code>  match any
single element node, regardless of its name or
type annotation.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">element(person)</code> matches any element 
                        node whose name is <code nobreak="false">person</code>,
                        (in the <termref def="dt-default-namespace-elements-and-types"/>),
                     whether or not the element has been schema-validated.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">element(person, xs:untyped)</code> matches 
                        any element node whose name is <code nobreak="false">person</code>
                        (in the <termref def="dt-default-namespace-elements-and-types"/>), provided it has
                        not been schema-validated.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">element(person, xs:anyType?)</code> matches 
                        any element node whose name is <code nobreak="false">person</code>
                        (in the <termref def="dt-default-namespace-elements-and-types"/>), whether or
                        not it has been schema-validated. This type is equivalent to
                        <code nobreak="false">element(person)</code>.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">element(person, xs:anyType)</code> matches 
                        any element node whose name is <code nobreak="false">person</code>
                        (in the <termref def="dt-default-namespace-elements-and-types"/>), whether or
                        not it has been schema-validated, provided it has not been found (during
                        schema validation) to be nilled. This type is <emph>not</emph> equivalent to
                        <code nobreak="false">element(person)</code>, because it excludes nilled elements.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">element(doctor|nurse)</code> matches any element node whose name is 
                        <code nobreak="false">doctor</code> or <code nobreak="false">nurse</code>,
                        in the <termref def="dt-default-namespace-elements-and-types"/>.</p>
                     </item>
                     <item diff="add" at="A">
                        <p>
                           <code role="parse-test" nobreak="false">element(xhtml:*)</code> matches any element node whose name is in the namespace
                        bound to the prefix <code nobreak="false">xhtml</code>.</p>
                     </item>
                     <item diff="add" at="A">
                        <p>
                           <code role="parse-test" nobreak="false">element(xhtml:*|svg:*|mathml:*)</code> matches any element node whose name is one of the
                        three namespaces identified, specifically the namespaces bound to the prefixes
                        <code nobreak="false">xhtml</code>, <code nobreak="false">svg</code>, and <code nobreak="false">mathml</code>.</p>
                     </item>
                     <item diff="add" at="A">
                        <p>
                           <code role="parse-test" nobreak="false">element(Q{http://www.w3.org/2000/svg}*)</code> matches any element node whose name is in the SVG namespace.</p>
                     </item>
                     <item diff="add" at="A">
                        <p>
                           <code role="parse-test" nobreak="false">element(*:html)</code> matches any element node whose local name is <code nobreak="false">"html"</code>,
                     in any namespace.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">element(person, surgeon)</code> matches a
non-nilled element node whose name is <code nobreak="false">person</code> and whose
type annotation is <code nobreak="false">surgeon</code> (or is derived from <code nobreak="false">surgeon</code>). </p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">element(person, surgeon?)</code> matches a nilled or non-nilled element node whose name is <code nobreak="false">person</code> and whose type
annotation is <code nobreak="false">surgeon</code> (or is derived from <code nobreak="false">surgeon</code>).</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">element(*, surgeon)</code>
matches any non-nilled element node whose type annotation is
<code nobreak="false">surgeon</code> (or is derived from <code nobreak="false">surgeon</code>), regardless of its name.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">element(*, surgeon?)</code>
matches any nilled or non-nilled element node whose type annotation is
<code nobreak="false">surgeon</code> (or is derived from <code nobreak="false">surgeon</code>), regardless of its name.</p>
                     </item>
                  </olist>
                  <p diff="add" at="Issue451">
                  Where a <nt def="prod-xpath40-TypeName">TypeName<!--$spec = xpath40--></nt>
                     <var>T</var> (other than 
                  <code nobreak="false">xs:anyType</code> or <code nobreak="false">xs:untyped</code>) is included in an 
                  <nt def="doc-xpath40-ElementNodeType"><!--$spec = xpath40--></nt>
                     <var>T</var>, an element node will only
                  match the test if it has been validated against a schema that 
                  defines type <var>T</var>; furthermore, <var>T</var> must be
                  present in the <termref def="dt-issd"/> of the static context of the
                  <nt def="doc-xpath40-ElementNodeType"><!--$spec = xpath40--></nt>. Although it is guaranteed that
                  type <var>T</var> will have 
                  <xtermref spec="DM40" ref="dt-schema-compatible">compatible</xtermref>
                  definitions in the schema that was used for validation and in the
                  <termref def="dt-issd"/>, it is not guaranteed that revalidation
                  using the <termref def="dt-issd"/> would succeed. For example, if
                  substitution group membership varies between the two schemas, the element
                  node may contain children or descendants that the <termref def="dt-issd"/>
                  would not allow.
               </p>
                  <note>
                     <p>Technically, <code nobreak="false">element(p|q)</code> is not the same type as
               the choice item type <code nobreak="false">(element(p)|element(q))</code>. However, (a)
               they match exactly the same set of element nodes, and (b) each is a subtype
               of the other, so in practice they are indistinguishable.</p>
                  </note>
                  <div5 id="id-schema-element-test">
                     <head>Schema Element Types</head>
                     <scrap headstyle="show">
                        <prod id="doc-xpath40-SchemaElementNodeType">
                           <lhs>SchemaElementNodeType</lhs>
                           <rhs>"schema-element"  "("  <nt def="prod-xpath40-ElementName">ElementName<!--$idref_lang_part = xpath40- --></nt>  ")"</rhs>
                        </prod>

                        <prod id="doc-xpath40-SchemaElementNodeType-ElementName">
                           <lhs>ElementName</lhs>
                           <rhs>
                              <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                           </rhs>
                        </prod>

                        <prod id="doc-xpath40-SchemaElementNodeType-EQName">
                           <lhs>EQName</lhs>
                           <rhs>
                              <nt def="prod-xpath40-QName">QName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$idref_lang_part = xpath40- --></nt>
                           </rhs>
                        </prod>
                     </scrap>
                     <p>
    A <nt def="doc-xpath40-SchemaElementNodeType"><!--$spec = xpath40--></nt> matches an element node against a corresponding
    element declaration found in the <termref def="dt-is-elems">in-scope element declarations</termref>.
  </p>
                     <p>
    The <nt def="prod-xpath40-ElementName">ElementName<!--$spec = xpath40--></nt> of a <nt def="doc-xpath40-SchemaElementNodeType"><!--$spec = xpath40--></nt>
    has its prefixes expanded to a namespace URI by means of the
    <termref def="dt-static-namespaces">statically known namespaces</termref>, or if unprefixed, the
                  is interpreted according to the
                  <termref def="dt-default-namespace-elements-and-types"/>. If this has the special
                  value <code nobreak="false">"##any"</code>, an unprefixed name represents a name in no namespace.

    If the <nt def="prod-xpath40-ElementName">ElementName<!--$spec = xpath40--></nt> specified in the <nt def="doc-xpath40-SchemaElementNodeType"><!--$spec = xpath40--></nt>
    is not found in the <termref def="dt-is-elems">in-scope element declarations</termref>, a
    <termref def="dt-static-error">static error</termref> is raised <errorref class="ST" code="0008"/>.
  </p>
                     <p>
    A <nt def="doc-xpath40-SchemaElementNodeType"><!--$spec = xpath40--></nt> matches a candidate element node if all of the following conditions are satisfied:
  </p>
                     <olist>
                        <item>
                           <p>Either:</p>
                           <olist>
                              <item>
                                 <p>The name <var>N</var> of the candidate node matches the specified <nt def="prod-xpath40-ElementName">ElementName<!--$spec = xpath40--></nt>, or</p>
                              </item>
                              <item>
                                 <p>The name <var>N</var> of the candidate node matches the name of an element declaration 
                              that is a member of the actual substitution group headed by the declaration of element <nt def="prod-xpath40-ElementName">ElementName<!--$spec = xpath40--></nt>.</p>
                              </item>
                           </olist>
                           <note>
                              <p>The term “actual substitution group” is defined in <bibref ref="XMLSchema11"/>. The actual substitution group of an element declaration 
                           <var>H</var> includes those element declarations 
                           <var>P</var> that are declared to have <var>H</var> as their 
                           direct or indirect substitution group head, provided that 
                           <var>P</var> is not declared as abstract, and that <var>P</var> 
                           is validly substitutable for <var>H</var>, which means that 
                           there must be no blocking constraints that prevent substitution.</p>
                           </note>
                        </item>
                        <item>
                           <p>The schema element declaration named <var>N</var> is not abstract.</p>
                        </item>
                        <item>
                           <p>
                              <var>AT</var>
                              <termref def="dt-derives-from"/>
                              <var>ET</var>,
                        where <var>AT</var> is the type annotation of the candidate node 
                        and <var>ET</var> is the schema type referenced by the <code nobreak="false">{type definition}</code> 
                        property of the global schema element declaration named <var>N</var>.</p>
                           <note>
                              <p>If the element declaration has no explicit <code nobreak="false">type</code> attribute
                        or <code nobreak="false">xs:simpleType</code> or <code nobreak="false">xs:complexType</code> child, but
                        is a member of a substitution group, then the <code nobreak="false">{type definition}</code> 
                        property defaults to the <code nobreak="false">{type definition}</code> of the first
                        element named in the <code nobreak="false">substitutionGroup</code> attribute.</p>
                           </note>
                        </item>
                        <item>
                           <p>If the schema element declaration named <var>N</var> 
                        is not nillable, then the <code nobreak="false">nilled</code> property of the candidate node 
                        is <code nobreak="false">false</code>.</p>
                        </item>
                     </olist>
                     <note>
                        <p>The broad intent of the <code nobreak="false">schema-element(<var>N</var>)</code> 
                  type is to select nodes that have been
                  validated (using strict or lax validation) against the global element declaration 
                  named <var>N</var>. An element that has been validated in this way will always match
                  the <code nobreak="false">schema-element</code> test. However, it is possible for an element node
                  to match the <code nobreak="false">schema-element(<var>N</var>)</code> test and yet be invalid against the element
                  declaration <var>N</var>. This can happen, for example, when 
                  (a) the element node has been validated against an
                  unrelated (local) element declaration having the same name and the same type, 
                  and (b) the global element
                  declaration imposes constraints beyond those implied by its 
                  <code nobreak="false">{type definition}</code> property. For example, the global element declaration
                  might define uniqueness constraints that are not present in the local element declaration
                  that was used for validation.</p>
                     </note>
                     <p>Example: The <nt def="doc-xpath40-SchemaElementNodeType"><!--$spec = xpath40--></nt>
                        <code role="parse-test" nobreak="false">schema-element(customer)</code> matches a candidate element node 
                  in the following two situations (among others):
<olist>
                           <item>
                              <p>
                                 <code nobreak="false">customer</code> is a top-level element declaration in the in-scope element declarations; 
                           the name of the candidate node is <code nobreak="false">customer</code>; the element declaration of <code nobreak="false">customer</code> 
                           is not abstract; the type annotation of the candidate node is the same as or 
                           derived from the schema type declared in the <code nobreak="false">customer</code> element declaration; 
                           and either the candidate node is not nilled, or <code nobreak="false">customer</code> is declared to be nillable.</p>
                           </item>
                           <item>
                              <p>
                                 <code nobreak="false">customer</code> is a top-level element declaration in the in-scope element declarations; 
                           the name of the candidate node is <code nobreak="false">client</code>; <code nobreak="false">client</code> is an actual 
                           (non-abstract and non-blocked) member of the substitution group of 
                           <code nobreak="false">customer</code>; the type annotation of the candidate node is the same as or 
                           derived from the schema type declared for the <code nobreak="false">client</code> element; 
                           and either the candidate node is not nilled, or <code nobreak="false">client</code> is 
                           declared to be nillable.</p>
                           </item>
                        </olist>
                     </p>
                     <p diff="add" at="Issue451">
                  In the case where the schema <var>X</var> used to validate an element node 
                  <var>E</var> (whose name is <var>N</var>)
                  differs from the schema <var>Y</var> represented by the
                  <termref def="dt-issd"/> in the static context of the 
                  <nt def="doc-xpath40-SchemaElementNodeType"><!--$spec = xpath40--></nt>, the following
                  considerations apply:</p>
                     <ulist>
                        <item>
                           <p>In applying the test <code nobreak="false">
                                 <var>AT</var> derives-from <var>ET</var>
                              </code>,
                  note that <var>AT</var> will necessarily be present in <var>X</var>,
                  but not necessarily in <var>Y</var>. However, <var>ET</var> will 
                  necessarily be present in both; and because the two schemas
                  must be <xtermref spec="DM40" ref="dt-schema-compatible">compatible</xtermref>,
                  <var>ET</var> will be the present in both schemas, will have the same
                  definition in both, and will be the declared type of <var>N</var> in both.
                  The test can therefore be applied from knowledge of type <var>AT</var>
                  as defined in schema <var>X</var>.</p>
                        </item>
                        <item>
                           <p>The test as to whether the element name <var>N</var> is a member
                  of the actual substitution group is performed entirely by reference
                  to schema <var>Y</var>. Although the two schemas are compatible,
                  substitution group membership can vary.</p>
                        </item>
                     </ulist>
                  </div5>
               </div4>
               <div4 id="id-attribute-test">
                  <head>Attribute Types</head>
                  <changes>
                     <change issue="107" PR="286" date="2023-01-17">
                     Element and attribute tests of the form <code nobreak="false">element(N)</code>
                     and <code nobreak="false">attribute(N)</code> now allow <code nobreak="false">N</code> to be any <code nobreak="false">NameTest</code>,
                     including a wildcard.
                  </change>
                     <change issue="23" PR="606" date="2023-01-17">
                     Element and attribute tests of the form <code nobreak="false">element(A|B)</code>
                     and <code nobreak="false">attribute(A|B)</code> are now allowed.
                  </change>
                  </changes>
                  <scrap headstyle="show">
                     <prod id="doc-xpath40-AttributeNodeType">
                        <lhs>AttributeNodeType</lhs>
                        <rhs>"attribute"  "("  (<nt def="prod-xpath40-NameTestUnion">NameTestUnion<!--$idref_lang_part = xpath40- --></nt>  (","  <nt def="prod-xpath40-TypeName">TypeName<!--$idref_lang_part = xpath40- --></nt>)?)?  ")"</rhs>
                     </prod>

                     <prod id="doc-xpath40-AttributeNodeType-NameTestUnion">
                        <lhs>NameTestUnion</lhs>
                        <rhs>(<nt def="prod-xpath40-NameTest">NameTest<!--$idref_lang_part = xpath40- --></nt> ++ "|")</rhs>
                     </prod>

                     <prod id="doc-xpath40-AttributeNodeType-NameTest">
                        <lhs>NameTest</lhs>
                        <rhs>
                           <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-Wildcard">Wildcard<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-AttributeNodeType-EQName">
                        <lhs>EQName</lhs>
                        <rhs>
                           <nt def="prod-xpath40-QName">QName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-AttributeNodeType-Wildcard">
                        <lhs>Wildcard</lhs>
                        <rhs>"*"<br/>|  (<nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>  ":*")<br/>|  ("*:"  <nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>)<br/>|  (<nt def="prod-xpath40-BracedURILiteral">BracedURILiteral<!--$idref_lang_part = xpath40- --></nt>  "*")</rhs>
                        <com>
                           <loc href="#ws-explicit">ws: explicit</loc>
                        </com>
                     </prod>

                     <prod id="doc-xpath40-AttributeNodeType-TypeName">
                        <lhs>TypeName</lhs>
                        <rhs>
                           <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>
                  </scrap>
                  <p>
    An <nt def="doc-xpath40-AttributeNodeType"><!--$spec = xpath40--></nt> is used to match an
    attribute node by its name and/or <termref def="dt-type-annotation">type annotation</termref>.
  </p>
                  <p>An unprefixed <nt def="doc-xpath40-EQName">EQName<!--$spec = xpath40--></nt>
               within the <code nobreak="false">NameTestUnion</code> is expanded using the
                  <termref def="dt-no-namespace-rule"/>.
                  The name need not be present in the <termref def="dt-is-attrs">in-scope attribute declarations</termref>.</p>
                  <p>An unprefixed <nt def="prod-xpath40-TypeName">TypeName<!--$spec = xpath40--></nt> is expanded using the <termref def="dt-default-type-namespace-rule"/>.
                  The <nt def="prod-xpath40-TypeName">TypeName<!--$spec = xpath40--></nt> must be present in the <termref def="dt-is-types">in-scope schema types</termref>
                     <errorref class="ST" code="0008"/>
                  </p>
                  <p diff="chg" at="Issue23">An <nt def="doc-xpath40-AttributeNodeType"><!--$spec = xpath40--></nt>
                     <var>AT</var> matches an item <var>A</var> if the following conditions
                     are satisfied:</p>
                  <olist>
                     <item>
                        <p>
                           <var>A</var> is an attribute node.</p>
                     </item>
                     <item>
                        <p>If <var>AT</var> includes a <nt def="prod-xpath40-NameTestUnion">NameTestUnion<!--$spec = xpath40--></nt>,
                        then the name of the attribute node <var>A</var> matches one or more of
                        the <nt def="prod-xpath40-NameTest">NameTests<!--$spec = xpath40--></nt> in the <nt def="prod-xpath40-NameTestUnion">NameTestUnion<!--$spec = xpath40--></nt>.
                        A name <var>N</var> matches a <nt def="prod-xpath40-NameTest">NameTest<!--$spec = xpath40--></nt>
                           <var>NT</var> if one of the following
                        conditions is true:</p>
                        <olist>
                           <item>
                              <p>
                                 <var>NT</var> is <code nobreak="false">*</code>
                              </p>
                           </item>
                           <item>
                              <p>
                                 <var>NT</var> is <code nobreak="false">*:<emph>local</emph>
                                 </code> and the local part
                           of <var>N</var> matches <var>local</var>.</p>
                           </item>
                           <item>
                              <p>
                                 <var>NT</var> is <code nobreak="false">
                                    <emph>prefix</emph>:*</code> and the namespace URI
                           of <var>N</var> matches the namespace URI bound to <var>prefix</var> in the static
                           context.</p>
                           </item>
                           <item>
                              <p>
                                 <var>NT</var> is <code nobreak="false">
                                    <emph>BracedURILiteral</emph>*</code> and the namespace URI
                              of <var>N</var> matches the namespace URI found in the <code nobreak="false">BracedURILiteral</code>.</p>
                           </item>
                           <item>
                              <p>
                                 <var>NT</var> is an <code nobreak="false">EQName</code> equal to <var>N</var>.</p>
                           </item>
                        </olist>
                     </item>
                     <item>
                        <p>If <var>AT</var> includes a <nt def="prod-xpath40-TypeName">TypeName<!--$spec = xpath40--></nt>
                           <var>T</var>,
                        then the <termref def="dt-type-annotation"/> of the attribute node <var>A</var>
                           <termref def="dt-derives-from"/>
                           <var>T</var>.</p>
                     </item>
                  </olist>
                  <p>Here are some examples of <nt def="doc-xpath40-AttributeNodeType"><!--$spec = xpath40--></nt>s:
  </p>
                  <ulist>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">attribute()</code> and <code role="parse-test" nobreak="false">attribute(*)</code> match any single attribute node,
regardless of its name or type annotation.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">attribute(price)</code>
                        matches any attribute node whose name is <code nobreak="false">price</code>
                        (in no namespace), regardless of its type annotation.</p>
                     </item>
                     <item diff="add" at="Issue23">
                        <p>
                           <code role="parse-test" nobreak="false">attribute(price|discount)</code>
                        matches any attribute node whose name is <code nobreak="false">price</code> or <code nobreak="false">discount</code>
                        (in no namespace).</p>
                     </item>
                     <item diff="add" at="A">
                        <p>
                           <code role="parse-test" nobreak="false">attribute(xlink:*)</code> matches any attribute node whose name is in the namespace
                        bound to the prefix <code nobreak="false">xlink</code>.</p>
                     </item>
                     <item diff="add" at="A">
                        <p>
                           <code role="parse-test" nobreak="false">element(Q{http://www.w3.org/2000/svg}*)</code> matches any attribute node whose name is in the SVG namespace.</p>
                     </item>
                     <item diff="add" at="A">
                        <p>
                           <code nobreak="false">attribute(*:default-collation)</code> matches any attribute node
                        whose local name is <code nobreak="false">default-collation</code>,
                        regardless of namespace, and regardless of type annotation.</p>
                     </item>
                     <item diff="add" at="Issue23">
                        <p>
                           <code nobreak="false">attribute(*:price|*:discount)</code> matches any attribute node
                        whose local name is <code nobreak="false">price</code> or <code nobreak="false">discount</code>,
                        regardless of namespace, and regardless of type annotation.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">attribute(price, currency)</code> matches an
attribute node whose name is <code nobreak="false">price</code> (in no namespace) and whose type
annotation is
<code nobreak="false">currency</code> (or is derived from <code nobreak="false">currency</code>).</p>
                     </item>
                     <item diff="add" at="A">
                        <p>
                           <code role="parse-test" nobreak="false">attribute(xlink:*, xs:string)</code> matches any attribute node whose name is in the namespace
                        bound to the prefix <code nobreak="false">xlink</code>, and whose type annotation is <code nobreak="false">xs:string</code>
                     or a type derived from <code nobreak="false">xs:string</code>.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">attribute(*, currency)</code> matches any attribute node whose
type annotation is <code nobreak="false">currency</code> (or is derived from <code nobreak="false">currency</code>), regardless of its
name.</p>
                     </item>
                  </ulist>
                  <p diff="add" at="Issue451">
                  Unlike the situation with an <nt def="doc-xpath40-ElementNodeType"><!--$spec = xpath40--></nt>,
                  few problems arise if the attribute was validated using a different
                  schema. This is because simple types can never be derived by extension,
                  and attributes do not have substitution groups.</p>
                  <note>
                     <p>Technically, <code nobreak="false">attribute(p|q)</code> is not the same type as
               the choice item type <code nobreak="false">(attribute(p)|attribute(q))</code>. However, (a)
               they match exactly the same set of attribute nodes, and (b) each is a subtype
               of the other, so in practice they are indistinguishable.</p>
                  </note>
                  <div5 id="id-schema-attribute-test">
                     <head>Schema Attribute Types</head>
                     <scrap headstyle="show">
                        <prod id="doc-xpath40-SchemaAttributeNodeType">
                           <lhs>SchemaAttributeNodeType</lhs>
                           <rhs>"schema-attribute"  "("  <nt def="prod-xpath40-AttributeName">AttributeName<!--$idref_lang_part = xpath40- --></nt>  ")"</rhs>
                        </prod>

                        <prod id="doc-xpath40-SchemaAttributeNodeType-AttributeName">
                           <lhs>AttributeName</lhs>
                           <rhs>
                              <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                           </rhs>
                        </prod>

                        <prod id="doc-xpath40-SchemaAttributeNodeType-EQName">
                           <lhs>EQName</lhs>
                           <rhs>
                              <nt def="prod-xpath40-QName">QName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$idref_lang_part = xpath40- --></nt>
                           </rhs>
                        </prod>
                     </scrap>
                     <p>
    A <nt def="doc-xpath40-SchemaAttributeNodeType"><!--$spec = xpath40--></nt> matches an attribute node against a corresponding
    attribute declaration found in the <termref def="dt-is-attrs">in-scope attribute declarations</termref>.
  </p>
                     <p>
    The <nt def="prod-xpath40-AttributeName">AttributeName<!--$spec = xpath40--></nt> of a <nt def="doc-xpath40-SchemaAttributeNodeType"><!--$spec = xpath40--></nt>
    has its prefixes expanded to a namespace URI by means of the
    <termref def="dt-static-namespaces">statically known namespaces</termref>. If unprefixed, an
    <nt def="prod-xpath40-AttributeName">AttributeName<!--$spec = xpath40--></nt> is in no namespace.

    If the <nt def="prod-xpath40-AttributeName">AttributeName<!--$spec = xpath40--></nt> specified in the <nt def="doc-xpath40-SchemaAttributeNodeType"><!--$spec = xpath40--></nt>
    is not found in the <termref def="dt-is-attrs">in-scope attribute declarations</termref>, a
    <termref def="dt-static-error">static error</termref> is raised <errorref class="ST" code="0008"/>.
  </p>
                     <p>
    A <nt def="doc-xpath40-SchemaAttributeNodeType"><!--$spec = xpath40--></nt> matches a candidate attribute node if both of the
  following conditions are satisfied:
  </p>
                     <olist>
                        <item>
                           <p>The name of the candidate node matches the specified <nt def="prod-xpath40-AttributeName">AttributeName<!--$spec = xpath40--></nt>.</p>
                        </item>
                        <item>
                           <p>
                              <var>AT</var>
                              <termref def="dt-derives-from"/>
                              <var>ET</var>,
                        where <var>AT</var> is the type annotation of the candidate node and 
                        <var>ET</var> is the schema type (always a simple type) referenced
                        by the <code nobreak="false">{type definition}</code> property of the attribute
                        declaration for attribute <nt def="prod-xpath40-AttributeName">AttributeName<!--$spec = xpath40--></nt> in the <termref def="dt-is-attrs">in-scope attribute declarations</termref>.</p>
                        </item>
                     </olist>
                     <p>Example: The <nt def="doc-xpath40-SchemaAttributeNodeType"><!--$spec = xpath40--></nt>
                        <code role="parse-test" nobreak="false">schema-attribute(color)</code> matches a candidate attribute node if <code nobreak="false">color</code> is a top-level attribute declaration in the <termref def="dt-is-attrs">in-scope attribute declarations</termref>, the name of the candidate node is <code nobreak="false">color</code>, and the type annotation of the candidate node  is the same as or derived from the schema type declared for the <code nobreak="false">color</code> attribute.</p>
                     <p diff="add" at="Issue451">
                  Unlike the situation with a <nt def="doc-xpath40-SchemaElementNodeType"><!--$spec = xpath40--></nt>,
                  few problems arise if the attribute was validated using a different
                  schema. This is because attributes do not have substitution groups.</p>
                  </div5>
               </div4>
            </div3>
            <div3 id="id-function-map-array-tests">
               <head>Function, Map, and Array Types</head>
               <p>The following sections describe the syntax for <termref def="dt-item-type">item types</termref>
            for functions, including arrays and maps.</p>
               <p>The <termref def="dt-subtype"/> relation among these types is described in the various subsections
            of <specref ref="id-itemtype-subtype"/>.</p>
               <div4 id="id-function-test">
                  <head>Function Types</head>
                  <changes>
                     <change issue="1192" PR="1197" date="2024-05-21">The keyword <code nobreak="false">fn</code> is allowed as a synonym for <code nobreak="false">function</code>
                  in function types, to align with changes to inline function declarations.</change>
                     <change>The terms <term>FunctionType</term>, <term>ArrayType</term>,
                     <term>MapType</term>, and <term>RecordType</term> replace 
                     <term>FunctionTest</term>, <term>ArrayTest</term>,
                     <term>MapTest</term>, and <term>RecordTest</term>, with no
                  change in meaning.</change>
                     <change issue="1136" PR="1696" date="2025-01-12">
                     Parameter names may be included in a function signature; they are purely
                     documentary.
                  </change>
                  </changes>
                  <p>A <nt def="doc-xpath40-FunctionType">FunctionType<!--$spec = xpath40--></nt> matches selected <termref def="dt-function-item">function items</termref>,
                  potentially checking their <xtermref spec="DM40" ref="dt-signature">signature</xtermref>
                  (which includes the types of the arguments and results).</p>
                  <scrap headstyle="show">
                     <prod id="doc-xpath40-FunctionType">
                        <lhs>FunctionType</lhs>
                        <rhs>
                           <nt def="prod-xpath40-AnyFunctionType">AnyFunctionType<!--$idref_lang_part = xpath40- --></nt>
                           <br/>|  <nt def="prod-xpath40-TypedFunctionType">TypedFunctionType<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-FunctionType-AnyFunctionType">
                        <lhs>AnyFunctionType</lhs>
                        <rhs>("function"  |  "fn")  "("  "*"  ")"</rhs>
                     </prod>

                     <prod id="doc-xpath40-FunctionType-TypedFunctionType">
                        <lhs>TypedFunctionType</lhs>
                        <rhs>("function"  |  "fn")  "("  (<nt def="prod-xpath40-TypedFunctionParam">TypedFunctionParam<!--$idref_lang_part = xpath40- --></nt> ** ",")  ")"  "as"  <nt def="prod-xpath40-SequenceType">SequenceType<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-FunctionType-TypedFunctionParam">
                        <lhs>TypedFunctionParam</lhs>
                        <rhs>("$"  <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>  "as")?  <nt def="prod-xpath40-SequenceType">SequenceType<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-FunctionType-EQName">
                        <lhs>EQName</lhs>
                        <rhs>
                           <nt def="prod-xpath40-QName">QName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-FunctionType-SequenceType">
                        <lhs>SequenceType</lhs>
                        <rhs>("empty-sequence"  "("  ")")<br/>|  (<nt def="prod-xpath40-ItemType">ItemType<!--$idref_lang_part = xpath40- --></nt>
                           <nt def="prod-xpath40-OccurrenceIndicator">OccurrenceIndicator<!--$idref_lang_part = xpath40- --></nt>?)</rhs>
                     </prod>
                  </scrap>
                  <p>The keywords <code nobreak="false">function</code> and <code nobreak="false">fn</code> are synonyms.</p>
                  <p>An <nt def="prod-xpath40-AnyFunctionType">AnyFunctionType<!--$spec = xpath40--></nt>
    matches any <termref def="dt-function-item"/>, including a map or an array. For example,
    the following expressions all return true:</p>
                  <ulist>
                     <item>
                        <p>
                           <code nobreak="false">fn:name#1 instance of function(*)</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">fn { @id } instance of function(*)</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">fn:random-number-generator() instance of function(*)</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">[ 1, 2, 3 ] instance of fn(*)</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">{} instance of fn(*)</code>
                        </p>
                     </item>
                  </ulist>
                  <p>A <nt def="prod-xpath40-TypedFunctionType">TypedFunctionType<!--$spec = xpath40--></nt> matches
    a <termref def="dt-function-item"/> if the function’s type signature (as defined in
    <xspecref spec="DM40" ref="function-items"/>) is a <termref def="dt-subtype">subtype</termref> of the <nt def="prod-xpath40-TypedFunctionType">TypedFunctionType<!--$spec = xpath40--></nt>.</p>
                  <note>
                     <p>The keywords <code nobreak="false">function</code> and <code nobreak="false">fn</code> are synonymous.</p>
                  </note>
                  <p>If parameter names are included in a <nt def="prod-xpath40-TypedFunctionType">TypedFunctionType<!--$spec = xpath40--></nt>,
               they are purely documentary and have no semantic effect. In particular, they
               play no part in deciding whether a particular function item matches the
               function type, and they never appear as keywords in function calls. 
               For example the construct
               <code nobreak="false">function($x as node()) as xs:string</code> designates exactly the same type
               as <code nobreak="false">function(node()) as xs:string</code>.</p>
                  <p>Any parameter names that are supplied must be distinct 
                  <errorref spec="XQ" class="ST" code="0039"/>.</p>
                  <p diff="add" at="issue730">A <nt def="prod-xpath40-TypedFunctionType">TypedFunctionType<!--$spec = xpath40--></nt>
               may also match certain maps and arrays, as described in <specref ref="id-map-test"/> and
               <specref ref="id-array-test"/>
                  </p>
                  <p>
    Here are some examples of expressions that 
    use a <nt def="prod-xpath40-TypedFunctionType">TypedFunctionType<!--$spec = xpath40--></nt>:
  </p>
                  <ulist>
                     <item>
                        <p>
                           <code nobreak="false">fn:count#1 instance of function(item()*) as xs:integer</code> returns true,
                        because the signature of the function item <code nobreak="false">fn:count#1</code>
                        is <code nobreak="false">function(item()*) as xs:integer</code>.
                     </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">fn:count#1 instance of function(xs:string*) as item()</code> returns true,
                        because the signature of the function item <code nobreak="false">fn:count#1</code>
                        is a subtype of <code nobreak="false">function(xs:string*) as item()</code>.
                     </p>
                        <note>
                           <p>The same type might also be written 
                        <code nobreak="false">fn($x as xs:int, $y as xs:int) as xs:int</code>.</p>
                        </note>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">function(xs:anyAtomicType) as item()*</code> matches any map, 
                        or any other function item with the required signature.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">function(xs:integer) as item()*</code> matches any array, 
                        or any other function item with the required signature.</p>
                     </item>
                  </ulist>
               </div4>
               <div4 id="id-map-test">
                  <head>Map Types</head>
                  <p>A <nt def="doc-xpath40-MapType">MapType<!--$spec = xpath40--></nt> designates an item type that
               either matches any map, or that matches maps whose keys and values
               are constrained to specific types.</p>
                  <scrap headstyle="show">
                     <head/>
                     <prod id="doc-xpath40-MapType">
                        <lhs>MapType</lhs>
                        <rhs>
                           <nt def="prod-xpath40-AnyMapType">AnyMapType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-TypedMapType">TypedMapType<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-MapType-AnyMapType">
                        <lhs>AnyMapType</lhs>
                        <rhs>"map"  "("  "*"  ")"</rhs>
                     </prod>

                     <prod id="doc-xpath40-MapType-TypedMapType">
                        <lhs>TypedMapType</lhs>
                        <rhs>"map"  "("  <nt def="prod-xpath40-ItemType">ItemType<!--$idref_lang_part = xpath40- --></nt>  ","  <nt def="prod-xpath40-SequenceType">SequenceType<!--$idref_lang_part = xpath40- --></nt>  ")"</rhs>
                     </prod>

                     <prod id="doc-xpath40-MapType-ItemType">
                        <lhs>ItemType</lhs>
                        <rhs>
                           <nt def="prod-xpath40-RegularItemType">RegularItemType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-FunctionType">FunctionType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-TypeName">TypeName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ChoiceItemType">ChoiceItemType<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-MapType-SequenceType">
                        <lhs>SequenceType</lhs>
                        <rhs>("empty-sequence"  "("  ")")<br/>|  (<nt def="prod-xpath40-ItemType">ItemType<!--$idref_lang_part = xpath40- --></nt>
                           <nt def="prod-xpath40-OccurrenceIndicator">OccurrenceIndicator<!--$idref_lang_part = xpath40- --></nt>?)</rhs>
                     </prod>
                  </scrap>
                  <p>An <nt def="prod-xpath40-AnyMapType">AnyMapType<!--$spec = xpath40--></nt>
                     <code nobreak="false">map(*)</code> matches any map.</p>
                  <p>The <nt def="doc-xpath40-MapType">MapType<!--$spec = xpath40--></nt>
                     <code nobreak="false">map(K, V)</code> matches any map where every key
                  is an instance of <code nobreak="false">K</code> and every value is an
                  instance of <code nobreak="false">V</code>.</p>
                  <p>The <xtermref spec="DM40" ref="dt-entry-order">entry-order</xtermref>
               of a map has no effect on whether the map matches a particular
               map type.</p>
                  <p diff="add" at="A">Although the grammar for <code nobreak="false">TypedMapType</code>
               allows the key to be described using the full <code nobreak="false">ItemType</code> syntax, the item type used must be
               a <termref def="dt-generalized-atomic-type"/>
                     <errorref class="ST" code="0152"/>.</p>
                  <p>For example, given a map <code nobreak="false">$M</code> whose keys are integers and whose
  results are strings, such as <code nobreak="false">{ 0: "no", 1: "yes" }</code>,
  the following following expressions deliver the result shown:
  </p>
                  <ulist>
                     <item>
                        <p>
                           <code nobreak="false">$M instance of map(*)</code>  returns <code nobreak="false">true</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">$M instance of map(xs:integer, xs:string)</code>  returns <code nobreak="false">true</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">$M instance of map(xs:decimal, xs:anyAtomicType)</code>  returns <code nobreak="false">true</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">$M instance of map(xs:int, xs:string)</code>  returns <code nobreak="false">false</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">$M instance of map(xs:integer, xs:token))</code>  returns <code nobreak="false">false</code>
                        </p>
                     </item>
                  </ulist>
                  <p diff="add" at="issue730">A map is also a function item, and therefore matches certain
               function types. Specifically, a map that matches <code nobreak="false">map(K, V)</code> also matches a function
               type of the form <code nobreak="false">function(xs:anyAtomicType) as R</code> provided that both the following
                  conditions are satisfied:</p>
                  <ulist diff="add" at="issue730">
                     <item>
                        <p>
                           <var>V</var> is a <termref def="dt-subtype"/> of <var>R</var>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">empty-sequence()</code> is a <termref def="dt-subtype"/> of <var>R</var>
                        </p>
                     </item>
                  </ulist>
                  <note diff="add" at="issue730">
                     <p>To understand this rule, consider the use of a map <code nobreak="false">$M</code> in a function 
                  call <code nobreak="false">$M($K)</code>, which is equivalent to the function call <code nobreak="false">map:get($M, $K)</code>.

                  This function accepts any atomic item for the argument <code nobreak="false">$K</code>, and hence matches
                  a function type that requires an argument type of <code nobreak="false">xs:anyAtomicType</code>. If the

                  key <code nobreak="false">$K</code> is present in the map, the result of the function will be a value of
                  type <var>V</var>; if not, it will be the empty sequence. The map is therefore substitutable
                  for the function type provided that the function type allows both a value of type <var>V</var>
                  and the empty sequence as possible results.</p>
                     <p>The key type <var>K</var> does not enter into this rule. That is because in the function call
                     <code nobreak="false">$M($K)</code>, the sought key <code nobreak="false">$K</code> does not have to be of the same
                  type as the keys actually present in the map.</p>
                     <p>The transitivity rules for item type matching mean that if an item <var>M</var>
                     matches a type <var>T</var>, and <var>T</var> is a <termref def="dt-subtype"/> 
                     of <var>U</var>, then <var>M</var> also matches type <var>U</var>. So the fact
                  that a map from integers to strings (<code nobreak="false">map(xs:integer, xs:string)</code>)
                  matches <code nobreak="false">function(xs:anyAtomicType) as xs:string?</code>
                  means that it will also match other function types such as 
                     <code nobreak="false">function(xs:integer) as xs:string?</code> and 
                     <code nobreak="false">function(xs:decimal) as xs:anyAtomicType?</code>
                     </p>
                     <p>Furthermore, the rules for
                     <termref def="dt-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 
                     <code nobreak="false">map(xs:integer, xs:string)</code> can be coerced to a function of
                     type <code nobreak="false">function(xs:integer) as xs:string</code>; in this situation a type
                     error will occur only if a call on the function actually returns the empty sequence. </p>
                  </note>
                  <p>Examples:</p>
                  <ulist>
                     <item>
                        <p>
                           <code nobreak="false">$M instance of fn(*)</code>  returns <code nobreak="false">true</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">$M instance of fn(xs:anyAtomicType) as item()*</code> returns <code nobreak="false">true</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">$M instance of fn(xs:integer) as item()*</code>  returns <code nobreak="false">true</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">$M instance of fn(xs:int) as item()*</code>  returns <code nobreak="false">true</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">$M instance of fn(xs:string) as item()*</code>  returns <code nobreak="false">true</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">not($M instance of fn(xs:integer) as xs:string)</code>  returns <code nobreak="false">true</code>
                        </p>
                     </item>
                  </ulist>
                  <note>
                     <p>The last case might seem surprising; 
                     however, <termref def="dt-function-coercion">function coercion</termref> ensures that <code nobreak="false">$M</code> can be used successfully 
  anywhere that the required type is <code nobreak="false">fn(xs:integer) as xs:string</code>.</p>
                  </note>
                  <p>Rules defining whether one map type is a <termref def="dt-subtype"/> of another
               are given in <specref ref="id-item-subtype-maps"/>.</p>
               </div4>
               <div4 id="id-record-test" diff="add" at="A">
                  <head>Record Types</head>
                  <changes>
                     <change>
                     Record types are added as a new kind of <code nobreak="false">ItemType</code>, constraining
                     the value space of maps.
                  </change>
                     <!--<change issue="52" PR="728" date="2023-10-10">
                     The syntax <code>record(*)</code> is allowed; it matches any map.
                  </change>-->
                     <change issue="1491" PR="1577" date="2024-10-17">
                     The syntax <code nobreak="false">record()</code> is allowed; the only thing it matches is the empty map.
                  </change>
                     <change issue="2365" PR="2413" date="2026-01-28">
                     Extensible map types are dropped; instead, the coercion rules cause undefined
                     map entries to be discarded.
                  </change>
                  </changes>
                  <p>A <nt def="doc-xpath40-RecordType">RecordType<!--$spec = xpath40--></nt> matches maps that meet specific criteria.</p>
                  <p>For example, the <code nobreak="false">RecordType</code>
                     <code nobreak="false">record(r as xs:double, i as xs:double)</code>
		             matches a map if the map has exactly two entries: an entry with key <code nobreak="false">"r"</code>
		                whose value is a <termref def="dt-singleton"/>
                     <code nobreak="false">xs:double</code> value, and an entry with key <code nobreak="false">"i"</code>
		                whose value is also a <termref def="dt-singleton"/>
                     <code nobreak="false">xs:double</code> value.</p>
                  <p>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.</p>
                  <scrap headstyle="show">
                     <prod id="doc-xpath40-RecordType">
                        <lhs>RecordType</lhs>
                        <rhs>"record"  "("  (<nt def="prod-xpath40-FieldDeclaration">FieldDeclaration<!--$idref_lang_part = xpath40- --></nt> ** ",")  ")"</rhs>
                     </prod>

                     <prod id="doc-xpath40-RecordType-FieldDeclaration">
                        <lhs>FieldDeclaration</lhs>
                        <rhs>
                           <nt def="prod-xpath40-FieldName">FieldName<!--$idref_lang_part = xpath40- --></nt>  "?"?  ("as"  <nt def="prod-xpath40-SequenceType">SequenceType<!--$idref_lang_part = xpath40- --></nt>)?</rhs>
                     </prod>

                     <prod id="doc-xpath40-RecordType-FieldName">
                        <lhs>FieldName</lhs>
                        <rhs>
                           <nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="doc-xpath40-StringLiteral">StringLiteral<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-RecordType-StringLiteral">
                        <lhs>StringLiteral</lhs>
                        <rhs>
                           <nt def="prod-xpath40-AposStringLiteral">AposStringLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-QuotStringLiteral">QuotStringLiteral<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                        <com>
                           <loc href="#ws-explicit">ws: explicit</loc>
                        </com>
                     </prod>

                     <prod id="doc-xpath40-RecordType-SequenceType">
                        <lhs>SequenceType</lhs>
                        <rhs>("empty-sequence"  "("  ")")<br/>|  (<nt def="prod-xpath40-ItemType">ItemType<!--$idref_lang_part = xpath40- --></nt>
                           <nt def="prod-xpath40-OccurrenceIndicator">OccurrenceIndicator<!--$idref_lang_part = xpath40- --></nt>?)</rhs>
                     </prod>
                  </scrap>
                  <!--<p>If the list of fields ends with <code>",*"</code> then the record type is said to be
		                <term>extensible</term>. For example, the <code>RecordType</code>
                  <code>record(e as element(Employee), *)</code>
		             matches a map if it has an entry with key <code>"e"</code> whose value matches <code>element(Employee)</code>,
		             regardless what other entries the map might contain.</p>-->
                  <p>For generality, the syntax <code nobreak="false">record()</code> defines a record type that has no explicit fields. 
                  The only thing it matches is an <xtermref spec="DM40" ref="dt-empty-map"/>.</p>
                  <p>A record type can describe only maps whose keys are strings.
		             A field 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.</p>
                  <p>Although constructors for named record types produce a map in which the
                  <xtermref spec="DM40" ref="dt-entry-order">entry order</xtermref> reflects
                  the order of field definitions in the record type definition,
                  the <xtermref spec="DM40" ref="dt-entry-order">entry order</xtermref>
                  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.</p>
                  <note>
                     <p>Lookup expressions have been extended in 4.0 so that non-NCName keys can be used without
		             parentheses: <code nobreak="false">employee?"middle name"</code>
                     </p>
                  </note>
                  <p>If the type declaration for a field is omitted, then <code nobreak="false">item()*</code> is assumed: that is,
		             the map entry may have any type.</p>
                  <p>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 <code nobreak="false">RecordType</code>
                     <code nobreak="false">record(first as xs:string, middle? as xs:string, last as xs:string)</code>
		                requires the map to have string-valued entries with keys <code nobreak="false">"first"</code> and <code nobreak="false">"last"</code>;
		                it also declares that if the map has an entry with key <code nobreak="false">"middle"</code>, the value of that
		                entry must be a single <code nobreak="false">xs:string</code>. Declaring the type as 
		                <code nobreak="false">record(first as xs:string, middle? as xs:string?, last as xs:string)</code> also allows
		             the entry with key <code nobreak="false">"middle"</code> to be present but empty.</p>
                  <p>A map that contains an entry whose key corresponds to no field in the record type does not
               match the record type. However, it can be coerced to such a record type when the <termref def="dt-coercion-rules"/>
               are applied. In practice this means that when the required type of an argument is declared using a record
               type, the map that is supplied as a value for this argument may contain additional fields, which are discarded
               so they are invisible to the called function.</p>
                  <!--<note>
                  <p>Within an extensible record type, a <code>FieldDeclaration</code> 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.</p>
               </note>-->
                  <p>The names of the fields in a record type must be distinct <errorref class="ST" code="0021"/>.</p>
                  <p>If a variable <code nobreak="false">$rec</code> is known to conform to a particular
		             record type, then when a lookup expression <code nobreak="false">$rec?field</code> is used, (a) the processor
		             can report a type error if <code nobreak="false">$rec</code> cannot contain an entry with name <code nobreak="false">field</code>
                   (see <specref ref="id-implausible-lookup-expressions"/>),
		             and (b) the processor can make static type inferences about the type of value returned by 
		             <code nobreak="false">$rec?field</code>.</p>
                  <note>
                     <p>(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 <code nobreak="false">map(*)</code>, 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 <function>fn:parse-json</function>, previously
		                given as <code nobreak="false">map(*)</code>, can now be expressed as <code nobreak="false">record(liberal? as xs:boolean, 
		                   duplicates? as xs:string, escape? as xs:boolean, fallback as fn(xs:string) as xs:string)</code>.
		                In principle the <code nobreak="false">xs:string</code> type used to describe the <code nobreak="false">duplicates</code>
		                   option could also be replaced by a schema-defined subtype
		                of <code nobreak="false">xs:string</code> that enumerates the permitted values (<code nobreak="false">"reject"</code>,
		                   <code nobreak="false">"use-first"</code>, <code nobreak="false">"use-last"</code>). 
		                </p>
                     <p>The use of a record type in the signature of such a function causes the 
		                   <termref def="dt-coercion-rules">coercion rules</termref>
		                to be invoked. So, for example, if the function expects an entry in the map to be an <code nobreak="false">xs:double</code>
		                value, it becomes possible to supply a map in which the corresponding entry has type <code nobreak="false">xs:integer</code>.</p>
                     <p>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.</p>
                  </note>
                  <note>
                     <p>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 <code nobreak="false">{longitude: 130.2, latitude: 53.4}</code> 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 
		                <code nobreak="false">match="record(longitude, latitude)"</code>
                     </p>
                  </note>
                  <p>Rules defining whether one record type is a <termref def="dt-subtype"/> of another
                  are given in <specref ref="id-item-subtype-records"/>.</p>
                  <div5 id="id-recursive-record-tests" diff="add" at="issue295">
                     <head>Recursive Record Types</head>
                     <p>A named record type <var>N</var> is said to be recursive if its 
                  definition includes a direct or indirect reference to <var>N</var>. 
               </p>
                     <p>For example, the following XQuery declaration defines a linked list:</p>
                     <p>
                        <eg xml:space="preserve">declare record my:list (value as item()*, next? as my:list);</eg>
                     </p>
                     <p>The equivalent in XSLT is:</p>
                     <eg xml:space="preserve">&lt;xsl:record-type name="my:list"&gt;
   &lt;xsl:field name="value" as="item()*"/&gt;
   &lt;xsl:field name="next" as="my:list" required="no"/&gt;
&lt;/xsl:record-type&gt;</eg>
                     <p>Instances of recursive record types can be constructed and interrogated in the normal way.
               For example a list of length 3 can be constructed as:</p>
                     <p>
                        <eg xml:space="preserve">{ "value": 1, "next": { "value": 2, "next": { "value": 3 } } }</eg>
                     </p>
                     <p>and the third value in the map can be retrieved as <code nobreak="false">$list?next?next?value</code>.
               In practice, recursive data structures are usually manipulated using recursive functions.</p>
                     <p>It is possible to define a recursive record type that cannot be instantiated, because it
               has no finite instances: for example (in XQuery) <code nobreak="false">declare record X (next as X);</code>.
               Such a record declaration is <termref def="dt-implausible"/>, so the processor may
               treat it as an error <errorref class="ST" code="0023"/>, but it is not obliged to do so.</p>
                     <note>
                        <p>For an example of a practical use of recursive record types, see the
               specification of the function <function>fn:random-number-generator</function>.</p>
                     </note>
                     <p>Recursive type definitions need to be handled specially by the subtyping rules; 
                  a naïve approach of simply replacing each reference to a named item type 
               with its definition would make the assessment of the subtype relationship non-terminating.
               For details see <specref ref="id-itemtype-subtype"/>.</p>
                     <note>
                        <p>While record types may be recursive, it is not possible to construct
               instances containing cyclic references. Specifically, if an instance <var>A</var> contains a reference
               to <var>B</var> then it is not possible for <var>B</var> to contain a reference to <var>A</var>.
               This is because <var>A</var> cannot contain a reference to <var>B</var>
               unless <var>B</var> exists at the time <var>A</var> is created, and since all values
               are immutable, <var>B</var> cannot subsequently be updated to refer to <code nobreak="false">A</code>.</p>
                        <p>The simplest workaround for this is to make the references indirect, via some kind of index
               based on application-allocated unique identifiers.</p>
                        <p>The data model does not forbid cycles among instances, and indeed, there are functions
               such as <function>fn:schema-type</function> that may return cyclic instances. However, such
               cycles can only be constructed using mechanisms beyond the capabilities of XPath 4.0.
               (The structure returned by <function>fn:schema-type</function> carefully uses functions
               to represent references from one value to another, rather than making the 
               references direct. This reduces the danger that
               operations such as serialization will be non-terminating. However, it does not remove
               the difficulty that the structure cannot be built using XPath 4.0 alone.)</p>
                     </note>
                     <example id="e-binary-tree">
                        <head>A Binary Tree</head>
                        <p>A record used to represent a node in a binary tree might be represented (using XQuery syntax) as:</p>
                        <eg xml:space="preserve">declare record t:binary-tree 
   ( left? as t:binary-tree, 
     value as item()*, 
     right? as t:binary-tree
   )</eg>
                        <p>A recursive function to walk this tree and enumerate all the values in depth-first order might be written 
                     (again using XQuery syntax) as:</p>
                        <eg xml:space="preserve">declare function t:values($tree as t:binary-tree?) as item()* {
  $tree ! (t:values(?left), ?value, t:values(?right))   
}</eg>
                     </example>
                     <example id="e-arbitrary-tree">
                        <head>An Arbitrary Tree</head>
                        <p>A record used to represent a node in a tree where each node has an arbitrary number
                     of children might be represented (using XQuery syntax) as:</p>
                        <eg xml:space="preserve">declare record t:tree as (value, children as t:tree*);</eg>
                        <p>A function to walk this tree and enumerate all the values in order might be written 
                     as:</p>
                        <eg xml:space="preserve">declare function t:flatten($tree as t:tree) as item()* {
  $tree?value, $tree?children ! t:flatten(.))   
}</eg>
                     </example>
                     <!--<example id="e-mutually-recursive-types">
                  <head>Mutually Recursive Types</head>
                  <p>The usual textbook example of mutually-recursive types is that of a <emph>forest</emph>
                  consisting of a list of <emph>trees</emph>, where each <emph>tree</emph> is a record 
                  comprising a value and a <emph>forest</emph>.
                  As the previous example shows, this structure can be defined straightforwardly in &language; without 
                  recourse to mutual recursion.</p>
                  <p>A more realistic example where mutual recursion is needed is for the schema component model
                     used in <bibref ref="XMLSchema10"/> or <bibref ref="XMLSchema11"/>. Simplifying greatly,
                     the data representing an element declaration in XSD may contain references to a
                     complex type, which in turn will typically contain references to further 
                     element declarations. The structure therefore involves mutual recursion.</p>
                  <p>To model such a structure it is important to make sure that the type is instantiable.
                     The schema component model can contain cycles (for example an element declaration <var>E</var>
                     might have a complex type <var>T</var>, where <var>T</var> has a content model that
                     allows instances of element <var>E</var>. Values are immutable, and either
                     <var>E</var> or <var>T</var> must be created before the other exists, so there
                     is no way that each of them can refer to the other, even if the references
                     are encapsulated in functions.</p>
                  <p>A practical solution to this problem is for the components to refer
                     to each other by name, rather than directly. It will then be necessary,
                     when following references from one component to another, to dereference
                     these names, which can be achieved using a map from names to components.
                     </p>
                  <p>A simplified version of the schema component model might be written (in part) as:</p>
                  <eg>
declare record ElementDeclaration (
   name as xs:NCName,
   targetNamespace? as xs:anyURI,
   typeDefinition as (SimpleTypeDefinition | ComplexTypeDefinition),
   nillable as xs:boolean,
   abstract as xs:boolean
);
declare record SimpleTypeDefinition (
   name? as xs:NCName,
   targetNamespace? as xs:anyURI,
   baseType? as SimpleTypeDefinition,
   variety as enum("atomic", "list", "union"),
   facets as Facet*,
);
declare record ComplexTypeDefinition (
   name? as xs:NCName,
   targetNamespace? as xs:anyURI,
   baseType? as ComplexTypeDefinition,
   derivationMethod as enum("extension", "restriction"),
   contentType as record (
      variety as enum("empty", "simple", "element-only", "mixed"),
      particle? as Particle,
      simpleTypeDefinition? as SimpleTypeDefinition
   )
);
declare record Particle (
   minOccurs as xs:nonNegativeInteger,
   maxOccurs as (xs:positiveInteger | enum("unbounded")),
   term as (ElementDeclaration | Wildcard | Group)
);</eg>

               </example>-->
                  </div5>
               </div4>
               <div4 id="id-array-test">
                  <head>Array Types</head>
                  <p>An <nt def="doc-xpath40-ArrayType">ArrayType<!--$spec = xpath40--></nt> designates an item type that
               either matches all arrays, or that matches arrays whose members
               are constrained to a specific type.</p>
                  <scrap headstyle="show">
                     <prod id="doc-xpath40-ArrayType">
                        <lhs>ArrayType</lhs>
                        <rhs>
                           <nt def="prod-xpath40-AnyArrayType">AnyArrayType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-TypedArrayType">TypedArrayType<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-ArrayType-AnyArrayType">
                        <lhs>AnyArrayType</lhs>
                        <rhs>"array"  "("  "*"  ")"</rhs>
                     </prod>

                     <prod id="doc-xpath40-ArrayType-TypedArrayType">
                        <lhs>TypedArrayType</lhs>
                        <rhs>"array"  "("  <nt def="prod-xpath40-SequenceType">SequenceType<!--$idref_lang_part = xpath40- --></nt>  ")"</rhs>
                     </prod>

                     <prod id="doc-xpath40-ArrayType-SequenceType">
                        <lhs>SequenceType</lhs>
                        <rhs>("empty-sequence"  "("  ")")<br/>|  (<nt def="prod-xpath40-ItemType">ItemType<!--$idref_lang_part = xpath40- --></nt>
                           <nt def="prod-xpath40-OccurrenceIndicator">OccurrenceIndicator<!--$idref_lang_part = xpath40- --></nt>?)</rhs>
                     </prod>
                  </scrap>
                  <p>An <nt def="prod-xpath40-AnyArrayType">AnyArrayType<!--$spec = xpath40--></nt>
                     <code nobreak="false">array(*)</code> matches any array.</p>
                  <p>The <nt def="prod-xpath40-TypedArrayType">TypedArrayType<!--$spec = xpath40--></nt>
                     <code nobreak="false">array(X)</code> matches any array
  in which every array member matches the <nt def="doc-xpath40-SequenceType">SequenceType<!--$spec = xpath40--></nt>
                     <code nobreak="false">X</code>.</p>
                  <p>Examples:</p>
                  <ulist>
                     <item>
                        <p>
                           <code nobreak="false">[ 1, 2 ] instance of array(*)</code> returns <code nobreak="false">true</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">[] instance of array(xs:string)</code> returns <code nobreak="false">true</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">[ "foo" ] instance of array(xs:string)</code> returns <code nobreak="false">true</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">[ "foo" ] instance of array(xs:integer)</code> returns <code nobreak="false">false</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">[ (1, 2), (3, 4) ] instance of array(xs:integer)</code> returns <code nobreak="false">false</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">[ (1, 2), (3, 4) ] instance of array(xs:integer+)</code> returns <code nobreak="false">true</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">[ [ 1, 2 ], [ 3, 4 ] ] instance of array(array(xs:integer+))</code> returns <code nobreak="false">true</code>
                        </p>
                     </item>
                  </ulist>
                  <p>An array also matches certain other <termref def="dt-item-type">item types</termref>, 
                  including:</p>
                  <ulist>
                     <item>
                        <p>
                           <code nobreak="false">item()</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">function(*)</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">function(xs:integer) as item()*</code>
                        </p>
                     </item>
                  </ulist>
                  <p diff="add" at="issue730">An array that matches <code nobreak="false">array(T)</code>
                  also matches the function type <code nobreak="false">function(xs:integer) as T</code>.</p>
                  <note diff="add" at="issue730">
                     <p>To understand this rule, consider the use of an array <code nobreak="false">$A</code> in a function 
                     call <code nobreak="false">$A($I)</code>, which is equivalent to the function call <code nobreak="false">array:get($A, $I)</code>.
                     This function accepts any integer for the argument <code nobreak="false">$I</code>, and the result
                     will either be an instance of <var>T</var>, or an error.</p>
                     <p>The transitivity rules for item type matching mean that if an item <var>A</var>
                     matches a type <var>T</var>, and <var>T</var> is a <termref def="dt-subtype"/> 
                     of <var>U</var>, then <var>A</var> also matches type <var>U</var>. So the fact
                     that an array of strings (<code nobreak="false">array(xs:string)</code>)
                     matches <code nobreak="false">function(xs:integer) as xs:string</code>
                     means that it will also match other function types such as 
                     <code nobreak="false">function(xs:long) as item()*</code>.</p>
                     <p>Furthermore, the rules for
                     <termref def="dt-function-coercion"/> mean that any array 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 an array of type 
                        <code nobreak="false">array(node())</code> can be coerced to a function of
                        type <code nobreak="false">function(xs:integer) as element()</code>; in this situation a type
                        error will occur only if a call on the function actually returns a node
                        that is not an element node.</p>
                  </note>
                  <p diff="del" at="issue730">The function signature of an array
  matching <code nobreak="false">array(X)</code>, treated as a function, is
  <code nobreak="false">function(xs:integer) as X</code>.  It is thus always a subtype of
  <code nobreak="false">function(xs:integer) as item()*</code>
  regardless of the actual member types in the array.  The rules for
                  <termref def="dt-function-coercion">function coercion</termref> mean that any array can be supplied as a value in
  a context where the required type has a more specific return type,
  such as <code nobreak="false">function(xs:integer) as xs:integer</code>, even when the array does
  not match in the sense required to satisfy the <code nobreak="false">instance of</code>
  operator. In such cases, a type error will occur only if an actual
  call on the array (treated as a function) returns a value that is
  not an instance of the required return type.</p>
                  <p>Rules defining whether one array type is a <termref def="dt-subtype"/> of another
                  are given in <specref ref="id-item-subtype-arrays"/>.</p>
               </div4>
            </div3>
            <div3 id="id-jnode-types">
               <head>JNode Types</head>
               <changes>
                  <change issue="2025" PR="2031" date="2025-06-13">
                     JNodes are introduced
                  </change>
               </changes>
               <p>A <nt def="doc-xpath40-JNodeType">JNodeType<!--$spec = xpath40--></nt> matches a <termref def="dt-JNode"/>.</p>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-JNodeType">
                     <lhs>JNodeType</lhs>
                     <rhs>"jnode"  "("  (("*"  |  <nt def="prod-xpath40-JRootSelector">JRootSelector<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-Constant">Constant<!--$idref_lang_part = xpath40- --></nt>)  (","  <nt def="prod-xpath40-SequenceType">SequenceType<!--$idref_lang_part = xpath40- --></nt>)?)?  ")"</rhs>
                  </prod>

                  <prod id="doc-xpath40-JNodeType-JRootSelector">
                     <lhs>JRootSelector</lhs>
                     <rhs>"("  ")"</rhs>
                  </prod>

                  <prod id="doc-xpath40-JNodeType-Constant">
                     <lhs>Constant</lhs>
                     <rhs>
                        <nt def="doc-xpath40-StringLiteral">StringLiteral<!--$idref_lang_part = xpath40- --></nt>  |  ("-"?  <nt def="prod-xpath40-NumericLiteral">NumericLiteral<!--$idref_lang_part = xpath40- --></nt>)  |  <nt def="prod-xpath40-QNameLiteral">QNameLiteral<!--$idref_lang_part = xpath40- --></nt>  |  ("true"  "("  ")")  |  ("false"  "("  ")")</rhs>
                  </prod>

                  <prod id="doc-xpath40-JNodeType-SequenceType">
                     <lhs>SequenceType</lhs>
                     <rhs>("empty-sequence"  "("  ")")<br/>|  (<nt def="prod-xpath40-ItemType">ItemType<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-OccurrenceIndicator">OccurrenceIndicator<!--$idref_lang_part = xpath40- --></nt>?)</rhs>
                  </prod>
               </scrap>
               <p>Specifically:</p>
               <ulist>
                  <item>
                     <p>The forms <code nobreak="false">jnode()</code> and <code nobreak="false">jnode(*)</code> are
                  equivalent, and match any JNode.</p>
                  </item>
                  <item>
                     <p>The first argument constrains the value of the <term>·jkey·</term> property:</p>
                     <ulist>
                        <item>
                           <p>If there are no arguments, the default for the first argument is <code nobreak="false">*</code>.</p>
                        </item>
                        <item>
                           <p>If the first argument is an NCName, this is equivalent to writing the NCName as a string
                     literal by adding quotation marks. For example, <code nobreak="false">jnode(Status)</code> is simply an abbreviation
                     for <code nobreak="false">jnode("Status")</code>.</p>
                        </item>
                        <item>
                           <p>If the first argument is a <nt def="doc-xpath40-Constant">Constant<!--$spec = xpath40--></nt>, then it specifies
                     a value that must match the value of the <term>·jkey·</term> property of the JNode,
                     according to the rules of the <function>fn:atomic-equal</function> function.</p>
                        </item>
                        <item>
                           <p>If the first argument is <code nobreak="false">()</code>, then the <term>·jkey·</term> property
                        must be absent: that is, the JNode must be the root of a JTree.</p>
                        </item>
                        <item>
                           <p>If the first argument is <code nobreak="false">*</code>, then the <term>·jkey·</term> property
                        may take any value, or may be absent.</p>
                        </item>
                     </ulist>
                  </item>
                  <item>
                     <p>The second argument, if present, constrains the <term>·jvalue·</term> property of the JNode:</p>
                     <ulist>
                        <item>
                           <p>If the argument is omitted then there are no constraints on the 
                        <term>·jvalue·</term> property</p>
                        </item>
                        <item>
                           <p>If the argument is a sequence type, then the value of the <term>·jvalue·</term> 
                              property of the JNode must match this sequence type.</p>
                        </item>
                     </ulist>
                  </item>
               </ulist>
               <p>For example:</p>
               <ulist>
                  <item>
                     <p>
                        <code nobreak="false">jnode(*)</code> matches any JNode.</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">jnode(())</code> matches a JNode that is the root of a JTree.</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">jnode((), map(*))</code> matches a JNode that is the root of a JTree 
                        and whose <term>·jvalue·</term> property is an instance of <code nobreak="false">map(*)</code>.</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">jnode("first name")</code> matches any JNode whose <term>·jkey·</term> property
                     is the string <code nobreak="false">"first name"</code>.</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">jnode(surname)</code> matches any JNode whose <term>·jkey·</term> property
                     is the string <code nobreak="false">"surname"</code>.</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">jnode("first name", xs:string)</code> matches any JNode whose <term>·jkey·</term> property
                     is the string <code nobreak="false">"first name"</code> and whose <term>·jvalue·</term> property is an instance of
                     <code nobreak="false">xs:string</code>.</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">jnode(*, array(xs:integer))</code> matches any JNode whose 
                        <term>·jvalue·</term> property is an array of integers.</p>
                  </item>
               </ulist>
            </div3>
            <div3 id="id-generalized-node-types">
               <head>Generalized Node Types</head>
               <changes>
                  <change issue="2025" PR="2031" date="2025-06-13">
                     JNodes are introduced
                  </change>
               </changes>
               <p>A <nt def="doc-xpath40-GNodeType">GNodeType<!--$spec = xpath40--></nt> matches a generalized node (<termref def="dt-GNode"/>):
                  that is, it matches any <termref def="dt-XNode"/>
                  or <xtermref spec="DM40" ref="dt-JNode"/>.</p>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-GNodeType">
                     <lhs>GNodeType</lhs>
                     <rhs>"gnode"  "("  ")"</rhs>
                  </prod>
               </scrap>
               <p>The type <code nobreak="false">gnode()</code> is equivalent to the choice type <code nobreak="false">jnode() | node()</code>.</p>
            </div3>
            <div3 id="id-xs-error">
               <head>The type <code nobreak="false">xs:error</code>
               </head>
               <p>The item type <code nobreak="false">xs:error</code> has an empty value space; 
                  it never appears as a dynamic type or as the content type of a dynamic element or attribute type. 
                  
                  
                  It was defined in XML Schema in the interests of making the type system complete and closed, 
                  and it is also available in XPath 4.0 for similar reasons.</p>
               <note>
                  <p>Even though it cannot occur in an instance, <code nobreak="false">xs:error</code> is a valid type name in a sequence type. The
                     practical uses of <code nobreak="false">xs:error</code> as a sequence type are limited, but they do exist. For instance, an error-handling function that always raises a dynamic error 
                     never returns a value, so <code nobreak="false">xs:error</code> is a good choice for the return type of the function.</p>
                  <p>The semantics of <code nobreak="false">xs:error</code> are well defined as a consequence of the fact that <code nobreak="false">xs:error</code> is defined as a union type with
                     no member types. For example:</p>
                  <ulist>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">$x instance of xs:error</code> always returns <code nobreak="false">false</code>, regardless of the value of <code nobreak="false">$x</code>.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">$x cast as xs:error</code> fails dynamically with error <xerrorref spec="FO40" class="RG" code="0001"/>,  regardless of the value of <code nobreak="false">$x</code>.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">$x cast as xs:error?</code> raises a <termref def="dt-dynamic-error">dynamic error</termref>
                           <xerrorref spec="FO40" class="RG" code="0001"/> if <code nobreak="false">exists($x)</code> returns <code nobreak="false">true</code>, and evaluates to the empty sequence if <code nobreak="false">empty($x)</code> returns <code nobreak="false">true</code>.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">xs:error($x)</code> has the same semantics as <code nobreak="false">$x cast as xs:error?</code> (see the previous bullet point)</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">$x castable as xs:error</code> evaluates to <code nobreak="false">false</code>, regardless of the value of <code nobreak="false">$x</code>.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">$x treat as xs:error</code>  raises a <termref def="dt-type-error"/>
                           <errorref code="0050" class="DY"/>, regardless of the value of <code nobreak="false">$x</code>.</p>
                     </item>
                  </ulist>
                  <p>All of the above examples assume that <code nobreak="false">$x</code> is actually evaluated. The rules specified in <specref ref="id-errors-and-opt"/> permit an implementation to avoid evaluating <code nobreak="false">$x</code> if the result of the query does not depend upon the value of <code nobreak="false">$x</code> and thus to avoid raising an error.</p>
               </note>
            </div3>
         </div2>
         <div2 id="id-sequencetype-subtype">
            <head>Subtype Relationships</head>
            <changes>
               <change issue="196" PR="202" date="2022-10-25">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.</change>
            </changes>
            <p diff="chg" at="B">
               <termdef term="subtype" id="dt-subtype">Given two 
               <termref def="dt-sequence-type">sequence types</termref>
               or <termref def="dt-item-type">item types</termref>, the rules in this section determine if one 
               is a <term>subtype</term> of the other. If a type <var>A</var> is a subtype of type <var>B</var>,
               it follows that every value matched by <var>A</var> is also matched by <var>B</var>.</termdef>
            </p>
            <note diff="add" at="B">
               <p>The relationship <code nobreak="false">subtype(A, A)</code> is always true:
               every type is a subtype of itself.</p>
            </note>
            <note diff="add" at="B">
               <p>The converse is not necessarily true: we cannot infer that 
               if every value matched by <var>A</var> is also matched by <var>B</var>, then 
               <var>A</var> is a subtype of type <var>B</var>. For example, <var>A</var> might be
            defined as the set of strings matching the regular expression <code nobreak="false">[A-Z]*</code>, while <var>B</var>
            is the set of strings matching the regular expression <code nobreak="false">[A-Za-z]*</code>; no subtype
            relationship holds between these types.</p>
            </note>
            <p diff="chg" at="B">The rules for deciding whether one <termref def="dt-sequence-type"/> is a subtype
               of another are given in <specref ref="id-seqtype-subtype"/>. The rules for deciding whether
               one <termref def="dt-item-type"/> is a subtype of another are given in <specref ref="id-itemtype-subtype"/>.</p>
            <note diff="add" at="B">
               <p>The subtype relationship is not acyclic. There are cases where <code nobreak="false">subtype(A, B)</code> and
               <code nobreak="false">subtype(B, A)</code> are both true. This implies that <var>A</var> and <var>B</var>
               have the same value space, but they can still be different types. For example this applies when <var>A</var>
               is a union type with member types <code nobreak="false">xs:string</code> and <code nobreak="false">xs:integer</code>, while 
               <var>B</var> is a union type with member types <code nobreak="false">xs:integer</code> and <code nobreak="false">xs:string</code>.
               These are different types (<code nobreak="false">"23" cast as A</code> produces a string, while <code nobreak="false">"23" cast as B</code>
               produces an integer, because casting is attempted to each member type in order) but both types have the same value space.
            </p>
            </note>
            <div3 id="id-seqtype-subtype">
               <head>Subtypes of Sequence Types</head>
               <p>We use the notation <code nobreak="false">A ⊑ B</code>, or <code nobreak="false">subtype(A, B)</code> to indicate that
                  a <termref def="dt-sequence-type"/>
                  <code nobreak="false">A</code> is a <termref def="dt-subtype"/> of a sequence type <code nobreak="false">B</code>.
               This section defines the rules for deciding whether any two sequence types have this relationship.</p>
               <p>To define the rules, we divide sequence types into six categories:</p>
               <ulist>
                  <item>
                     <p>The category <code nobreak="false">empty</code> includes the sequence types <code nobreak="false">empty-sequence()</code>,
                   <code nobreak="false">xs:error*</code> and <code nobreak="false">xs:error?</code>. All these sequence types
                  match the empty sequence as their only instance.</p>
                  </item>
                  <item>
                     <p>The category <code nobreak="false">void</code> includes the sequence types <code nobreak="false">xs:error</code> and <code nobreak="false">xs:error+</code>,
                  which have no instances (not even the empty sequence).</p>
                  </item>
                  <item>
                     <p>The categories <code nobreak="false">X?</code>, <code nobreak="false">X*</code>, <code nobreak="false">X</code> and <code nobreak="false">X+</code> includes all sequence types 
                     having an item type <code nobreak="false">X</code> other than <code nobreak="false">xs:error</code>, together with an occurrence indicator of 
                     <code nobreak="false">?</code> (zero or more), <code nobreak="false">*</code> (one or more), absent (exactly one), or <code nobreak="false">+</code> (one or more)
                     respectively. We use the notation <var>X/i</var> to indicate the item type of such a sequence type.</p>
                  </item>
               </ulist>
               <p>The judgement <code nobreak="false">A ⊑ B</code> is then determined by the categories of the two sequence types, as defined
               in the table below. In many cases this depends on the relationship between the item types of <code nobreak="false">A</code>
                  and <code nobreak="false">B</code>. This is denoted using the notation <code nobreak="false">
                     <var>A/i</var> ⊆ <var>B/i</var>
                  </code>, 
                  as defined in <specref ref="id-itemtype-subtype"/>.</p>
               <table role="medium">
                  <tbody>
                     <tr>
                        <th rowspan="2" colspan="2"/>
                        <th colspan="6" rowspan="1">
                           <termref def="dt-sequence-type">Sequence type</termref>
                           <var>B</var>
                        </th>
                     </tr>
                     <tr>
                        <th rowspan="1" colspan="1">
                           <code nobreak="false">empty</code>
                        </th>
                        <th rowspan="1" colspan="1">
                           <code nobreak="false">
                              <var>B/i</var>?</code>
                        </th>
                        <th rowspan="1" colspan="1">
                           <code nobreak="false">
                              <var>B/i</var>*</code>
                        </th>
                        <th rowspan="1" colspan="1">
                           <code nobreak="false">
                              <var>B/i</var>
                           </code>
                        </th>
                        <th rowspan="1" colspan="1">
                           <code nobreak="false">
                              <var>B/i</var>+</code>
                        </th>
                        <th rowspan="1" colspan="1">
                           <code nobreak="false">void</code>
                        </th>
                     </tr>
                     <tr>
                        <th rowspan="6" colspan="1">
                           <termref def="dt-sequence-type">Sequence type</termref>
                           <var>A</var>
                        </th>
                        <th rowspan="1" colspan="1">
                           <code nobreak="false">empty</code>
                        </th>
                        <td rowspan="1" colspan="1">true</td>
                        <td rowspan="1" colspan="1">true</td>
                        <td rowspan="1" colspan="1">true</td>
                        <td rowspan="1" colspan="1">false</td>
                        <td rowspan="1" colspan="1">false</td>
                        <td rowspan="1" colspan="1">false</td>
                     </tr>
                     <tr>
                        <th rowspan="1" colspan="1">
                           <code nobreak="false">
                              <var>A/i</var>?</code>
                        </th>
                        <td rowspan="1" colspan="1">false</td>
                        <td rowspan="1" colspan="1">
                           <code nobreak="false">
                              <var>A/i</var> ⊆ <var>B/i</var>
                           </code>
                        </td>
                        <td rowspan="1" colspan="1">
                           <code nobreak="false">
                              <var>A/i</var> ⊆ <var>B/i</var>
                           </code>
                        </td>
                        <td rowspan="1" colspan="1">false</td>
                        <td rowspan="1" colspan="1">false</td>
                        <td rowspan="1" colspan="1">false</td>
                     </tr>
                     <tr>
                        <th rowspan="1" colspan="1">
                           <code nobreak="false">
                              <var>A/i</var>*</code>
                        </th>
                        <td rowspan="1" colspan="1">false</td>
                        <td rowspan="1" colspan="1">false</td>
                        <td rowspan="1" colspan="1">
                           <code nobreak="false">
                              <var>A/i</var> ⊆ <var>B/i</var>
                           </code>
                        </td>
                        <td rowspan="1" colspan="1">false</td>
                        <td rowspan="1" colspan="1">false</td>
                        <td rowspan="1" colspan="1">false</td>
                     </tr>
                     <tr>
                        <th rowspan="1" colspan="1">
                           <code nobreak="false">
                              <var>A/i</var>
                           </code>
                        </th>
                        <td rowspan="1" colspan="1">false</td>
                        <td rowspan="1" colspan="1">
                           <code nobreak="false">
                              <var>A/i</var> ⊆ <var>B/i</var>
                           </code>
                        </td>
                        <td rowspan="1" colspan="1">
                           <code nobreak="false">
                              <var>A/i</var> ⊆ <var>B/i</var>
                           </code>
                        </td>
                        <td rowspan="1" colspan="1">
                           <code nobreak="false">
                              <var>A/i</var> ⊆ <var>B/i</var>
                           </code>
                        </td>
                        <td rowspan="1" colspan="1">
                           <code nobreak="false">
                              <var>A/i</var> ⊆ <var>B/i</var>
                           </code>
                        </td>
                        <td rowspan="1" colspan="1">false</td>
                     </tr>
                     <tr>
                        <th rowspan="1" colspan="1">
                           <code nobreak="false">
                              <var>A/i</var>+</code>
                        </th>
                        <td rowspan="1" colspan="1">false</td>
                        <td rowspan="1" colspan="1">false</td>
                        <td rowspan="1" colspan="1">
                           <code nobreak="false">
                              <var>A/i</var> ⊆ <var>B/i</var>
                           </code>
                        </td>
                        <td rowspan="1" colspan="1">false</td>
                        <td rowspan="1" colspan="1">
                           <code nobreak="false">
                              <var>A/i</var> ⊆ <var>B/i</var>
                           </code>
                        </td>
                        <td rowspan="1" colspan="1">false</td>
                     </tr>
                     <tr>
                        <th rowspan="1" colspan="1">
                           <code nobreak="false">void</code>
                        </th>
                        <td rowspan="1" colspan="1">true</td>
                        <td rowspan="1" colspan="1">true</td>
                        <td rowspan="1" colspan="1">true</td>
                        <td rowspan="1" colspan="1">true</td>
                        <td rowspan="1" colspan="1">true</td>
                        <td rowspan="1" colspan="1">true</td>
                     </tr>
                  </tbody>
               </table>
               <!--   <p>
                  <code>xs:error+</code> is treated the same way as <code>xs:error</code> in the above table. 
                  <code>xs:error?</code> and <code>xs:error*</code> are treated the same way as <code>empty-sequence()</code>.</p>-->
            </div3>
            <div3 id="id-itemtype-subtype">
               <head>Subtypes of Item Types</head>
               <p>We use the notation <code nobreak="false">A ⊆ B</code>, or <code nobreak="false">itemtype-subtype(A, B)</code> to indicate that
                  an <termref def="dt-item-type"/>
                  <code nobreak="false">A</code> is a <termref def="dt-subtype"/> of an item type <code nobreak="false">B</code>.
                  This section defines the rules for deciding whether any two item types have this relationship.</p>
               <p diff="chg" at="Issue451">The rules in this section apply to 
                  <termref def="dt-item-type">item types</termref>, not to 
                  <termref def="dt-item-type-designator">item type designators</termref>.
                  For example, if the name <code nobreak="false">STR</code> has been defined in the
                  static context as a <termref def="dt-named-item-type"/> referring to the type <code nobreak="false">xs:string</code>,
                  then anything said here about the type <code nobreak="false">xs:string</code> applies equally
                  whether it is designated as <code nobreak="false">xs:string</code> or as <code nobreak="false">STR</code>,
                  or indeed as the parenthesized forms <code nobreak="false">(xs:string)</code> or
                 <code nobreak="false">(STR)</code>.</p>
               <p diff="chg" at="issue295">References to <termref def="dt-named-item-type">named item types</termref> 
                  are handled as described in <specref ref="id-itemtype-subtype-aliases"/>.</p>
               <p>The relationship <code nobreak="false">A ⊆ B</code> is true
               if and only if at least one of the conditions listed in the following subsections applies:</p>
               <div4 id="id-item-subtype-general">
                  <head>General Subtyping Rules</head>
                  <p>Given <termref def="dt-item-type">item types</termref>
                     <var>A</var> and <var>B</var>, 
                     <code nobreak="false">
                        <var>A</var> ⊆ <var>B</var>
                     </code> is true if any of the following apply:</p>
                  <olist>
                     <item diff="chg" at="A">
                        <p>
                           <var>A</var> is <code nobreak="false">xs:error</code>.</p>
                     </item>
                     <item>
                        <p>
                           <var>B</var> is <code nobreak="false">item()</code>.</p>
                     </item>
                     <item diff="chg" at="A">
                        <p>
                           <var>A</var> and <var>B</var> are the same <termref def="dt-item-type"/>.</p>
                     </item>
                     <item diff="chg" at="A">
                        <p>There is an <termref def="dt-item-type"/>
                           <var>X</var> such that <code nobreak="false">
                              <var>A</var> ⊆ <var>X</var>
                           </code>
                              and <code nobreak="false">
                              <var>X</var> ⊆ <var>B</var>
                           </code>. (This is referred to below as the <term>transitivity rule</term>).</p>
                     </item>
                  </olist>
                  <note>
                     <p>The first rule is technically redundant: it is implied by the second rule in <specref ref="id-item-subtype-atomic"/>.
                     The type <code nobreak="false">xs:error</code> is defined as a union type with no member types; therefore it is automatically true that
                        every member type <var>T</var> satisfies <code nobreak="false">
                           <var>T</var> ⊆ <var>B</var>
                        </code>.</p>
                  </note>
               </div4>
               <div4 id="id-item-subtype-choice">
                  <head>Subtyping of Choice Item Types</head>
                  <p>The following rules determine whether <code nobreak="false">
                        <var>A</var> ⊆ <var>B</var>
                     </code> is true in the
                  case where either <var>A</var> or <var>B</var> or both is a <termref def="dt-choice-item-type"/>.</p>
                  <p>Firstly, if one of the operands is <emph>not</emph> a choice item type, then:</p>
                  <ulist>
                     <item>
                        <p>If it is an abstract item type that cannot be extended with new immediate subtypes,
                           then it is treated as being equivalent to a choice of its concrete subtypes. Specifically:</p>
                        <ulist>
                           <item>
                              <p>
                                 <code nobreak="false">xs:anyAtomicType</code> is treated as a choice of the 19 XSD primitive
                           atomic types (<code nobreak="false">xs:string</code>, <code nobreak="false">xs:boolean</code>, etc), plus
                           <code nobreak="false">xs:untypedAtomic</code>;</p>
                           </item>
                           <item>
                              <p>
                                 <code nobreak="false">node()</code> is treated as <code nobreak="false">(document-node() | element() | attribute() 
                                    | text() | comment() | processing-instruction() | namespace-node())</code>;</p>
                           </item>
                           <item>
                              <p>
                                 <code nobreak="false">gnode()</code> is treated as <code nobreak="false">(node() | jnode())</code>, where <code nobreak="false">node()</code>
                           is then further expanded as above;</p>
                           </item>
                           <item>
                              <p>
                                 <code nobreak="false">item()</code> is treated as <code nobreak="false">(gnode() | xs:anyAtomicType | function(*))</code>,
                           where <code nobreak="false">gnode()</code> and <code nobreak="false">xs:anyAtomicType</code> are then expanded as above.</p>
                           </item>
                        </ulist>
                     </item>
                     <item>
                        <p>Otherwise, it is treated as a choice item type with a single member type.</p>
                     </item>
                  </ulist>
                  <p>Applying these rules means that both types are now choice item types. The rule is then:</p>
                  <p>
                     <code nobreak="false">
                        <var>A</var> ⊆ <var>B</var>
                     </code> is true if for every member type <var>a</var> in 
                  <var>A</var>, there is a member type <var>b</var> in <var>B</var> such that <code nobreak="false">
                        <var>a</var> ⊆ <var>b</var>
                     </code>.</p>
                  <p>For example:</p>
                  <ulist>
                     <item>
                        <p>
                           <code nobreak="false">(xs:int | xs:long)</code> is a subtype of <code nobreak="false">(xs:decimal | xs:date)</code>
                  because both <code nobreak="false">xs:int</code> and <code nobreak="false">xs:long</code> are subtypes of <code nobreak="false">xs:decimal</code>.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">node()</code> is a subtype of <code nobreak="false">(element() | attribute() | text() |
                     comment() | processing-instruction() | document-node() | jnode())</code> because <code nobreak="false">node()</code>
                     is an abstract type that is expanded to a choice of the seven kinds of XNode.</p>
                     </item>
                  </ulist>
                  <note>
                     <p>Because an <termref def="dt-enumeration-type"/> is defined as a choice type
                        of singleton enumerations, these
                     rules have the consequence, for example, that <code nobreak="false">enum("A", "B")</code> is a subtype
                     of <code nobreak="false">enum("A", "B", "C")</code>.</p>
                  </note>
                  <note>
                     <p>The type <code nobreak="false">xs:int</code> is not a subtype of <code nobreak="false">(xs:negativeInteger | xs:nonNegativeInteger)</code>,
                     because it does not satisfy this rule. This is despite the fact that the value space of <code nobreak="false">xs:int</code>
                     is a subset of the value space of <code nobreak="false">(xs:negativeInteger | xs:nonNegativeInteger)</code>.</p>
                  </note>
               </div4>
               <div4 id="id-item-subtype-atomic">
                  <head>Subtyping of Atomic and Union Types</head>
                  <p>Given item types <var>A</var> and <var>B</var>, <code nobreak="false">
                        <var>A</var> ⊆ <var>B</var>
                     </code> is true if any of the following apply:</p>
                  <olist>
                     <item>
                        <p>
                           <var>A</var> and <var>B</var> are <termref def="dt-generalized-atomic-type">generalized atomic types</termref>, 
                              and <var>A</var>
                           <termref def="dt-derives-from"/>
                           <var>B</var>.</p>
                        <example diff="add" at="B">
                           <head>Examples:</head>
                           <ulist>
                              <item>
                                 <p>
                                    <code nobreak="false">xs:integer ⊆ xs:decimal</code> because <code nobreak="false">xs:integer</code> is derived
                                 by restriction from <code nobreak="false">xs:decimal</code>.</p>
                              </item>
                              <item>
                                 <p>
                                    <code nobreak="false">xs:decimal ⊆ xs:numeric</code> because <code nobreak="false">xs:numeric</code> is a pure union
                                    type that includes <code nobreak="false">xs:decimal</code> as a member type.</p>
                              </item>
                           </ulist>
                        </example>
                     </item>
                     <item>
                        <p>
                           <var>A</var> is a <termref def="dt-pure-union-type"/>, 
                              and every type <var>T</var> in the transitive membership of <var>A</var>
                              satisfies <code nobreak="false">
                              <var>T</var> ⊆ <var>B</var>
                           </code>.</p>
                        <example diff="add" at="B">
                           <head>Examples:</head>
                           <ulist>
                              <item>
                                 <p>
                                    <code nobreak="false">(xs:short | xs:long) ⊆ xs:integer</code>
                                    because <code nobreak="false">xs:short ⊆ xs:integer</code> and <code nobreak="false">xs:long ⊆ xs:integer</code>.</p>
                              </item>
                              <item>
                                 <p>
                                    <code nobreak="false">(P | Q) ⊆ (P | Q | R)</code>
                                 because <code nobreak="false">P ⊆ (P | Q | R)</code> and <code nobreak="false">Q ⊆ (P | Q | R)</code>.</p>
                              </item>
                              <item>
                                 <p>
                                    <code nobreak="false">enum("red", "green") ⊆ xs:string</code> because the 
                                    enumeration type <code nobreak="false">enum("red") ⊆ xs:string</code> 
                                    and <code nobreak="false">enum("green") ⊆ xs:string</code>.</p>
                              </item>
                              <item>
                                 <p>
                                    <code nobreak="false">enum("red", "green") ⊆ enum("red", "green", "blue")</code> because 
                                    <code nobreak="false">enum("red") ⊆ enum("red", "green", "blue")</code> and 
                                    <code nobreak="false">enum("green") ⊆ enum("red", "green", "blue")</code>.</p>
                              </item>
                              <item>
                                 <p>
                                    <code nobreak="false">enum("red", "green", "blue") ⊆ (enum("red", "green") | enum("blue"))</code> because 
                                    each of the types <code nobreak="false">enum("red")</code>, <code nobreak="false">enum("green")</code>, and <code nobreak="false">enum("blue")</code>
                                    is a subtype of one of the two members of the union type.</p>
                              </item>
                           </ulist>
                        </example>
                        <!--<note><p>This rule applies both when <code>A</code> is a schema-defined union type
                              and when it is a <termref def="dt-local-union-type"/>; in addition it
                              applies when <code>A</code> is an enumeration type with multiple enumerated values,
                              which is defined to be equivalent to a union type.
                           </p></note>-->
                     </item>
                  </olist>
               </div4>
               <div4 id="id-item-subtype-enum">
                  <head>Subtyping of Enumeration Types</head>
                  <p>If <var>A</var> is a <termref def="dt-singleton-enumeration-type"/>
                     permitting the string value <var>V</var>, then <code nobreak="false">
                        <var>A</var> ⊆ <var>B</var>
                     </code> 
                     is true if <var>B</var> is <code nobreak="false">xs:string</code>.</p>
                  <note>
                     <p>Because a non-singleton enumeration type is defined as a choice type,
                  <code nobreak="false">
                           <var>A</var> ⊆ <var>B</var>
                        </code> also holds if <var>A</var> is
                  <code nobreak="false">enum("red")</code> and <var>B</var> is <code nobreak="false">enum("red", "green")</code>.
                  See <specref ref="id-item-subtype-choice"/>.</p>
                  </note>
                  <note>
                     <p>The type <code nobreak="false">enum("red", "green")</code> is not a subtype
                  of <code nobreak="false">xs:NCName</code>, despite the fact that all the enumerated values
                  are valid <code nobreak="false">NCName</code>s. This is because instances of <code nobreak="false">xs:NCName</code>
                  must have a type annotation of <code nobreak="false">xs:NCName</code> or a subtype thereof,
                  whereas instances of <code nobreak="false">enum("red", "green")</code> are not subject to this
                  constraint.</p>
                  </note>
                  <note>
                     <p>A type <var>T</var> derived by restriction from <code nobreak="false">xs:string</code>,
                  for example a type with the facet <code nobreak="false">length="0"</code> (which permits
                  only the zero-length string), is not a subtype of any enumeration type,
                  even if every string in the value space of <var>T</var> is an instance of
                  the enumeration type.</p>
                  </note>
               </div4>
               <div4 id="id-item-subtype-nodes">
                  <head>Subtyping of Node Types</head>
                  <p>The following subsections describe the subtype relationships
                  among node types.</p>
                  <div5 id="id-item-subtype-nodes-general">
                     <head>Subtyping Nodes: General Rules</head>
                     <p>Given item types <var>A</var> and <var>B</var>, <code nobreak="false">
                           <var>A</var> ⊆ <var>B</var>
                        </code> is true if any of the following apply:</p>
                     <olist>
                        <item>
                           <p>
                              <var>A</var> is an <nt def="prod-xpath40-XNodeType"><!--$spec = xpath40--></nt> and <var>B</var> is <code nobreak="false">node()</code>.</p>
                           <example>
                              <head>Example:</head>
                              <p>
                                 <code nobreak="false">comment() ⊆ node()</code>
                              </p>
                           </example>
                        </item>
                        <item>
                           <p>
                              <var>A</var> is <code nobreak="false">processing-instruction(<var>N</var>)</code> for any name <var>N</var>,
                              and <var>B</var> is <code nobreak="false">processing-instruction()</code>.</p>
                           <example>
                              <head>Example:</head>
                              <p>
                                 <code nobreak="false">processing-instruction('pi') ⊆ processing-instruction()</code>
                              </p>
                           </example>
                        </item>
                        <item>
                           <p>
                              <var>A</var> is a <nt def="doc-xpath40-JNodeType">JNodeType<!--$spec = xpath40--></nt> and <var>B</var> is a <nt def="doc-xpath40-GNodeType">GNodeType<!--$spec = xpath40--></nt>.</p>
                        </item>
                        <item>
                           <p>
                              <var>A</var> is a <nt def="doc-xpath40-NodeTest">NodeTest<!--$spec = xpath40--></nt> and <var>B</var> is a <nt def="doc-xpath40-GNodeType">GNodeType<!--$spec = xpath40--></nt>
                           </p>
                        </item>
                     </olist>
                  </div5>
                  <div5 id="id-item-subtype-documents">
                     <head>Subtyping Nodes: Document Nodes</head>
                     <changes>
                        <change issue="1624" PR="1898" date="2025-04-07">The rules for subtyping of document node types have been refined.</change>
                     </changes>
                     <p>Given item types <var>A</var> and <var>B</var>, <code nobreak="false">
                           <var>A</var> ⊆ <var>B</var>
                        </code> 
                     is true if any of the following rules apply.</p>
                     <p>These rules apply after expanding <code nobreak="false">document-node(<var>N</var>)</code>, where <var>N</var>
                  is a <nt def="prod-xpath40-NameTestUnion">NameTestUnion<!--$spec = xpath40--></nt>, to the equivalent 
                     <code nobreak="false">document-node(element(<var>N</var>))</code>.</p>
                     <olist>
                        <item>
                           <p>
                              <var>A</var> is <code nobreak="false">document-node(<var>E</var>)</code> for any <var>E</var>,
                              and <var>B</var> is <code nobreak="false">document-node()</code>.</p>
                           <example>
                              <head>Examples:</head>
                              <p>
                                 <code nobreak="false">document-node(element(chap)) ⊆ document-node()</code>
                              </p>
                              <p>
                                 <code nobreak="false">document-node(*) ⊆ document-node()</code>
                              </p>
                           </example>
                        </item>
                        <item>
                           <p>All the following are true:</p>
                           <olist>
                              <item>
                                 <p>
                                    <var>A</var> is <code nobreak="false">document-node(<var>A/e</var>)</code>
                                 </p>
                              </item>
                              <item>
                                 <p>
                                    <var>B</var> is <code nobreak="false">document-node(<var>B/e</var>)</code>
                                 </p>
                              </item>
                              <item>
                                 <p>
                                    <code nobreak="false">
                                       <var>A/e</var> ⊆ <var>B/e</var>
                                    </code>
                                 </p>
                              </item>
                           </olist>
                           <example>
                              <head>Examples:</head>
                              <p>
                                 <code nobreak="false">document-node(element(title)) ⊆ document-node(element(*))</code>.</p>
                              <p>
                                 <code nobreak="false">document-node(title) ⊆ document-node(*)</code>.</p>
                           </example>
                        </item>
                        <item>
                           <p>
                              <var>A</var> is <code nobreak="false">document-node(element(<var>A/1</var>|<var>A/2</var>|..., <var>T</var>))</code> 
                              (where <var>T</var> may be absent),
                           and for each <var>A/n</var>, <code nobreak="false">document-node(element(<var>A/n</var>, <var>T</var>)) ⊆ <var>B</var>
                              </code>.</p>
                           <example>
                              <head>Examples:</head>
                              <ulist>
                                 <item>
                                    <p>
                                       <code nobreak="false">document-node(a|b) ⊆ document-node(a) | document-node(b)</code>
                                    </p>
                                 </item>
                                 <item>
                                    <p>
                                       <code nobreak="false">document-node(a|b) ⊆ document-node(a|b|c)</code>
                                    </p>
                                 </item>
                              </ulist>
                           </example>
                        </item>
                     </olist>
                  </div5>
                  <div5 id="id-item-subtype-elements">
                     <head>Subtyping Nodes: Elements</head>
                     <changes>
                        <change issue="2201" PR="2202" date="2025-09-23">The type <code nobreak="false">schema-element(N)</code> is now defined
                     to be a subtype of <code nobreak="false">element()</code> and of various other element tests.</change>
                     </changes>
                     <p diff="chg" at="Issue23">
                        <termdef id="dt-wildcard-matches" term="wildcard-matches">In these rules, if <var>MU</var> and <var>NU</var> 
                     are <nt def="prod-xpath40-NameTestUnion">NameTestUnions<!--$spec = xpath40--></nt>, 
                     then <var>MU</var>
                           <term>wildcard-matches</term>
                           <var>NU</var> is true if every name that matches <var>MU</var>
                     also matches <var>NU</var>.</termdef>
                     </p>
                     <p diff="chg" at="Issue23">More specifically, this is the case if for every <nt def="prod-xpath40-NameTest">NameTest<!--$spec = xpath40--></nt>
                        <var>M</var>
                     in <var>MU</var> there is a <nt def="prod-xpath40-NameTest">NameTest<!--$spec = xpath40--></nt>
                        <var>N</var> in <var>NU</var>
                     where at least one of the following applies:</p>
                     <olist>
                        <item>
                           <p>
                              <var>M</var> and <var>N</var> are the same <code nobreak="false">NameTest</code>.</p>
                        </item>
                        <item>
                           <p>
                              <var>M</var> is an <code nobreak="false">EQName</code> and <var>N</var> is a 
                        <nt def="prod-xpath40-Wildcard">Wildcard<!--$spec = xpath40--></nt> that matches <var>M</var>.</p>
                        </item>
                        <item>
                           <p>
                              <var>N</var> is the <nt def="prod-xpath40-Wildcard">Wildcard<!--$spec = xpath40--></nt>
                              <code nobreak="false">*</code>.</p>
                        </item>
                     </olist>
                     <p>Given item types <var>A</var> and <var>B</var>, <code nobreak="false">
                           <var>A</var> ⊆ <var>B</var>
                        </code> 
                     is true if any of the following apply.</p>
                     <olist>
                        <item>
                           <p>
                              <var>A</var> is an <nt def="doc-xpath40-ElementNodeType"><!--$spec = xpath40--></nt> 
                           or <nt def="doc-xpath40-SchemaElementNodeType"><!--$spec = xpath40--></nt> and
                           <var>B</var> is either <code nobreak="false">element()</code> or <code nobreak="false">element(*)</code>
                           </p>
                        </item>
                        <item>
                           <p>All the following are true:</p>
                           <olist>
                              <item>
                                 <p>
                                    <var>A</var> is either <code nobreak="false">element(<var>A/n</var>)</code> or <code nobreak="false">element(<var>A/n</var>, <var>T</var>)</code>  
                                 or <code nobreak="false">element(<var>A/n</var>, <var>T</var>?)</code> for any type <var>T</var>
                                 </p>
                              </item>
                              <item>
                                 <p>
                                    <var>B</var> is either <code nobreak="false">element(<var>B/n</var>)</code> or <code nobreak="false">element(<var>B/n</var>, xs:anyType?)</code>
                                 </p>
                              </item>
                              <item>
                                 <p>
                                    <var>A/n</var>
                                    <termref def="dt-wildcard-matches"/>
                                    <var>B/n</var>
                                 </p>
                              </item>
                           </olist>
                           <example>
                              <head>Examples:</head>
                              <ulist>
                                 <item>
                                    <p>
                                       <code nobreak="false">element(title) ⊆ element(*)</code>
                                    </p>
                                 </item>
                                 <item>
                                    <p>
                                       <code nobreak="false">element(title, xs:string) ⊆ element(*)</code>
                                    </p>
                                 </item>
                                 <item diff="add" at="Issue23">
                                    <p>
                                       <code nobreak="false">element(title|heading, xs:string) ⊆ element(*)</code>
                                    </p>
                                 </item>
                                 <item diff="add" at="Issue23">
                                    <p>
                                       <code nobreak="false">element(title, xs:string) ⊆ element(title|heading)</code>
                                    </p>
                                 </item>
                                 <item>
                                    <p>
                                       <code nobreak="false">element(title, xs:string?) ⊆ element(*)</code>
                                    </p>
                                 </item>
                                 <item diff="add" at="Issue23">
                                    <p>
                                       <code nobreak="false">element(title|heading, xs:string) ⊆ element(*)</code>
                                    </p>
                                 </item>
                                 <item>
                                    <p>
                                       <code nobreak="false">element(title) ⊆ element(title, xs:anyType?)</code>
                                    </p>
                                 </item>
                                 <item>
                                    <p>
                                       <code nobreak="false">element(title, xs:integer) ⊆ element(title|heading, xs:anyType?)</code>
                                    </p>
                                 </item>
                                 <item>
                                    <p>
                                       <code nobreak="false">element(title, xs:string?) ⊆ element(title, xs:anyType?)</code>
                                    </p>
                                 </item>
                                 <item diff="add" at="Issue23">
                                    <p>
                                       <code nobreak="false">element(my:title|your:title) ⊆ element(*:title)</code>
                                    </p>
                                 </item>
                                 <item diff="add" at="Issue23">
                                    <p>
                                       <code nobreak="false">element(my:title|my:heading) ⊆ element(my:*)</code>
                                    </p>
                                 </item>
                              </ulist>
                           </example>
                        </item>
                        <item>
                           <p>All the following are true:</p>
                           <olist>
                              <item>
                                 <p>
                                    <var>A</var> is <code nobreak="false">element(<var>A/n</var>, <var>A/t</var>)</code>.</p>
                              </item>
                              <item>
                                 <p>
                                    <var>B</var> is <code nobreak="false">element(<var>B/n</var>, <var>B/t</var>)</code>.</p>
                              </item>
                              <item>
                                 <p>
                                    <var>A/n</var>
                                    <termref def="dt-wildcard-matches"/>
                                    <var>B/n</var>.</p>
                              </item>
                              <item>
                                 <p>
                                    <var>A/t</var>
                                    <termref def="dt-derives-from"/>
                                    <var>B/t</var>.</p>
                              </item>
                           </olist>
                           <example>
                              <head>Examples:</head>
                              <ulist>
                                 <item>
                                    <p>
                                       <code nobreak="false">element(size, xs:integer) ⊆ element(size, xs:decimal)</code>
                                    </p>
                                 </item>
                                 <item diff="add" at="Issue23">
                                    <p>
                                       <code nobreak="false">element(size, xs:integer) ⊆ element(size|größe, xs:decimal)</code>
                                    </p>
                                 </item>
                                 <item>
                                    <p>
                                       <code nobreak="false">element(size, xs:integer) ⊆ element(*, xs:decimal)</code>
                                    </p>
                                 </item>
                                 <item>
                                    <p>
                                       <code nobreak="false">element(*, xs:integer) ⊆ element(*, xs:decimal)</code>
                                    </p>
                                 </item>
                                 <item>
                                    <p>
                                       <code nobreak="false">element(my:*, xs:integer) ⊆ element(*, xs:decimal)</code>
                                    </p>
                                 </item>
                              </ulist>
                           </example>
                        </item>
                        <item>
                           <p>All the following are true:</p>
                           <olist>
                              <item>
                                 <p>
                                    <var>A</var> is either <code nobreak="false">element(<var>A/n</var>, <var>A/t</var>)</code> or 
                                 <code nobreak="false">element(<var>A/n</var>, <var>A/t</var>?)</code>
                                 </p>
                              </item>
                              <item>
                                 <p>
                                    <var>B</var> is <code nobreak="false">element(<var>B/n</var>, <var>B/t</var>?)</code>
                                 </p>
                              </item>
                              <item>
                                 <p>
                                    <var>A/n</var>
                                    <termref def="dt-wildcard-matches"/>
                                    <var>B/n</var>
                                 </p>
                              </item>
                              <item>
                                 <p>
                                    <var>A/t</var>
                                    <termref def="dt-derives-from"/>
                                    <var>B/t</var>.</p>
                              </item>
                           </olist>
                           <example>
                              <head>Examples:</head>
                              <ulist>
                                 <item>
                                    <p>
                                       <code nobreak="false">element(size, xs:integer) ⊆ element(size, xs:decimal?)</code>
                                    </p>
                                 </item>
                                 <item>
                                    <p>
                                       <code nobreak="false">element(size, xs:integer?) ⊆ element(*, xs:decimal?)</code>
                                    </p>
                                 </item>
                                 <item>
                                    <p>
                                       <code nobreak="false">element(*, xs:integer) ⊆ element(*, xs:decimal?)</code>
                                    </p>
                                 </item>
                                 <item>
                                    <p>
                                       <code nobreak="false">element(my:*, xs:integer?) ⊆ element(*, xs:decimal?)</code>
                                    </p>
                                 </item>
                              </ulist>
                           </example>
                        </item>
                        <item>
                           <p>All the following are true:</p>
                           <olist>
                              <item>
                                 <p>
                                    <var>A</var> is <code nobreak="false">schema-element(<var>A/n</var>)</code>
                                 </p>
                              </item>
                              <item>
                                 <p>
                                    <var>B</var> is <code nobreak="false">schema-element(<var>B/n</var>)</code>
                                 </p>
                              </item>
                              <item>
                                 <p>Every element declaration that is an actual member of the substitution group of <var>A/n</var> 
                                 is also an actual member of the substitution group of <var>B/n</var>.</p>
                              </item>
                           </olist>
                           <note>
                              <p>The fact that <var>P</var> is a member of the substitution group of <var>Q</var> 
                                   does not mean that every element declaration in the substitution group of <var>P</var> 
                                   is also in the substitution group of <var>Q</var>. For example, <var>Q</var> might 
                                   block substitution of elements whose type is derived by extension, while <var>P</var> does not.</p>
                           </note>
                        </item>
                        <item>
                           <p>All the following are true:</p>
                           <olist>
                              <item>
                                 <p>
                                    <var>A</var> is <code nobreak="false">schema-element(<var>A/n</var>)</code>
                                 </p>
                              </item>
                              <item>
                                 <p>
                                    <var>B</var> is <code nobreak="false">element(*, <var>B/t</var>)</code>
                                 </p>
                              </item>
                              <item>
                                 <p>the schema type identified by the <code nobreak="false">{type definition}</code> 
                                 property of the element declaration of 
                              <var>A/n</var> in the <termref def="dt-static-context"/>
                                    <termref def="dt-derives-from"/>
                                    <var>B/t</var>.</p>
                              </item>
                              <item>
                                 <p>the element declaration of 
                              <var>A/n</var> in the <termref def="dt-static-context"/> is not nillable.</p>
                              </item>
                           </olist>
                        </item>
                        <item>
                           <p>All the following are true:</p>
                           <olist>
                              <item>
                                 <p>
                                    <var>A</var> is <code nobreak="false">schema-element(<var>A/n</var>)</code>
                                 </p>
                              </item>
                              <item>
                                 <p>
                                    <var>B</var> is <code nobreak="false">element(*, <var>B/t</var>?)</code>
                                 </p>
                              </item>
                              <item>
                                 <p>the schema type identified by the <code nobreak="false">{type definition}</code> 
                                 property of the element declaration of 
                              <var>A/n</var> in the <termref def="dt-static-context"/>
                                    <termref def="dt-derives-from"/>
                                    <var>B/t</var>.</p>
                              </item>
                           </olist>
                        </item>
                        <item>
                           <p>
                              <var>A</var> is <code nobreak="false">element(<var>A/1</var>|<var>A/2</var>|..., <var>T</var>)</code> 
                              (where <var>T</var> may be absent),
                           and for each <var>A/n</var>, <code nobreak="false">element(<var>A/n</var>, <var>T</var>) ⊆ <var>B</var>
                              </code>.</p>
                           <example>
                              <head>Examples:</head>
                              <ulist>
                                 <item>
                                    <p>
                                       <code nobreak="false">element(a|b) ⊆ (element(a)|element(b)|element(c))</code>
                                    </p>
                                 </item>
                                 <item>
                                    <p>
                                       <code nobreak="false">element(a|b, xs:integer) ⊆ (element(a, xs:decimal) | element(b, xs:integer))</code>
                                    </p>
                                 </item>
                              </ulist>
                           </example>
                        </item>
                     </olist>
                  </div5>
                  <div5 id="id-item-subtype-attributes">
                     <head>Subtyping Nodes: Attributes</head>
                     <changes>
                        <change issue="2201" PR="2202" date="2025-09-23">The type <code nobreak="false">schema-attribute(N)</code> is now defined
                     to be a subtype of <code nobreak="false">attribute()</code> and of various other attribute tests.</change>
                     </changes>
                     <p>Given item types <var>A</var> and <var>B</var>, <code nobreak="false">
                           <var>A</var> ⊆ <var>B</var>
                        </code> is true if any of the following apply:</p>
                     <olist>
                        <item>
                           <p>
                              <var>A</var> is an <nt def="doc-xpath40-AttributeNodeType"><!--$spec = xpath40--></nt> 
                              and
                              <var>B</var> is either <code nobreak="false">attribute()</code> or <code nobreak="false">attribute(*)</code>
                           </p>
                        </item>
                        <item>
                           <p>All the following are true:</p>
                           <olist>
                              <item>
                                 <p>
                                    <var>A</var> is either <code nobreak="false">attribute(<var>A/n</var>)</code> or 
                                 <code nobreak="false">attribute(<var>A/n</var>, <var>T</var>)</code> 
                                 for any type <var>T</var>.</p>
                              </item>
                              <item>
                                 <p>
                                    <var>B</var> is either <code nobreak="false">attribute(Bn)</code> or 
                                 <code nobreak="false">attribute(<var>B/n</var>, xs:anyAtomicType)</code>
                                 </p>
                              </item>
                              <item>
                                 <p>
                                    <var>A/n</var>
                                    <termref def="dt-wildcard-matches"/>
                                    <var>B/n</var>
                                 </p>
                              </item>
                           </olist>
                           <example>
                              <head>Examples:</head>
                              <ulist>
                                 <item>
                                    <p>
                                       <code nobreak="false">attribute(code) ⊆ attribute(*)</code>
                                    </p>
                                 </item>
                                 <item diff="add" at="Issue23">
                                    <p>
                                       <code nobreak="false">attribute(code|status) ⊆ attribute(*)</code>
                                    </p>
                                 </item>
                                 <item>
                                    <p>
                                       <code nobreak="false">attribute(code, xs:untypedAtomic) ⊆ attribute(*)</code>
                                    </p>
                                 </item>
                                 <item>
                                    <p>
                                       <code nobreak="false">attribute(code|status, xs:string) ⊆ attribute(code, xs:anyAtomicType)</code>
                                    </p>
                                 </item>
                                 <item diff="add" at="Issue23">
                                    <p>
                                       <code nobreak="false">attribute(my:code|your:code) ⊆ attribute(*:code)</code>
                                    </p>
                                 </item>
                                 <item diff="add" at="Issue23">
                                    <p>
                                       <code nobreak="false">attribute(my:code|my:status) ⊆ attribute(my:*)</code>
                                    </p>
                                 </item>
                              </ulist>
                           </example>
                        </item>
                        <item>
                           <p>All the following are true:</p>
                           <olist>
                              <item>
                                 <p>
                                    <var>A</var> is <code nobreak="false">attribute(<var>A/n</var>, <var>A/t</var>)</code>
                                 </p>
                              </item>
                              <item>
                                 <p>
                                    <var>B</var> is <code nobreak="false">attribute(<var>B/n</var>, <var>B/t</var>)</code>
                                 </p>
                              </item>
                              <item>
                                 <p>
                                    <var>A/n</var>
                                    <termref def="dt-wildcard-matches"/>
                                    <var>B/n</var>
                                 </p>
                              </item>
                              <item>
                                 <p>
                                    <var>A/t</var>
                                    <termref def="dt-derives-from"/>
                                    <var>B/t</var>.</p>
                              </item>
                           </olist>
                           <example>
                              <head>Examples:</head>
                              <ulist>
                                 <item>
                                    <p>
                                       <code nobreak="false">attribute(*, xs:ID) ⊆ attribute(*, xs:string)</code>
                                    </p>
                                 </item>
                                 <item>
                                    <p>
                                       <code nobreak="false">attribute(my:*, xs:ID) ⊆ attribute(*, xs:string)</code>
                                    </p>
                                 </item>
                                 <item diff="add" at="Issue23">
                                    <p>
                                       <code nobreak="false">attribute(code, xs:ID) ⊆ attribute(code|status, xs:string)</code>
                                    </p>
                                 </item>
                                 <item>
                                    <p>
                                       <code nobreak="false">attribute(code, xs:ID) ⊆ attribute(*, xs:string)</code>
                                    </p>
                                 </item>
                                 <item>
                                    <p>
                                       <code nobreak="false">attribute(code, xs:ID) ⊆ attribute(*:code, xs:ID)</code>
                                    </p>
                                 </item>
                                 <item diff="add" at="Issue23">
                                    <p>
                                       <code nobreak="false">attribute(my:code|my:status, xs:ID) ⊆ attribute(my:*, xs:string)</code>
                                    </p>
                                 </item>
                              </ulist>
                           </example>
                        </item>
                        <item>
                           <p>All the following are true:</p>
                           <olist>
                              <item>
                                 <p>
                                    <var>A</var> is <code nobreak="false">schema-attribute(<var>A/n</var>)</code>
                                 </p>
                              </item>
                              <item>
                                 <p>
                                    <var>B</var> is <code nobreak="false">schema-attribute(<var>B/n</var>)</code>
                              or <code nobreak="false">attribute(<var>B/n</var>)</code>
                                 </p>
                              </item>
                              <item>
                                 <p>the <termref def="dt-expanded-qname">expanded QName</termref> of <var>A/n</var> equals the <termref def="dt-expanded-qname">expanded QName</termref> of <var>B/n</var>
                                 </p>
                              </item>
                           </olist>
                        </item>
                        <item>
                           <p>All the following are true:</p>
                           <olist>
                              <item>
                                 <p>
                                    <var>A</var> is <code nobreak="false">schema-attribute(<var>A/n</var>)</code>
                                 </p>
                              </item>
                              <item>
                                 <p>
                                    <var>B</var> is <code nobreak="false">attribute(<var>B/n</var>, <var>B/t</var>)</code>
                                 </p>
                              </item>
                              <item>
                                 <p>the <termref def="dt-expanded-qname">expanded QName</termref> of <var>A/n</var> equals the <termref def="dt-expanded-qname">expanded QName</termref> of <var>B/n</var>
                                 </p>
                              </item>
                              <item>
                                 <p>the schema type (always a simple type) referenced
                                  by the <code nobreak="false">{type definition}</code> property of the attribute
                                  declaration of 
                              <var>A/n</var> in the <termref def="dt-static-context"/>
                                    <termref def="dt-derives-from"/>
                                    <var>B/t</var>.</p>
                              </item>
                           </olist>
                        </item>
                        <item>
                           <p>All the following are true:</p>
                           <olist>
                              <item>
                                 <p>
                                    <var>A</var> is <code nobreak="false">schema-attribute(<var>A/n</var>)</code>
                                 </p>
                              </item>
                              <item>
                                 <p>
                                    <var>B</var> is <code nobreak="false">attribute(<var>N</var>, <var>B/t</var>)</code>
                                 </p>
                              </item>
                              <item>
                                 <p>
                                    <var>N</var> is a <nt def="prod-xpath40-NameTestUnion">NameTestUnion<!--$spec = xpath40--></nt> that matches
                              <var>A/n</var> (for example, <code nobreak="false">*</code>).</p>
                              </item>
                              <item>
                                 <p>the schema type (always a simple type) referenced
                                  by the <code nobreak="false">{type definition}</code> property of the attribute
                                  declaration of 
                              <var>A/n</var> in the <termref def="dt-static-context"/>
                                    <termref def="dt-derives-from"/>
                                    <var>B/t</var>.</p>
                              </item>
                           </olist>
                        </item>
                        <item>
                           <p>
                              <var>A</var> is <code nobreak="false">attribute(<var>A/1</var>|<var>A/2</var>|..., <var>T</var>)</code> (where <var>T</var> may be absent),
                           and for each <var>A/n</var>, <code nobreak="false">attribute(<var>A/n</var>, <var>T</var>) ⊆ <var>B</var>
                              </code>.</p>
                           <example>
                              <head>Examples:</head>
                              <ulist>
                                 <item>
                                    <p>
                                       <code nobreak="false">attribute(a|b) ⊆ (attribute(a)|attribute(b)|attribute(c))</code>
                                    </p>
                                 </item>
                                 <item>
                                    <p>
                                       <code nobreak="false">attribute(a|b, xs:integer) ⊆ (attribute(a, xs:decimal) | attribute(b))</code>
                                    </p>
                                 </item>
                              </ulist>
                           </example>
                        </item>
                     </olist>
                  </div5>
                  <div5 id="id-item-subtype-jnodes">
                     <head>Subtyping JNodes</head>
                     <p>Given item types <var>A</var> and <var>B</var>, <code nobreak="false">
                           <var>A</var> ⊆ <var>B</var>
                        </code> is true 
                     if any of the following apply:</p>
                     <olist>
                        <item>
                           <p>
                              <var>A</var> is <code nobreak="false">jnode()</code> (or equivalently, <code nobreak="false">jnode(*)</code>)
                         and <var>B</var> is <code nobreak="false">gnode()</code>.</p>
                        </item>
                        <item>
                           <p>
                              <var>A</var> is <code nobreak="false">jnode(<var>C</var>)</code> and <var>B</var> is <code nobreak="false">jnode()</code>, for any constant 
                           <var>C</var>.</p>
                        </item>
                        <item>
                           <p>
                              <var>A</var> is <code nobreak="false">jnode(*, <var>T</var>)</code> and <var>B</var> is <code nobreak="false">jnode()</code>, for any sequence type 
                           <var>T</var>.</p>
                        </item>
                        <item>
                           <p>
                              <var>A</var> is <code nobreak="false">jnode(*, <var>T</var>)</code>, <var>B</var> is <code nobreak="false">jnode(*, <var>U</var>)</code>, 
                           and <code nobreak="false">T ⊑ U</code>.</p>
                        </item>
                        <item>
                           <p>
                              <var>A</var> is <code nobreak="false">jnode(C, <var>T</var>)</code>, <var>B</var> is <code nobreak="false">jnode(C, <var>U</var>)</code>, 
                           for any constant <var>C</var>, and <code nobreak="false">T ⊑ U</code>.</p>
                        </item>
                        <item>
                           <p>
                              <var>A</var> is <code nobreak="false">jnode(C, <var>T</var>)</code>, <var>B</var> is <code nobreak="false">jnode(*, <var>U</var>)</code>, 
                           for any constant <var>C</var>, and <code nobreak="false">T ⊑ U</code>.</p>
                        </item>
                        <item>
                           <p>
                              <var>A</var> is <code nobreak="false">jnode(())</code> and <var>B</var> is <code nobreak="false">jnode(*)</code>.</p>
                        </item>
                        <item>
                           <p>
                              <var>A</var> is <code nobreak="false">jnode((), <var>T</var>)</code>, <var>B</var> is <code nobreak="false">jnode(*, <var>U</var>)</code>,
                           and <code nobreak="false">T ⊑ U</code>.</p>
                        </item>
                     </olist>
                  </div5>
               </div4>
               <div4 id="id-item-subtype-functions">
                  <head>Subtyping Functions</head>
                  <p>Given item types <var>A</var> and <var>B</var>, <code nobreak="false">
                        <var>A</var> ⊆ <var>B</var>
                     </code> is true if any of the following apply:</p>
                  <olist>
                     <item>
                        <p>All the following are true:</p>
                        <olist>
                           <item>
                              <p>
                                 <var>A</var> is a <nt def="doc-xpath40-FunctionType">FunctionType<!--$spec = xpath40--></nt>
                              </p>
                           </item>
                           <item>
                              <p>
                                 <var>B</var> is <code nobreak="false">
                                  function(*)</code>
                              </p>
                           </item>
                        </olist>
                        <example>
                           <head>Example:</head>
                           <p>
                              <code nobreak="false">function(xs:integer) as xs:string ⊆ function(*)</code>
                           </p>
                        </example>
                     </item>
                     <item>
                        <p>All the following are true:</p>
                        <olist>
                           <item>
                              <p>
                                 <var>A</var> is <code nobreak="false">
                                    function(<var>a/1</var>, <var>a/2</var>, ... <var>a/M</var>) as <var>R/A</var>
                                 </code>
                              </p>
                           </item>
                           <item>
                              <p>
                                 <var>B</var> is <code nobreak="false">
                                    function(<var>b/1</var>, <var>b/2</var>, ... <var>b/N</var>) as <var>R/B</var>
                                 </code>
                              </p>
                           </item>
                           <item>
                              <p>
                                 <var>N</var> (the arity of <var>B</var>) equals <var>M</var> (the arity of <var>A</var>)
                                    </p>
                           </item>
                           <item>
                              <p>
                                 <code nobreak="false">
                                    <var>R/A</var> ⊑ <var>R/B</var>
                                 </code>
                              </p>
                           </item>
                           <item>
                              <p>For all values of <var>p</var> between 1 and <var>N</var>, <code nobreak="false">
                                    <var>b/p</var> ⊑ <var>a/p</var>
                                 </code>
                              </p>
                           </item>
                        </olist>
                        <example>
                           <head>Examples:</head>
                           <ulist>
                              <item>
                                 <p>
                                    <code nobreak="false">function(xs:integer) as xs:string ⊆ function(xs:long) as xs:string</code>
                                 </p>
                              </item>
                              <item>
                                 <p>
                                    <code nobreak="false">function(xs:integer) as xs:ID ⊆ function(xs:integer) as xs:string</code>
                                 </p>
                              </item>
                              <item>
                                 <p>
                                    <code nobreak="false">function(xs:integer) as xs:ID ⊆ function(xs:long) as xs:string</code>
                                 </p>
                              </item>
                           </ulist>
                        </example>
                        <note>
                           <p>Function return types are covariant because this rule requires <code nobreak="false">
                                 <var>R/A</var> ⊑ <var>R/B</var>
                              </code> for return types. 
                                 Function parameter types are contravariant because this rule requires <code nobreak="false">
                                 <var>b/p</var> ⊑ <var>a/p</var>
                              </code> for parameter types.</p>
                        </note>
                     </item>
                  </olist>
               </div4>
               <div4 id="id-item-subtype-maps">
                  <head>Subtyping Maps</head>
                  <p>Given item types <var>A</var> and <var>B</var>, <code nobreak="false">
                        <var>A</var> ⊆ <var>B</var>
                     </code> is true if any of the following apply:</p>
                  <olist>
                     <item>
                        <p>Both of the following are true:</p>
                        <olist>
                           <item>
                              <p>
                                 <var>A</var> is <code nobreak="false">map(<var>K</var>, <var>V</var>)</code>,
                                 for any <var>K</var> and <var>V</var>
                              </p>
                           </item>
                           <item>
                              <p>
                                 <var>B</var> is <code nobreak="false">map(*)</code>
                              </p>
                           </item>
                        </olist>
                        <example>
                           <head>Example:</head>
                           <p>
                              <code nobreak="false">map(xs:integer, item()*) ⊆ map(*)</code>
                           </p>
                        </example>
                     </item>
                     <item>
                        <p>All the following are true:</p>
                        <olist>
                           <item>
                              <p>
                                 <var>A</var> is <code nobreak="false">map(<var>K/a</var>, <var>V/a</var>)</code>
                              </p>
                           </item>
                           <item>
                              <p>
                                 <var>B</var> is <code nobreak="false">map(<var>K/b</var>, <var>V/b</var>)</code>
                              </p>
                           </item>
                           <item>
                              <p>
                                 <code nobreak="false">
                                    <var>K/a</var> ⊆ <var>K/b</var>
                                 </code>
                              </p>
                           </item>
                           <item>
                              <p>
                                 <code nobreak="false">
                                    <var>V/a</var> ⊑ <var>V/b</var>
                                 </code>
                              </p>
                           </item>
                        </olist>
                        <example>
                           <head>Example:</head>
                           <p>
                              <code nobreak="false">map(xs:long, item()) ⊆ map(xs:integer, item()+)</code>
                           </p>
                        </example>
                     </item>
                     <item>
                        <p>Both the following are true:</p>
                        <olist>
                           <item>
                              <p>
                                 <var>A</var> is <code nobreak="false">map(*)</code>
                                 (or, because of the transitivity rules, any other map type)</p>
                           </item>
                           <item>
                              <p>
                                 <var>B</var> is <code nobreak="false">function(*)</code>
                              </p>
                           </item>
                        </olist>
                        <example>
                           <head>Example:</head>
                           <p>
                              <code nobreak="false">map(xs:long, xs:string?) ⊆ function(*)</code>
                           </p>
                        </example>
                     </item>
                     <item>
                        <p>Both the following are true:</p>
                        <olist>
                           <item>
                              <p>
                                 <var>A</var> is <code nobreak="false">map(*)</code>
                                 (or, because of the transitivity rules, any other map type)</p>
                           </item>
                           <item>
                              <p>
                                 <var>B</var> is 
                                 <code nobreak="false">function(xs:anyAtomicType) as item()*</code>
                              </p>
                           </item>
                        </olist>
                        <example>
                           <head>Example:</head>
                           <p>
                              <code nobreak="false">map(xs:long, xs:string?) ⊆ function(xs:anyAtomicType) as item()*</code>
                           </p>
                        </example>
                     </item>
                     <item diff="chg" at="issue730">
                        <p>All the following are true:</p>
                        <olist>
                           <item>
                              <p>
                                 <var>A</var> is <code nobreak="false">map(<var>K</var>, <var>V</var>)</code>
                              </p>
                           </item>
                           <item>
                              <p>
                                 <var>B</var> is <code nobreak="false">function(xs:anyAtomicType) as <var>R</var>
                                 </code>
                              </p>
                           </item>
                           <item>
                              <p>
                                 <var>V</var> ⊆ <var>R</var>
                              </p>
                           </item>
                           <item>
                              <p>
                                 <code nobreak="false">empty-sequence()</code> ⊆ <var>R</var>
                              </p>
                           </item>
                        </olist>
                        <example>
                           <head>Examples:</head>
                           <ulist>
                              <item>
                                 <p>
                                    <code nobreak="false">map(xs:int, node()) ⊆ function(xs:anyAtomicType) as node()?</code>
                                 </p>
                              </item>
                              <item>
                                 <p>
                                    <code nobreak="false">map(xs:int, node()+) ⊆ function(xs:anyAtomicType) as node()*</code>
                                 </p>
                              </item>
                           </ulist>
                           <p>The function accepts type <code nobreak="false">xs:anyAtomicType</code> rather than <code nobreak="false">xs:int</code>,
                              because <code nobreak="false">$M("xyz")</code> is a valid call on a map (treated as a function) even
                              when all the keys in the map are integers.</p>
                           <p>The return type of the function is extended from <code nobreak="false">node()</code> or <code nobreak="false">node()+</code> to allow the empty sequence
                                 because <code nobreak="false">$M("xyz")</code> can return the empty sequence even if none of the entries
                              in the map contains the empty sequence.</p>
                        </example>
                     </item>
                  </olist>
               </div4>
               <div4 id="id-item-subtype-arrays">
                  <head>Subtyping Arrays</head>
                  <p>Given item types <var>A</var> and <var>B</var>, <code nobreak="false">
                        <var>A</var> ⊆ <var>B</var>
                     </code> is true if any of the following apply:</p>
                  <olist>
                     <item>
                        <p>Both the following are true:</p>
                        <olist>
                           <item>
                              <p>
                                 <var>A</var> is <code nobreak="false">array(<var>X</var>)</code>
                              </p>
                           </item>
                           <item>
                              <p>
                                 <var>B</var> is <code nobreak="false">array(*)</code>
                              </p>
                           </item>
                        </olist>
                        <example>
                           <head>Example:</head>
                           <p>
                              <code nobreak="false">array(xs:integer) ⊆ array(*)</code>
                           </p>
                        </example>
                     </item>
                     <item>
                        <p>All the following are true:</p>
                        <olist>
                           <item>
                              <p>
                                 <var>A</var> is <code nobreak="false">array(<var>X</var>)</code>
                              </p>
                           </item>
                           <item>
                              <p>
                                 <var>B</var> is <code nobreak="false">array(<var>Y</var>)</code>
                              </p>
                           </item>
                           <item>
                              <p>
                                 <code nobreak="false">
                                    <var>X</var> ⊑ <var>Y</var>
                                 </code>
                              </p>
                           </item>
                        </olist>
                        <example>
                           <head>Example:</head>
                           <p>
                              <code nobreak="false">array(xs:integer) ⊆ array(xs:decimal+)</code>
                           </p>
                        </example>
                     </item>
                     <item>
                        <p>Both the following are true:</p>
                        <olist>
                           <item>
                              <p>
                                 <var>A</var> is <code nobreak="false">array(*)</code>
                                 (or, because of the transitivity rules, any other array type)</p>
                           </item>
                           <item>
                              <p>
                                 <var>B</var> is <code nobreak="false">function(*)</code>
                              </p>
                           </item>
                        </olist>
                        <example>
                           <head>Example:</head>
                           <p>
                              <code nobreak="false">array(xs:integer) ⊆ function(*)</code>
                           </p>
                        </example>
                     </item>
                     <item>
                        <p>Both the following are true:</p>
                        <olist>
                           <item>
                              <p>
                                 <var>A</var> is <code nobreak="false">array(*)</code>
                                 (or, because of the transitivity rules, any other array type)</p>
                           </item>
                           <item>
                              <p>
                                 <var>B</var> is <code nobreak="false">function(xs:integer) as item()*</code>
                              </p>
                           </item>
                        </olist>
                        <example>
                           <head>Example:</head>
                           <p>
                              <code nobreak="false">array(*) ⊆ function(xs:integer) as item()*</code>
                           </p>
                        </example>
                     </item>
                     <item>
                        <p>Both the following are true:</p>
                        <olist>
                           <item>
                              <p>
                                 <var>A</var> is <code nobreak="false">array(<var>X</var>)</code>
                              </p>
                           </item>
                           <item>
                              <p>
                                 <var>B</var> is <code nobreak="false">function(xs:integer) as <var>X</var>
                                 </code>
                              </p>
                           </item>
                        </olist>
                        <example>
                           <head>Example:</head>
                           <p>
                              <code nobreak="false">array(xs:string) ⊆ function(xs:integer) as xs:string</code>
                           </p>
                        </example>
                     </item>
                  </olist>
               </div4>
               <div4 id="id-item-subtype-records">
                  <head>Subtyping Records</head>
                  <changes>
                     <change issue="2365" PR="2413" date="2026-01-28">
                        Extensible map types are dropped; instead, the coercion rules cause undefined
                        map entries to be discarded.
                     </change>
                  </changes>
                  <p>Given item types <var>A</var> and <var>B</var>, <var>A</var>
                     <code nobreak="false">⊆</code>
                     <var>B</var> is true if any of the following apply:</p>
                  <olist><!--<item diff="add" at="issue52">
                        <p><var>A</var> is <code>map(*)</code> and <var>B</var> is <code>record(*)</code>.</p>
                     </item>-->
                     <item diff="add" at="A">
                        <p>All of the following are true:</p>
                        <olist>
                           <item>
                              <p>
                                 <var>A</var> is a record type.</p>
                           </item>
                           <item>
                              <p>
                                 <var>B</var> is <code nobreak="false">map(*)</code>.</p>
                           </item>
                        </olist>
                        <example>
                           <head>Example:</head>
                           <p>
                              <code nobreak="false">record(longitude, latitude)</code> ⊆ <code nobreak="false">map(*)</code>
                           </p>
                           <p>
                              <code nobreak="false">record(longitude as xs:double, latitude as xs:double)</code> ⊆ <code nobreak="false">map(*)</code>
                           </p>
                           <p>
                              <code nobreak="false">record(longitude, latitude, altitude?)</code> ⊆ <code nobreak="false">map(*)</code>
                           </p>
                        </example>
                     </item>
                     <item diff="add" at="A">
                        <p>All of the following are true:</p>
                        <olist>
                           <item>
                              <p>
                                 <var>A</var> is a record type</p>
                           </item>
                           <item>
                              <p>
                                 <var>B</var> is <code nobreak="false">map(<var>K</var>, <var>V</var>)</code>
                              </p>
                           </item>
                           <item>
                              <p>
                                 <var>K</var> is either <code nobreak="false">xs:string</code> or <code nobreak="false">xs:anyAtomicType</code>
                              </p>
                           </item>
                           <item>
                              <p>For every field <var>F</var> in <var>A</var>,
                              where <var>T</var> is the declared type of <var>F</var> (or its default, <code nobreak="false">item()*</code>),
                              <code nobreak="false">
                                    <var>T</var> ⊑ <var>V</var>
                                 </code>.</p>
                           </item>
                        </olist>
                        <example>
                           <head>Examples:</head>
                           <ulist>
                              <item>
                                 <p>
                                    <code nobreak="false">record(x, y)</code> ⊆ <code nobreak="false">map(xs:string, item()*)</code>
                                 </p>
                              </item>
                              <item>
                                 <p>
                                    <code nobreak="false">record(x as xs:double, y as xs:double)</code> ⊆ <code nobreak="false">map(xs:string, xs:double)</code>
                                 </p>
                              </item>
                           </ulist>
                        </example>
                     </item>
                     <item diff="add" at="A">
                        <p>All of the following are true:</p>
                        <olist>
                           <item>
                              <p>
                                 <var>A</var> is a record type.</p>
                           </item>
                           <item>
                              <p>
                                 <var>B</var> is a record type.</p>
                           </item>
                           <item>
                              <p>Every field in <var>A</var> is also declared in <var>B</var>.</p>
                           </item>
                           <item>
                              <p>Every mandatory field in <var>B</var> is also declared  as mandatory in <var>A</var>.</p>
                           </item>
                           <item>
                              <p>For every field that is declared in both <var>A</var> and <var>B</var>,
                              where the declared type in <var>A</var> is <var>T</var> 
                              and the declared type in <var>B</var> is <var>U</var>, <code nobreak="false">
                                    <var>T</var> ⊑ <var>U</var>
                                 </code>.</p>
                           </item>
                        </olist>
                        <example>
                           <head>Examples:</head>
                           <ulist>
                              <item>
                                 <p>
                                    <code nobreak="false">record(x, y as xs:integer) ⊆ record(x, y as xs:decimal)</code>
                                 </p>
                              </item>
                              <item>
                                 <p>
                                    <code nobreak="false">record(x, y) ⊆ record(x, y, z?)</code>
                                 </p>
                              </item>
                           </ulist>
                        </example>
                     </item>
                     <!--<item diff="add" at="A">
                           <p>All of the following are true:</p>
                           <olist>
                              <item><p><var>A</var> is an extensible record type</p></item>
                              <item><p><var>B</var> is an extensible record type</p></item>
                              <item><p>Every mandatory field in <var>B</var> is also declared  as mandatory in <var>A</var>.</p></item>
                              <item><p>For every field that is declared in both <var>A</var> and <var>B</var>,
                                 where the declared type in <var>A</var> is <var>T</var> 
                                 and the declared type in <var>B</var> is <var>U</var>, <code><var>T</var> ⊑ <var>U</var></code>.</p></item> 
                              <item><p>For every field that is declared in <var>B</var>
                                 but not in <var>A</var>, the declared type in <var>B</var> is <code>item()*</code>.</p>
                              </item>  
                           </olist>
                           <example>
                              <head>Examples:</head>
                              <ulist>
                                 <item><p><code>record(x, y, z, *) ⊆ record(x, y, *)</code></p></item>
                                 <item><p><code>record(x?, y?, z?, *) ⊆ record(x, y, *)</code></p></item>
                                 <item><p><code>record(x as xs:integer, y as xs:integer, *) ⊆ record(x as xs:decimal, y as xs:integer*, *)</code></p></item>
                                 <item><p><code>record(x as xs:integer, *) ⊆ record(x as xs:decimal, y as item(), *)</code></p></item>                               
                              </ulist>
                           </example>
                           
                        </item>-->
                     <!--<item diff="add" at="A">
                        <p>All of the following are true:</p>
                        <olist>
                           <item><p><var>A</var> is a non-extensible record type.</p></item>
                           <item><p><var>B</var> is an extensible record type.</p></item>
                           <item><p>Every mandatory field in <var>B</var> is also declared as mandatory in <var>A</var>.</p></item>
                           <!-\-<item><p>Every field that is declared in <var>B</var> with a type other than <code>item()*</code>
                              is also declared in <var>A</var>.</p></item>-\->
                           <item><p>For every field that is declared in both <var>A</var> and <var>B</var>,
                              where the declared type in <var>A</var> is <var>T</var> 
                              and the declared type in <var>B</var> is <var>U</var>, <code><var>T</var> ⊑ <var>U</var></code>.</p>                               
                           </item>
                        </olist>
                        <example>
                           <head>Examples:</head>
                           <ulist>
                              <item><p><code>record(x, y as xs:integer) ⊆ record(x, y as xs:decimal, *)</code></p></item>
                              <item><p><code>record(y as xs:integer) ⊆ record(x?, y as xs:decimal, *)</code></p></item>
                           </ulist>
                        </example>
                     </item>-->
                  </olist>
               </div4>
               <div4 id="id-itemtype-subtype-aliases" diff="add" at="issue295">
                  <head>Subtyping of Named Item Types</head>
                  <p>This section describes how references to <termref def="dt-named-item-type">named item types</termref>
                  are handled when evaluating the subtype relationship.</p>
                  <p>Named item types can be classified as recursive or non-recursive. 
                     A recursive type is one that references itself, directly or indirectly. Only named record
                  types are allowed to be recursive.</p>
                  <p>In the case of references to non-recursive named item types, the reference
                  is fully expanded as the first step in evaluating the subtype relationship. For example
                  this means that if <var>U</var> is a named item type with the expansion 
                     <code nobreak="false">(xs:integer | xs:double)</code>,
                     then <code nobreak="false">xs:integer ⊆ U</code> is true, because 
                     <code nobreak="false">xs:integer ⊆ (xs:integer | xs:double)</code> is true.</p>
                  <p>Recursive record types are considered to be, in the terminology of the computer science
                  literature, <term>iso-recursive</term> (rather than <term>equi-recursive</term>). 
                     This means that a recursive type name is not
                  treated as being equivalent to its expansion (at any depth). 
                  For example, if the named item type <var>T</var>
                  has the expansion <code nobreak="false">record(A as item()*, B as T?)</code>, then the type 
                     <code nobreak="false">array(T)</code> is not considered to be equivalent to 
                     <code nobreak="false">array(record(A as item()*, B as T?))</code>, despite the fact
                  that the two types have exactly the same instances.</p>
                  <p>The rules are therefore defined as follows:</p>
                  <ulist>
                     <item>
                        <p>If <var>B</var> is a reference to a recursive record type, then
                        <var>A</var> ⊆ <var>B</var> is true if and only if 
                        <var>A</var> and <var>B</var>
                        are references to the same named record type.</p>
                     </item>
                     <item>
                        <p>If <var>A</var> is a reference to a recursive named item type, then
                        <var>A</var> ⊆ <var>B</var> is true if and only if 
                        <var>A</var> and <var>B</var>
                        are references to the same named record type.</p>
                     </item>
                  </ulist>
                  <note>
                     <p>The decision to make recursive types iso-recursive rather than equi-recursive
                  was made largely because it saves a great deal of implementation complexity without any serious
                  adverse effects for users. In practice, problems can be avoided by using named record types
                  consistently (for example, avoiding having two named record types with
                  different names but identical definitions).</p>
                  </note>
               </div4>
            </div3>
         </div2>
         <div2 id="id-coercion-rules">
            <head>Coercion Rules</head>
            <changes>
               <change PR="254" date="2022-11-29">
                  The term "function conversion rules" used in 3.1 has been replaced by the term "coercion rules".
               </change>
               <change issue="117" PR="254" date="2022-11-29">
                  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 <code nobreak="false">xs:positiveInteger</code>.
               </change>
               <change issue="980" PR="911" date="2024-01-30">
                  The coercion rules now allow any numeric type to be implicitly converted to any other, for example
                  an <code nobreak="false">xs:double</code> is accepted where the required type is <code nobreak="false">xs:decimal</code>.
               </change>
               <change issue="130 480" PR="815" date="2023-11-07">
                  The coercion rules now allow conversion in either direction between <code nobreak="false">xs:hexBinary</code>
                  and <code nobreak="false">xs:base64Binary</code>.
               </change>
               <change issue="1318" PR="1501" date="2024-10-29">
                  The coercion rules now apply recursively to the members of an array and the entries in a map.
               </change>
               <change issue="1862" PR="1874" date="2025-03-25">
                  The coercion rules now reorder the entries in a map when the required type is a record type.
               </change>
            </changes>
            <p diff="chg" at="2022-11-17">
               <termdef term="coercion rules" id="dt-coercion-rules">The <term>coercion rules</term> 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.
                  </termdef> The required type is expressed as a <termref def="dt-sequence-type">sequence type</termref>. 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.</p>
            <p diff="chg" at="2022-11-17">This section defines how the coercion rules operate; the situations in which the rules apply
                  are defined elsewhere, by reference to this section.</p>
            <note diff="add" at="A">
               <p>In previous versions of this specification, the coercion rules were referred to as the
                              <emph>function conversion</emph> rules. The terminology has changed because the rules are not exclusively
                              associated with functions or function calling.</p>
            </note>
            <p diff="chg" at="2023-03-11">If the required type is <code nobreak="false">empty-sequence()</code>, 
                  no coercion takes place (the supplied
               value must be the empty sequence, or a type error occurs).</p>
            <p>In all other cases, the required 
                  <termref def="dt-sequence-type"/>
               <var>T</var> comprises a required <termref def="dt-item-type"/>
               <var>R</var> 
                  and an optional occurrence indicator. The coercion rules are then 
                  applied to a supplied value <var>V</var> 
               and the required type <var>T</var> as follows:</p>
            <olist>
               <item role="xpath">
                  <p>If  <termref def="dt-xpath-compat-mode">XPath
                     1.0 compatibility mode</termref> is <code nobreak="false">true</code> and <var>V</var>
                     is not an instance of the required type <var>T</var>, then the conversions defined in
                     <specref ref="id-xpath-10-compatibility"/> are applied to <var>V</var>. Then:</p>
               </item>
               <item>
                  <p>Each item in <var>V</var> is processed against the required item type <var>R</var>
                     using the item coercion rules defined
                  in <specref ref="id-item-coercion-rules"/>, and the results are sequence-concatenated
                  into a single sequence <var>V'</var>.</p>
               </item>
               <item>
                  <p>A type error is raised if the cardinality of <var>V'</var> does not match the
                  required cardinality of <var>T</var>
                     <errorref code="0004" class="TY"/>.</p>
               </item>
            </olist>
            <div3 id="id-xpath-10-compatibility" role="xpath">
               <head>XPath 1.0 Compatibility Rules</head>
               <p>These rules are used to process a value <var>V</var> against a required sequence type 
                  <var>T</var> when 
                  <termref def="dt-xpath-compat-mode">XPath 1.0 compatibility mode</termref> is <code nobreak="false">true</code>.</p>
               <olist>
                  <item>
                     <p>If the occurrence indicator of <var>T</var> is either absent or <code nobreak="false">?</code>
                        (examples: <code nobreak="false">xs:string</code>, <code nobreak="false">xs:string?</code>, 
                        <code nobreak="false">xs:untypedAtomic</code>, <code nobreak="false">xs:untypedAtomic?</code>, 
                        <code nobreak="false">node()</code>, <code nobreak="false">node()?</code>, <code nobreak="false">item()</code>, 
                        <code nobreak="false">item()?</code>), then <var>V</var> is effectively replaced by <code nobreak="false">V[1]</code>.</p>
                  </item>
                  <item>
                     <p>If <var>T</var> is <code nobreak="false">xs:string</code> or <code nobreak="false">xs:string?</code>,
                        then <var>V</var> is effectively replaced by
                        <code nobreak="false">fn:string(V)</code>.</p>
                     <note diff="add" at="2022-11-17">
                        <p>This rule does not apply where <var>T</var> is derived from <code nobreak="false">xs:string</code>
                        or <code nobreak="false">xs:string?</code>, because derived types did not arise in XPath 1.0.</p>
                     </note>
                  </item>
                  <item>
                     <p>If <var>T</var> is <code nobreak="false">xs:double</code> or <code nobreak="false">xs:double?</code>, then 
                        <code nobreak="false">V</code> is effectively replaced by <code nobreak="false">fn:number(V)</code>.</p>
                     <note diff="add" at="2022-11-17">
                        <p>This rule does not apply where <var>T</var> is derived from <code nobreak="false">xs:double</code>
                        or <code nobreak="false">xs:double?</code>, because derived types did not arise in XPath 1.0.</p>
                     </note>
                  </item>
               </olist>
               <note>
                  <p>
                     The special rules for <termref def="dt-xpath-compat-mode">XPath 1.0 compatibility
                        mode</termref> are used for converting the arguments of a static function call, and
                     in certain XSLT constructs. They are not invoked in other contexts such as dynamic function calls,
                     for converting the result of an inline function to its required type,
                     for partial function application, or for implicit function calls such as
                     occur when evaluating functions such as <function>fn:for-each</function> and <function>fn:filter</function>.</p>
               </note>
            </div3>
            <div3 id="id-item-coercion-rules">
               <head>Item Coercion Rules</head>
               <p>The rules in this section are used to process each item <var>J</var> in a supplied
               sequence, given a required <termref def="dt-item-type"/>
                  <var>R</var>.</p>
               <olist>
                  <item>
                     <p>If <var>R</var> is a <termref def="dt-generalized-atomic-type"/>
                     (for example, if it is an <termref def="dt-atomic-type"/>,
                     a <termref def="dt-pure-union-type"/>, or
                     an <termref def="dt-enumeration-type"/>), and <var>J</var>
                     is not an atomic item, then:
                     <olist>
                           <item>
                              <p>
                                 <var>J</var> is <termref def="dt-atomization">atomized</termref> 
                           to produce a sequence of atomic items <var>JJ</var>.</p>
                           </item>
                           <item>
                              <p>Each atomic item in <var>JJ</var> is coerced to the required
                        type <var>R</var> by recursive application of the item coercion rules (the 
                        rules in this section) to produce a value <var>V</var>.</p>
                           </item>
                           <item>
                              <p>The result is the <termref def="dt-sequence-concatenation"/> 
                           of the <var>V</var> values.</p>
                           </item>
                        </olist>
                     </p>
                     <note>
                        <p>For example, if <code nobreak="false">J</code> is an element with type annotation
                  <code nobreak="false">xs:integer</code>, and <code nobreak="false">R</code> is the union type <code nobreak="false">xs:numeric</code>,
                  then the effect is to atomize the element to an <code nobreak="false">xs:integer</code>, and then
                  to coerce the resulting <code nobreak="false">xs:integer</code> to <code nobreak="false">xs:numeric</code>
                  (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 <code nobreak="false">xs:double</code>.</p>
                     </note>
                  </item>
                  <item>
                     <p>Otherwise, if <var>R</var> is a <termref def="dt-choice-item-type"/> or
                     a <termref def="dt-pure-union-type"/> (which includes the case where
                     it is an <termref def="dt-enumeration-type"/>), then:</p>
                     <olist>
                        <item>
                           <p>If <var>J</var> matches (is an instance of) one of the alternatives
                           in <var>R</var>, then <var>J</var> is coerced to the first alternative in 
                           <var>R</var> that <var>J</var> matches.</p>
                           <note>
                              <p>There are two situations where coercing an item to a type that
                              it already matches does not simply return the item unchanged:</p>
                              <ulist>
                                 <item>
                                    <p>When the required type is a typed function type
                                      (see <specref ref="id-function-test"/>),
                                    then function coercion is applied to coerce <var>J</var> to that
                                    function type, as described in <specref ref="id-function-coercion"/>.</p>
                                 </item>
                                 <item>
                                    <p>When the required type is a record type and the supplied
                                 value is a map, then coercion may change the <xtermref spec="DM40" ref="dt-entry-order"/>
                                 of the entries in the map.</p>
                                 </item>
                              </ulist>
                           </note>
                        </item>
                        <item>
                           <p>Otherwise, the item coercion rules (the rules in this section)
                              are applied to <var>J</var> recursively
                              with <var>R</var> 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.</p>
                           <p>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.)</p>
                        </item>
                     </olist>
                     <note>
                        <p>Suppose the required type is <code nobreak="false">(xs:integer | element(e))*</code>
                           and the supplied value is the sequence 
                           <code nobreak="false">(&lt;e&gt;22&lt;/e&gt;, 23, &lt;f&gt;24&lt;/f&gt;)</code>. 
                        Item coercion is applied independently to each of the three items in this
                        sequence. The first item matches one of the alternatives, namely <code nobreak="false">element(e)</code>,
                        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 <code nobreak="false">xs:integer</code> succeeds (by virtue of atomization and untyped
                           atomic conversion), so the final result is the sequence <code nobreak="false">(&lt;e&gt;22&lt;/e&gt;, 23, 24)</code>
                        </p>
                     </note>
                     <note>
                        <p>Suppose the required type is <code nobreak="false">enum("red", "green", "blue")</code>
                           and the supplied value is <code nobreak="false">"green"</code>. The enumeration type is defined
                           as a choice item type whose alternatives are singleton enumerations, so the rules
                           are applied first to the type <code nobreak="false">enum("red")</code> (which fails), and
                           then to the type <code nobreak="false">enum("green")</code> (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 <code nobreak="false">xs:string</code>.</p>
                     </note>
                     <note>
                        <p>Schema-defined union types behave in exactly the same way as
                        <termref def="dt-choice-item-type">choice item types.</termref>
                        </p>
                     </note>
                  </item>
                  <item>
                     <p>If <var>R</var> is an <termref def="dt-atomic-type"/>
                     and <var>J</var> is an <termref def="dt-atomic-item"/>, then:</p>
                     <olist>
                        <item diff="chg" at="2024-01-04">
                           <p>If <var>J</var> is an instance of 
                           <var>R</var> then it is used unchanged.</p>
                        </item>
                        <item>
                           <p>If <var>J</var> is an instance of type <code nobreak="false">xs:untypedAtomic</code>
                        then:</p>
                           <olist>
                              <item>
                                 <p>If <var>R</var> is <termref def="dt-namespace-sensitive">namespace-sensitive</termref> then 
                                    a <termref def="dt-type-error">type error</termref>
                                    <errorref class="TY" code="0117"/> is raised.</p>
                              </item>
                              <item>
                                 <p>Otherwise,  <var>J</var> is cast to type <var>R</var>.</p>
                              </item>
                           </olist>
                        </item>
                     </olist>
                  </item>
                  <item>
                     <p>If there is an entry (<var>from</var>, <var>to</var>)
                     in the following table such that <var>J</var> is an instance of <var>from</var>,
                     and <var>to</var> is <var>R</var>, then <var>J</var> is cast to type <var>R</var>.</p>
                     <table border="1" role="medium">
                        <caption>Implicit Casting</caption>
                        <thead>
                           <tr>
                              <th rowspan="1" colspan="1">from</th>
                              <th rowspan="1" colspan="1">to</th>
                           </tr>
                        </thead>
                        <tbody>
                           <tr>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">xs:decimal</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">xs:double</code>
                              </td>
                           </tr>
                           <tr>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">xs:double</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">xs:decimal</code>
                              </td>
                           </tr>
                           <tr>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">xs:decimal</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">xs:float</code>
                              </td>
                           </tr>
                           <tr>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">xs:float</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">xs:decimal</code>
                              </td>
                           </tr>
                           <tr>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">xs:float</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">xs:double</code>
                              </td>
                           </tr>
                           <tr>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">xs:double</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">xs:float</code>
                              </td>
                           </tr>
                           <tr>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">xs:string</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">xs:anyURI</code>
                              </td>
                           </tr>
                           <tr>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">xs:anyURI</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">xs:string</code>
                              </td>
                           </tr>
                           <tr>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">xs:hexBinary</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">xs:base64Binary</code>
                              </td>
                           </tr>
                           <tr>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">xs:base64Binary</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">xs:hexBinary</code>
                              </td>
                           </tr>
                        </tbody>
                     </table>
                     <note>
                        <p>The item type in the <var>to</var> column must match <var>R</var>
                        exactly; however, <var>J</var> may belong to a subtype of the type in the <var>from</var>
                        column.</p>
                        <p>For example, an <code nobreak="false">xs:NCName</code> will be cast to type <code nobreak="false">xs:anyURI</code>,
                        but an <code nobreak="false">xs:anyURI</code> will not be cast to type <code nobreak="false">xs:NCName</code>.</p>
                        <p>Similarly, an <code nobreak="false">xs:integer</code> will be cast to type <code nobreak="false">xs:double</code>,
                        but an <code nobreak="false">xs:double</code> will not be cast to type <code nobreak="false">xs:integer</code>.</p>
                     </note>
                  </item>
                  <item>
                     <p>If <var>R</var> is an <termref def="dt-singleton-enumeration-type"/>
                     and <var>J</var> is an instance of <code nobreak="false">xs:untypedAtomic</code>
                        or <code nobreak="false">xs:anyURI</code>, then <var>J</var> is cast to
                        type <code nobreak="false">xs:string</code>.</p>
                     <note>
                        <p>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 <termref def="dt-enumeration-type"/>,
                        for example <code nobreak="false">enum("red", "green", "blue")*</code>, the supplied value can be, 
                        in this example:</p>
                        <ulist>
                           <item>
                              <p>The empty sequence.</p>
                           </item>
                           <item>
                              <p>The string <code nobreak="false">"red"</code>.</p>
                           </item>
                           <item>
                              <p>An untyped node whose string value is <code nobreak="false">"red"</code>.</p>
                           </item>
                           <item>
                              <p>A list-valued node whose typed value contains zero or more
                              strings (or <code nobreak="false">xs:anyURI</code> values), each of which is 
                              codepoint-equal to one of <code nobreak="false">"red"</code>, <code nobreak="false">"green"</code>,
                              or <code nobreak="false">"blue"</code>.</p>
                           </item>
                           <item>
                              <p>The <code nobreak="false">xs:anyURI</code> value <code nobreak="false">"red"</code>.</p>
                           </item>
                           <item>
                              <p>An array with zero or more members each of which 
                              is codepoint-equal to one of <code nobreak="false">"red"</code>, <code nobreak="false">"green"</code>,
                              or <code nobreak="false">"blue"</code>.</p>
                           </item>
                           <item>
                              <p>A JNode whose <term>·jvalue·</term> property is any of the above.</p>
                           </item>
                        </ulist>
                     </note>
                  </item>
                  <item>
                     <p>If <var>R</var> is derived from some primitive atomic type <var>P</var>, 
                     then <var>J</var> is <term>relabeled</term> as an instance of <var>R</var> if it satisfies
                     all the following conditions:</p>
                     <ulist>
                        <item>
                           <p>
                              <var>J</var> is an instance of <var>P</var>.</p>
                        </item>
                        <item>
                           <p>
                              <var>J</var> is not an instance of <var>R</var>.</p>
                        </item>
                        <item>
                           <p>The <xtermref spec="DM40" ref="dt-datum"/> of <var>J</var> is 
                           within the value space of <var>R</var>.</p>
                        </item>
                     </ulist>
                     <p>Relabeling an atomic item changes the <termref def="dt-type-annotation"/> but not the 
                        <xtermref spec="DM40" ref="dt-datum"/>. For example, the
                        <code nobreak="false">xs:integer</code> value 3 can be relabeled as an instance of <code nobreak="false">xs:unsignedByte</code>, because
                        the datum is within the value space of <code nobreak="false">xs:unsignedByte</code>.</p>
                     <note>
                        <p>Relabeling is not the same as casting. For example, the <code nobreak="false">xs:decimal</code> value 10.1
                        can be cast to <code nobreak="false">xs:integer</code>, but it cannot be relabeled as <code nobreak="false">xs:integer</code>,
                        because its datum not within the value space of <code nobreak="false">xs:integer</code>.</p>
                     </note>
                     <note>
                        <p>The effect of this rule is that if, for example, a function parameter is declared
                        with an expected type of <code nobreak="false">xs:positiveInteger</code>, then a call that supplies the literal
                        value 3 will succeed, whereas a call that supplies -3 will fail.</p>
                        <p>This differs from previous versions of this specification, where both these calls would fail.</p>
                        <p>This change allows the arguments of existing functions to be defined with a
                           
                           more precise type. For example, the <code nobreak="false">$position</code> argument of <function>array:get</function>
                           
                           could be defined as <code nobreak="false">xs:positiveInteger</code> 
                           rather than <code nobreak="false">xs:integer</code>.</p>
                     </note>
                     <note>
                        <p>If <var>T</var>
                           is a union type with members <code nobreak="false">xs:negativeInteger</code> and 
                           <code nobreak="false">xs:positiveInteger</code> and the supplied value is the
                           sequence <code nobreak="false">(20, -20)</code>, then the effect of these rules 
                           is that the first item <code nobreak="false">20</code> is relabeled as type
                           <code nobreak="false">xs:positiveInteger</code> and the second item <code nobreak="false">-20</code>is relabeled as type 
                           <code nobreak="false">xs:negativeInteger</code>.</p>
                     </note>
                     <note>
                        <p>Promotion (for example of <code nobreak="false">xs:float</code> to <code nobreak="false">xs:double</code>)
                        occurs only when <var>T</var> is a primitive type.
                        Relabeling occurs only when <var>T</var> is a derived type. Promotion and relabeling are therefore
                        never combined.</p>
                     </note>
                     <note>
                        <p>The value space of a <termref def="dt-singleton-enumeration-type"/> 
                           such as <code nobreak="false">enum("green")</code> includes the <code nobreak="false">xs:string</code> value <code nobreak="false">"green"</code>; so if the
                     <code nobreak="false">xs:string</code> value <code nobreak="false">"green"</code> is supplied in a context where
                     the required type is <code nobreak="false">enum("red", "green", "blue")</code>, the value will be
                        accepted.</p>
                     </note>
                  </item>
                  <item>
                     <p>If <var>J</var> is a <xtermref spec="DM40" ref="dt-JNode"/> and does not
                        match <var>R</var>,
                     then each item in the <term>·jvalue·</term> of <var>J</var> is coerced to type <var>R</var>
                     by applying the coercion rules recursively.</p>
                     <note>
                        <p>For example, if <code nobreak="false">$A</code> is an array and the members
                     of the array are maps, then <code nobreak="false">$A/child::*</code> returns a sequence
                     of JNodes that encapsulate maps, and the average size of these maps can be obtained 
                     using the expression <code nobreak="false">avg($A/child::* ! map:size(.))</code>. The first
                     argument of <code nobreak="false">map:size</code> does not accept a JNode directly, but
                     it does (in effect) accept a JNode that encapsulates a map.</p>
                     </note>
                  </item>
                  <item diff="add" at="A">
                     <p>If <var>R</var> is an <nt def="doc-xpath40-ArrayType">ArrayType<!--$spec = xpath40--></nt> other than <code nobreak="false">array(*)</code> and <var>J</var>
                        is an array, then <var>J</var> is converted to a new array by converting
                        each member to the required member type by applying the coercion rules
                        recursively.</p>
                     <note>
                        <p>For example, if the required type is
                     <code nobreak="false">array(xs:double)</code> and the supplied value is
                        <code nobreak="false">[ 1, 2 ]</code>, the array is converted to
                        <code nobreak="false">[ 1e0, 2e0 ]</code>.</p>
                     </note>
                  </item>
                  <item diff="add" at="A">
                     <p>If <var>R</var> is a <nt def="doc-xpath40-MapType">MapType<!--$spec = xpath40--></nt> other than <code nobreak="false">map(*)</code> and <var>J</var>
                        is a map, then <var>J</var> is converted to a new map as follows:</p>
                     <olist>
                        <item>
                           <p>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
                           <errorref class="TY" code="0004"/>.</p>
                        </item>
                        <item>
                           <p>The corresponding value is converted to the required
                           map value type by applying the coercion rules recursively.</p>
                        </item>
                        <item>
                           <p>The order of entries in the map remains unchanged.</p>
                        </item>
                     </olist>
                     <note>
                        <p>For example, if the required type is
                     <code nobreak="false">map(xs:string, xs:double)</code> and the supplied value is
                        <code nobreak="false">{ "x": 1, "y": 2 }</code>, the map is converted to
                        <code nobreak="false">{ "x": 1e0, "y": 2e0 }</code>.</p>
                     </note>
                     <note>
                        <p>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 <code nobreak="false">{ 1.2: 0, 1.2000001: 0 }</code>, which contains two keys
                        of type <code nobreak="false">xs:decimal</code>, is coerced to the type
                        <code nobreak="false">map(xs:float, xs:integer)</code>.</p>
                     </note>
                  </item>
                  <item diff="add" at="A">
                     <p>If <var>R</var> is a <nt def="doc-xpath40-RecordType">RecordType<!--$spec = xpath40--></nt> and <var>J</var> is a map, then <var>J</var> is converted
                        to a new map as follows:</p>
                     <olist>
                        <item>
                           <p>The keys in the supplied map are unchanged.</p>
                        </item>
                        <item>
                           <p>In any map entry whose key is equal to the
                        name of one of the field declarations in <var>R</var> (under the rules
                           of the <function>atomic-equal</function> 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).</p>
                        </item>
                        <item>
                           <p>Any map entry in the supplied map whose key is not equal to the name
                        of any of the field declarations in <var>R</var> (under the same rules) is
                        removed from the map.</p>
                        </item>
                        <item>
                           <p>The order of entries in the map is changed to match the order of the 
                              field declarations in <var>R</var>.</p>
                        </item>
                     </olist>
                     <note>
                        <p>For example, if the required type is
                     <code nobreak="false">record(longitude as xs:double, latitude as xs:double)</code> and the supplied value is 
                        <code nobreak="false">{ "latitude": 53.2, "longitude": 0, "altitude": 3_500 }</code>,
                        then the map is converted to <code nobreak="false">{ "longitude": 0.0e0, "latitude": 53.2e0 }</code>.</p>
                     </note>
                  </item>
                  <item>
                     <p>If <var>R</var> is a <nt def="prod-xpath40-TypedFunctionType">TypedFunctionType<!--$spec = xpath40--></nt> and <var>J</var> is a function item, then <termref def="dt-function-coercion">function coercion</termref> is applied to <var>J</var>.</p>
                     <note>
                        <p>Function coercion applies even if <var>J</var> is already an instance
                        of <var>R</var>.</p>
                        <p>Maps and arrays are functions, so function coercion applies to them as well.</p>
                     </note>
                  </item>
                  <item>
                     <p> If, after the
		above conversions, the resulting item does not match
		the expected item type <var>R</var> according to the rules for <termref def="dt-sequencetype-matching">SequenceType
		Matching</termref>, a type error is
		raised <errorref class="TY" code="0004"/>.</p>
                     <note diff="add" at="Issue602">
                        <p>Under the general rules for type errors 
                           (see <specref ref="id-kinds-of-errors"/>), a processor
                        <rfc2119>may</rfc2119> report a type error during static
                        analysis if it will necessarily occur when the expression is evaluated.
                        For example, the function call <code nobreak="false">fn:abs("beer")</code>
                        will necessarily fail when evaluated, because the function requires
                        a numeric value as its argument; this <rfc2119>may</rfc2119> be detected and reported
                        as a static error.</p>
                     </note>
                  </item>
               </olist>
            </div3>
            <div3 id="id-implausible-coercions" diff="add" at="2023-06-01">
               <head>Implausible Coercions</head>
               <p>An expression is deemed to be
                     <termref def="dt-implausible"/>
                  <errorref class="TY" code="0006"/> if the static type of the expression, after applying
                     all necessary coercions, is <term>substantively disjoint</term>
                     with the required type <var>T</var>.</p>
               <p>
                  <termdef id="dt-substantively-disjoint"
                           term="substantively disjoint"
                           open="true">Two 
               <termref def="dt-sequence-type">sequence types</termref> are
                     deemed to be <term>substantively disjoint</term> if (a) neither is a subtype
                     of the other (see <specref ref="id-seqtype-subtype"/>) and 
                     (b) the only values that
                     are instances of both types are one or more of the following:</termdef>
               </p>
               <ulist>
                  <item>
                     <p>The empty sequence, <code nobreak="false">()</code>.</p>
                  </item>
                  <item>
                     <p>The <xtermref spec="DM40" ref="dt-empty-map"/>, <code nobreak="false">{}</code>.</p>
                  </item>
                  <item>
                     <p>The <xtermref spec="DM40" ref="dt-empty-array"/>, <code nobreak="false">[]</code>.</p>
                  </item>
               </ulist>
               <p role="closetermdef"/>
               <note>
                  <p>Examples of pairs of sequence types that are substantively disjoint
                        include:</p>
                  <ulist>
                     <item>
                        <p>
                           <code nobreak="false">xs:integer*</code> and <code nobreak="false">xs:string*</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">map(xs:integer, node())</code> and <code nobreak="false">map(xs:string, node())</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">array(xs:integer)</code> and <code nobreak="false">array(xs:string)</code>
                        </p>
                     </item>
                  </ulist>
               </note>
               <p>For example, supplying a value whose static type is <code nobreak="false">xs:integer*</code>
                     when the required type is <code nobreak="false">xs:string*</code> is <termref def="dt-implausible"/>,
                     because it can succeed only in the special case where the actual value supplied
                     is the empty sequence.</p>
               <note>
                  <p>The case where the supplied type and the required type are completely
                  disjoint (for example <code nobreak="false">map(*)</code> and <code nobreak="false">array(*)</code>) is covered
                  by the general rules for type errors: that case can always be reported as a static
                  error.</p>
               </note>
               <p>Examples of implausible coercions include the following:</p>
               <ulist>
                  <item>
                     <p>
                        <code nobreak="false">round(timezone-from-time($now))</code>. The result of <function>fn:timezone-from-time</function>
                  is of type <code nobreak="false">xs:dayTimeDuration?</code>, which is substantively disjoint with the required type
                  of <function>fn:round</function>, namely <code nobreak="false">xs:numeric?</code>.</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">function($x as xs:integer) as array(xs:string) { array { 1 to $x } }</code>. The type
                  of the function body is <code nobreak="false">array(xs:integer)</code>, which is substantively disjoint with the
                  required type <code nobreak="false">array(xs:string)</code>: the function can succeed only in the exceptional case
                  where the function body delivers an <xtermref spec="DM40" ref="dt-empty-array"/>.</p>
                  </item>
               </ulist>
            </div3>
            <div3 id="id-function-coercion">
               <head>Function Coercion</head>
               <changes>
                  <change>
                     Function coercion now allows a function with arity <var>N</var> to be supplied where a function of arity 
                     greater than <var>N</var> is expected. For example this allows the function <code nobreak="false">true#0</code> 
                     to be supplied where a predicate function is required.
                  </change>
                  <change issue="1020" PR="1023 1128" date="2024-04-09">
                     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.
                  </change>
               </changes>
               <p>
        Function coercion is a transformation applied to <termref def="dt-function-item">function items</termref> during application of the
        <termref def="dt-coercion-rules">coercion rules</termref>.
        <termdef term="function coercion" id="dt-function-coercion">
                     <term>Function coercion</term> wraps a <termref def="dt-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.</termdef>
               </p>
               <p>Given a function <var>F</var>, and an expected function type <var>T</var>,
                  <termref def="dt-function-coercion">function coercion</termref>
	proceeds as follows:</p>
               <olist>
                  <item>
                     <p>If <var>F</var> has higher arity than <var>T</var>,
                     a type error is raised <errorref class="TY" code="0004"/>
                     </p>
                  </item>
                  <item diff="add" at="A">
                     <p>If <var>F</var> has lower arity than <var>T</var>,
                     then <var>F</var> is wrapped in a new function that declares and ignores the
                  additional argument; the following steps are then applied to this new function.</p>
                     <p>For example, if <var>T</var> is <code nobreak="false">function(node(), xs:boolean) as xs:string</code>,
                  and the supplied function is <function>fn:name#1</function>, then the supplied function is effectively
                  replaced by <code nobreak="false">function($n as node(), $b as xs:boolean) as xs:string { fn:name($n) }</code>
                     </p>
                     <note>
                        <p>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 <function>fn:filter</function> function expected an argument of type 
                     <code nobreak="false">function(item()) as xs:boolean</code>. This has now been extended to
                     <code nobreak="false">function(item(), xs:integer) as xs:boolean</code>, but existing code continues
                     to work, because callback functions that are not interested in the value of the second
                     argument simply ignore it.                    
                  </p>
                     </note>
                  </item>
                  <item>
                     <p>A type error is raised <errorref class="TY" code="0004"/> 
                        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 <termref def="dt-substantively-disjoint"/>.
                     </p>
                     <p>For example, the types <code nobreak="false">xs:integer</code> and <code nobreak="false">xs:string</code>
                     are substantively disjoint, so a function with signature <code nobreak="false">function(xs:integer) as xs:boolean</code>
                        cannot be supplied where the expected type is <code nobreak="false">function(xs:string) as xs:boolean</code>.</p>
                  </item>
                  <item>
                     <p>Function coercion then
        returns a new <termref def="dt-function-item"/>
        with the following properties
        (as defined in <xspecref spec="DM40" ref="function-items"/>):

        <ulist>
                           <item>
                              <p>
                                 <term>name</term>:
            The name of <var>F</var>
                                 <phrase diff="add" at="B">(if not absent)</phrase>.
          </p>
                           </item>
                           <item>
                              <p diff="add" at="2023-05-25">
                                 <term>identity</term>: A new function
              identity distinct from the identity of any other function item.</p>
                              <note>
                                 <p>See also <specref ref="id-function-identity"/>.</p>
                              </note>
                           </item>
                           <item>
                              <p>
                                 <term>signature</term>:
            <code nobreak="false">Annotations</code> is set to the annotations of <var>F</var>. <code nobreak="false">TypedFunctionType</code> is set to the expected type.
          </p>
                           </item>
                           <item>
                              <p>
                                 <term>implementation</term>:
            In effect,
            a <code nobreak="false">FunctionBody</code> that calls <var>F</var>,
            passing it the parameters of this new function,
            in order.
          </p>
                           </item>
                           <item>
                              <p>
                                 <term>nonlocal variable bindings</term>:
            An empty mapping.
          </p>
                           </item>
                        </ulist>
                     </p>
                  </item>
               </olist>
               <!--<p>
        If the result of invoking the new function would
        necessarily result in a type error, that
        error may be raised during
                  <termref
                     def="dt-function-coercion"
                  >function coercion</termref>. It is implementation dependent whether this
        happens or not.
      </p>-->
               <p>
        These rules have the following consequences:

        <ulist>
                     <item>
                        <p>SequenceType matching of the function’s arguments and result are delayed until that function is called.
          </p>
                     </item>
                     <item>
                        <p>When the coerced function is called, the supplied arguments must match the parameter
              typed defined in <var>T</var>; it is not sufficient to match the parameter types defined
              in <var>F</var>.</p>
                     </item>
                     <item>
                        <p>
                           The <termref def="dt-coercion-rules">coercion rules</termref> 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.
          </p>
                     </item>
                     <item>
                        <p>
            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.
          </p>
                     </item>
                     <item>
                        <p>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 </p>
                        <eg xml:space="preserve">let $f as function(xs:integer) as xs:boolean := { 0: false(), 1: true() }
return $f?0</eg>
                        <p>raises a type error, because a lookup expression requires the left hand
           operand to be a map or array, and <code nobreak="false">$f</code> is neither.</p>
                     </item>
                     <item>
                        <p>When function types are used as alternatives in a <termref def="dt-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. </p>
                     </item>
                  </ulist>
               </p>
               <note>
                  <p>
                     The semantics of <termref def="dt-function-coercion">function coercion</termref> 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.
      </p>
               </note>
               <p>Since maps and arrays are also functions in XPath 4.0, 
                  <termref def="dt-function-coercion">function coercion</termref> applies to them as well.

        For instance, consider the following expression:
      </p>
               <eg role="parse-test" xml:space="preserve">
let $m := {
  "Monday" : true(),
  "Wednesday" : false(),
  "Friday" : true()
}
let $days := ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday")
return filter($days, $m)
      </eg>
               <p>
        The map <code nobreak="false">$m</code> is an instance of 
                  <code nobreak="false">function(xs:anyAtomicType?) as item()*</code>. 
                  When the <code nobreak="false">fn:filter()</code> function is called, the following 
                  occurs to the map:

<olist>
                     <item>
                        <p>The map <code nobreak="false">$m</code> is treated as a function equivalent to <code nobreak="false">map:get($m, ?)</code>.</p>
                     </item>
                     <item>
                        <p>The <termref def="dt-coercion-rules">coercion rules</termref> result in applying 
                           <termref def="dt-function-coercion">function coercion</termref> 
                           to this function, wrapping it in a new function (<var>M'</var>) with the 
                           signature <code nobreak="false">function(item(), xs:integer) as xs:boolean</code>.</p>
                     </item>
                     <item>
                        <p>When <var>M'</var> is called by <code nobreak="false">fn:filter()</code>, <termref def="dt-coercion-rules">coercion</termref> 
                           and SequenceType matching rules are applied to the argument, 
                           resulting in an <code nobreak="false">item()</code> value 
                           (<code nobreak="false">$a</code>) or a type error.</p>
                     </item>
                     <item>
                        <p>
                           The function <code nobreak="false">map:get($m, ?)</code> is called with <code nobreak="false">$a</code>
                           as the argument; this returns either an <code nobreak="false">xs:boolean</code> or the empty sequence
                           (call the result <var>R</var>).</p>
                     </item>
                     <item>
                        <p>
                           The wrapper function <code nobreak="false">$p</code> applies the <termref def="dt-coercion-rules"/>
                              to <var>R</var>. If <var>R</var> is an <code nobreak="false">xs:boolean</code> the matching succeeds. 
                              When it is the empty sequence (in particular, <code nobreak="false">$m</code> does not contain a 
                           key for <code nobreak="false">"Tuesday"</code>), a type error is raised <errorref class="TY" code="0004"/>, since the expected type is <code nobreak="false">xs:boolean</code>, 
                           which does not allow the empty sequence.</p>
                     </item>
                  </olist>
               </p>
               <p>Consider the following expression:
      </p>
               <eg role="parse-test" xml:space="preserve">

let $m := {
   "Monday" : true(),
   "Wednesday" : false(),
   "Friday" : true(),
}
let $days := ("Monday", "Wednesday", "Friday")
return filter($days, $m)
      </eg>
               <p>In this case the result of the expression is the sequence <code nobreak="false">("Monday", "Friday")</code>.
                  But if the input sequence included the string <code nobreak="false">"Tuesday"</code>, the filter operation
                  would fail with a type error.
               </p>
               <note diff="add" at="issue1020">
                  <p>Function coercion applies even if the supplied function matches the required type.</p>
                  <p>For example, consider this case:</p>
                  <eg role="parse-test" xml:space="preserve">
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)
      </eg>
                  <p>Here the supplied function <code nobreak="false">$f</code> is an instance of the required type,
                  because its signature defaults the argument type to <code nobreak="false">item()*</code>, which
                  is a supertype of <code nobreak="false">xs:string</code>. The expression <code nobreak="false">$s[$p(.)]</code>
                  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 <code nobreak="false">xs:string</code>,
                  so the call fails with a type error when the wrapping function is invoked supplying an
                  <code nobreak="false">xs:integer</code> as the argument.</p>
               </note>
            </div3>
            <div3 id="id-coercion-examples">
               <head>Examples of Coercions</head>
               <p>This section illustrates the effect of the coercion rules with examples.</p>
               <example id="eg-coercion-to-string">
                  <head>Coercion to <code nobreak="false">xs:string</code>
                  </head>
                  <p>Consider the case where the required type (of a variable, or a function argument)
                  is <code nobreak="false">xs:string</code>. For example, the second argument of <function>fn:matches</function>,
                  which expects a regular expression. The table below illustrates the values that might be supplied, and
                  the coercions that are applied.</p>
                  <table role="medium">
                     <thead>
                        <tr>
                           <th align="left" rowspan="1" colspan="1">Supplied Value</th>
                           <th align="left" rowspan="1" colspan="1">Coercion</th>
                        </tr>
                     </thead>
                     <tbody>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">"[0-9]"</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>None; the supplied value is an instance of the required type.</p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">default-language()</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>None; the supplied value is an instance of <code nobreak="false">xs:language</code>, which
                              is a subtype of the required type <code nobreak="false">xs:string</code>.</p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">&lt;a&gt;[0-9]&lt;/a&gt;</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>The supplied element node is atomized. Unless it has been schema-validated,
                           the typed value will be an instance of <code nobreak="false">xs:untypedAtomic</code>, which
                           is accepted when the required type is <code nobreak="false">xs:string</code>.</p>
                              <p>Supplying an element whose type annotation is (say) <code nobreak="false">xs:date</code> 
                                 will fail with a type error.</p>
                              <p role="xpath">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 <code nobreak="false">xs:string</code>.</p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">xs:anyURI("urn:dummy")</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>Supplying an instance of <code nobreak="false">xs:anyURI</code> where the expected type
                              is <code nobreak="false">xs:string</code> is permitted; this is one of the pairs of types
                           where implicit casting is allowed.</p>
                           </td>
                        </tr>
                        <tr role="xpath">
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">17.2</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>Supplying a number where a string is expected raises a type error.</p>
                              <p role="xpath">However, if XPath 1.0
                              compatibility mode is enabled, the number is converted to a string as if
                           by the <function>fn:string</function> function.</p>
                           </td>
                        </tr>
                        <tr role="xpath">
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">//author/@id</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>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
                              <code nobreak="false">xs:string</code>, <code nobreak="false">xs:untypedAtomic</code>, or <code nobreak="false">xs:anyURI</code>).</p>
                              <p role="xpath">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.</p>
                           </td>
                        </tr>
                        <tr role="xpath">
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">("red", "green", "blue")</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>Supplying a sequence of strings where a single string is expected 
                              raises a type error.</p>
                              <p role="xpath">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 <code nobreak="false">"red"</code>.</p>
                           </td>
                        </tr>
                        <tr role="xpath">
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">()</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>Supplying the empty sequence where a single string is expected will fail.</p>
                              <p role="xpath">If XPath 1.0 compatibility mode is enabled, however, the value is coerced by
                                 applying the function <code nobreak="false">fn:string(())</code>,
                                 which delivers the zero-length string.</p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">["a|b"]</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>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.</p>
                              <p>Supplying an array holding multiple strings would fail.</p>
                              <p role="xpath">In XPath 1.0 compatibility mode, supplying an array will fail, 
                                 regardless of the array contents, because the <function>fn:string</function> function does not 
                                 accept arrays.</p>
                           </td>
                        </tr>
                     </tbody>
                  </table>
               </example>
               <example id="eg-coercion-to-decimal">
                  <head>Coercion to <code nobreak="false">xs:decimal?</code>
                  </head>
                  <p>Consider the case where the required type (of a variable, or a function argument)
                     is <code nobreak="false">xs:decimal?</code>. For example, the first argument of <function>fn:seconds</function>,
                     which expects a decimal number of seconds. The table below illustrates the values that might be supplied, and
                     the coercions that are applied.</p>
                  <table role="medium">
                     <thead>
                        <tr>
                           <th align="left" rowspan="1" colspan="1">Supplied Value</th>
                           <th align="left" rowspan="1" colspan="1">Coercion</th>
                        </tr>
                     </thead>
                     <tbody>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">12.4</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>None; the supplied value is an instance of the required type.</p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">()</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>None; the empty sequence is an instance of the required type.</p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">42</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>None; the supplied value is an instance of <code nobreak="false">xs:integer</code>,
                              which is a subtype of the required type.</p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">math:pi()</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>The supplied value is an instance of <code nobreak="false">xs:double</code>,
                              which can be converted to <code nobreak="false">xs:decimal</code> under the coercion rules.</p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">("a", "b")[.="c"]</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>The supplied value is the empty sequence, which is a valid
                              instance of the required type <code nobreak="false">xs:decimal?</code>. 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. </p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">(1.5, 2.5, 3.5)</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>A type error is raised<phrase role="xpath">, except in the case where XPath 1.0
                           compatibility is enabled, in which case all values after the first are discarded</phrase>.</p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">&lt;a&gt;3.14159&lt;/a&gt;</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>The element node is atomized; unless it has been schema-validated, the
                              result will be <code nobreak="false">"3.14159"</code> as an instance of <code nobreak="false">xs:untypedAtomic</code>.
                             This is converted to an instance of <code nobreak="false">xs:decimal</code> following the rules
                           of the <code nobreak="false">cast as</code> operator.</p>
                           </td>
                        </tr>
                        <tr role="xpath">
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">"12.2"</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>Supplying a string where an <code nobreak="false">xs:decimal</code> is a type error<phrase role="xpath">,
                              even if XPath 1.0 compatibility mode is enabled. The rules for compatibility
                              mode would allow conversion if the required type were <code nobreak="false">xs:double</code>,
                              but not for <code nobreak="false">xs:decimal</code>
                                 </phrase>.
                        </p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">[1.5]</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>The array is atomized, and the result is a valid instance of the required
                           type <code nobreak="false">xs:decimal?</code>
                              </p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">[]</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>The array is atomized, and the result is the empty sequence, which is a valid instance of the required
                              type <code nobreak="false">xs:decimal?</code>
                              </p>
                           </td>
                        </tr>
                     </tbody>
                  </table>
               </example>
               <example id="eg-coercion-to-positive-integer">
                  <head>Coercion to <code nobreak="false">xs:positive-integer</code>
                  </head>
                  <p>Consider the case where the required type (of a variable, or a function argument)
                     is <code nobreak="false">xs:positive-integer</code>. The table below illustrates the values that might be supplied, and
                     the coercions that are applied.</p>
                  <table role="medium">
                     <thead>
                        <tr>
                           <th align="left" rowspan="1" colspan="1">Supplied Value</th>
                           <th align="left" rowspan="1" colspan="1">Coercion</th>
                        </tr>
                     </thead>
                     <tbody>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">12</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>The supplied value is of type <code nobreak="false">xs:integer</code>. Because the supplied value and
                              the required type, <code nobreak="false">xs:positiveInteger</code>, both come under the primitive
                           type <code nobreak="false">xs:decimal</code>, and the value <code nobreak="false">12</code> is within the value space
                           of <code nobreak="false">xs:positiveInteger</code>, the value is relabeled as an <code nobreak="false">xs:positiveInteger</code>
                           and the call succeeds.</p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">12.1</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>This fails with a type error, because the <code nobreak="false">xs:decimal</code> value <code nobreak="false">12.1</code>
                              is not a value in the value space of <code nobreak="false">xs:positiveInteger</code>. This is so even though
                           casting to <code nobreak="false">xs:positiveInteger</code> would succeed.</p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">math:pi()</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>This fails with a type error. A value of type <code nobreak="false">xs:double</code> is accepted
                           where the required type is <code nobreak="false">xs:decimal</code> or <code nobreak="false">xs:float</code>,
                           but not where it is <code nobreak="false">xs:positiveInteger</code>.</p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">&lt;a&gt;1200&lt;/a&gt;</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>The supplied element node is atomized. If the element has not been schema-validated,
                           the result will be an <code nobreak="false">xs:untypedAtomic</code> item, which is successfully cast to the
                           required type <code nobreak="false">xs:positiveInteger</code>. 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 <code nobreak="false">xs:positiveInteger</code>, or some other <code nobreak="false">xs:decimal</code> within the value space
                           of <code nobreak="false">xs:positiveInteger</code>.</p>
                           </td>
                        </tr>
                     </tbody>
                  </table>
               </example>
               <example id="eg-coercion-to-union">
                  <head>Coercion to a union type</head>
                  <p>Consider the first parameter of the function <function>fn:char</function>, whose declared
                  type is <code nobreak="false">(xs:string | xs:positiveInteger)</code>. The rules are the same
                  as if it were a union typed declared in an imported schema.</p>
                  <table role="medium">
                     <thead>
                        <tr>
                           <th align="left" rowspan="1" colspan="1">Supplied Value</th>
                           <th align="left" rowspan="1" colspan="1">Coercion</th>
                        </tr>
                     </thead>
                     <tbody>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">"amp"</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>The supplied value is of type <code nobreak="false">xs:string</code>, which is one of the allowed
                           types. The call therefore succeeds.</p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">"#"</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>The supplied value is of type <code nobreak="false">xs:string</code>, 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 <function>fn:char</function> function, however, this value is not accepted;
                              a dynamic error (as distinct from a type error) is therefore raised.</p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">0x25</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>The supplied value is of type <code nobreak="false">xs:integer</code>. Although this is not one of the allowed
                              types, it is acceptable because coercion of the value to type <code nobreak="false">xs:positiveInteger</code>
                              succeeds. The value is relabeled as an instance of <code nobreak="false">xs:positiveInteger</code>.</p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">&lt;a&gt;0x25&lt;/a&gt;</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>The supplied element node is atomized. Assuming that the node has not been schema-validated,
                              the result is an instance of <code nobreak="false">xs:untypedAtomic</code>. The member types of the choice
                              are tested in order. Conversion to <code nobreak="false">xs:string</code> with the value "0x25" succeeds, so 
                              the <function>fn:char</function> function is called supplying this string; but the function rejects this
                              string as semantically invalid. The same would happen if the value were, say, &lt;a&gt;37&lt;/a&gt;.
                              Supplying such a value requires an explicit cast, for example <code nobreak="false">fn:char( xs:positiveInteger( ./a ))</code>.</p>
                           </td>
                        </tr>
                     </tbody>
                  </table>
               </example>
               <example id="eg-coercion-to-choice">
                  <head>Coercion to a choice type</head>
                  <p>Suppose the required type is <code nobreak="false">(record(x as xs:decimal, y as xs:decimal, *) | record(size as enum("S", "M", "L", "XL"), *))</code>.</p>
                  <table role="medium">
                     <col width="40%" span="1"/>
                     <col width="60%" span="1"/>
                     <thead>
                        <tr>
                           <th align="left" rowspan="1" colspan="1">Supplied Value</th>
                           <th align="left" rowspan="1" colspan="1">Coercion</th>
                        </tr>
                     </thead>
                     <tbody>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">{ "x": 1, "y": 2, "z": 3 }</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>The supplied value is an instance of the first record type: no coercion is necessary.</p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">{ "size": "M" }</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>The supplied value is an instance of the second record type: no coercion is necessary.</p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">{ "x": 1, "y": 2, "size": "XL" }</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>The supplied value is an instance of both record types: no coercion is necessary.</p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">{ "x": 1e0, "y": 2e0, "size": "XL" }</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>The supplied value is not an instance of the first record type because the fields are of
                              type <code nobreak="false">xs:double</code> rather than <code nobreak="false">xs:decimal</code>. It is however an instance
                              of the second record type. It is therefore accepted <emph>as is</emph>; the fields
                           <code nobreak="false">x</code> and <code nobreak="false">y</code> are not converted from <code nobreak="false">xs:double</code> to
                           <code nobreak="false">xs:decimal</code>.</p>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">{ "x": 1e0, "y": 2e0, "size": "XXL" }</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <p>The supplied value is not an instance of the first record type because the fields are of
                              type <code nobreak="false">xs:double</code> rather than <code nobreak="false">xs:decimal</code>, and it is not an instance
                              of the second record type because the <code nobreak="false">size</code> value does not match the enumeration
                              type. Coercion is therefore attempted to the first record type, and succeeds. The <code nobreak="false">x</code>
                           and <code nobreak="false">y</code> fields are coerced to <code nobreak="false">xs:decimal</code>, and the <code nobreak="false">size</code> field
                           is accepted <emph>as is</emph>.</p>
                           </td>
                        </tr>
                     </tbody>
                  </table>
               </example>
            </div3>
         </div2>
         <div2 id="id-predefined-types">
            <head>Schema Types</head>
            <p>
               <termdef id="dt-schema-type" term="schema type">A <term>schema type</term>
            is a complex type or simple type as defined in the <bibref ref="XMLSchema10"/> or <bibref ref="XMLSchema11"/> specifications, including built-in types as well as user-defined types.</termdef>
            </p>
            <p>Every schema type is either a <term>complex type</term> or a
            <term>simple type</term>; simple types are further subdivided into <term>list types</term>, <term>union
               types</term>, and <term>atomic types</term> (see <bibref ref="XMLSchema10"/> or <bibref ref="XMLSchema11"/> for definitions and explanations of these terms.)</p>
            <p>A schema type can appear as a type annotation on an
            element or attribute node. The type annotation on an element node can be
            a complex type or a simple type; the type annotation on an attribute node
            is always a simple type. Non-instantiable types such as <code nobreak="false">xs:NOTATION</code> or
            <code nobreak="false">xs:anyAtomicType</code> never appear as type annotations, but their derived
            types can be so used. Union types never appear as type annotations; when
            an element or attribute is validated against a union type, the resulting
            type annotation will be one of the types in the transitive membership of 
            the union type.</p>
            <p>
               <termdef id="dt-atomic-type" term="atomic type">An <term>atomic type</term>
            is a simple <termref def="dt-schema-type"/> whose 
            <xtermref spec="XS11-1" ref="std-variety">{variety}</xtermref>
            is <code nobreak="false">atomic</code>.</termdef>
            </p>
            <p>An <term>atomic type</term> is either a built-in atomic
            type (defined either in the XSD specification or in this specification), or
            it is a user-defined atomic type included in an imported schema.</p>
            <p role="xpath">The <termref def="dt-is-types">in-scope schema types</termref>
            in the <termref def="dt-static-context">static
               context</termref> are initialized with a set of
            predefined schema types that is determined by the host
            language. This set may include some or all of the
            schema types in the
            namespace
            <code nobreak="false">http://www.w3.org/2001/XMLSchema</code>,
            represented in this document by the namespace prefix
            <code nobreak="false">xs</code>. The schema types in this namespace are defined in <bibref ref="XMLSchema10"/> or <bibref ref="XMLSchema11"/>
            and augmented by additional types defined in <bibref ref="xpath-datamodel-40"/>. An implementation
            that has based its type system on <bibref ref="XMLSchema10"/> is not required to support the <code nobreak="false">xs:dateTimeStamp</code> or <code nobreak="false">xs:error</code> types.</p>
            <p>The schema types defined in  <xspecref spec="DM40" ref="types-predefined"/> are summarized below.</p>
            <olist>
               <item>
                  <p>
                     <termdef term="xs:untyped" id="dt-untyped">
                        <code nobreak="false">xs:untyped</code> is  used as the <termref def="dt-type-annotation">type annotation</termref> of an element node that has not been validated, or has been validated in <code nobreak="false">skip</code> mode.</termdef> 
                  No predefined schema types are derived from <code nobreak="false">xs:untyped</code>.</p>
               </item>
               <item>
                  <p>
                     <termdef id="dt-untypedAtomic" term="xs:untypedAtomic">
                        <code nobreak="false">xs:untypedAtomic</code>
                     is an <termref def="dt-atomic-type"/> that is used to denote untyped atomic data, 
                     such as text that has not been assigned a more specific type.</termdef> 
                  An attribute that has been validated in <code nobreak="false">skip</code> mode is represented in the <termref def="dt-datamodel">data model</termref> by an attribute node with the <termref def="dt-type-annotation">type annotation</termref>
                     <code nobreak="false">xs:untypedAtomic</code>. No predefined schema types are derived from <code nobreak="false">xs:untypedAtomic</code>.</p>
               </item>
               <item>
                  <p>
                     <termdef term="xs:dayTimeDuration" id="dt-dayTimeDuration">
                        <code nobreak="false">xs:dayTimeDuration</code> is derived by restriction from <code nobreak="false">xs:duration</code>. The  lexical representation of <code nobreak="false">xs:dayTimeDuration</code>
                     is restricted to contain only day, hour, minute, and second
                     components.</termdef>
                  </p>
               </item>
               <item>
                  <p>
                     <termdef term="xs:yearMonthDuration" id="dt-yearMonthDuration">
                        <code nobreak="false">xs:yearMonthDuration</code> is derived by restriction from <code nobreak="false">xs:duration</code>. The lexical representation of <code nobreak="false">xs:yearMonthDuration</code> is
                     restricted to contain only year and month
                     components.</termdef>
                  </p>
               </item>
               <item>
                  <p>
                     <termdef term="xs:anyAtomicType" id="dt-anyAtomicType">
                        <code nobreak="false">xs:anyAtomicType</code> is an <termref def="dt-atomic-type"/> 
                     that includes all atomic items (and no values that
                     are not atomic). Its base type is
                     <code nobreak="false">xs:anySimpleType</code> from which all simple types, including atomic,
                     list, and union types, are derived. All primitive atomic types, such as
                     <code nobreak="false">xs:decimal</code> and <code nobreak="false">xs:string</code>, have <code nobreak="false">xs:anyAtomicType</code> as their base type.</termdef>
                  </p>
                  <note>
                     <p>
                        <code nobreak="false">xs:anyAtomicType</code>  will not appear as the type of an actual value in an <termref def="dt-data-model-instance">XDM instance</termref>.</p>
                  </note>
               </item>
               <item>
                  <p>
                     <termdef term="xs:error" id="dt-xs-error">
                        <code nobreak="false">xs:error</code> is a simple type with no value space.  It is defined in <xspecref spec="XS11-1" ref="xsd-error"/> and  can be used in the <specref ref="id-sequencetype-syntax"/> to raise errors.</termdef>
                  </p>
               </item>
            </olist>
            <p>The relationships among the schema types in the <code nobreak="false">xs</code> namespace are illustrated in Figure 2. A more complete description of the XPath 4.0 type hierarchy can be found in 
            <xspecref spec="FO40" ref="datatypes"/>.</p>
            <graphic xmlns:xlink="http://www.w3.org/1999/xlink"
                     source="types.jpg"
                     alt="Type Hierarchy Diagram"
                     xlink:type="simple"
                     xlink:show="embed"
                     xlink:actuate="onLoad"/>
            <p>Figure 2: Hierarchy of Schema Types used in XPath 4.0.</p>
         </div2>
      </div1>
      <div1 id="id-expressions">
         <head>Expressions</head>
         <p>This section discusses each of the basic kinds of expression. Each kind of expression has a name such as <code nobreak="false">PathExpr</code>, 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.</p>
         <p>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 [<specref ref="nt-bnf"/>].</p>
         <p>
            <phrase role="xpath">The highest-level symbol in the XPath grammar is XPath.</phrase>
         </p>
         <scrap role="xpath" headstyle="show">
            <prod id="doc-xpath40-XPath">
               <lhs>XPath</lhs>
               <rhs>(<nt def="prod-xpath40-DefaultElementNamespaceDecl">DefaultElementNamespaceDecl<!--$idref_lang_part = xpath40- --></nt>  ";")?  (<nt def="prod-xpath40-NamespaceDecl">NamespaceDecl<!--$idref_lang_part = xpath40- --></nt>  ";")*  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>
               </rhs>
            </prod>

            <prod id="doc-xpath40-XPath-DefaultElementNamespaceDecl">
               <lhs>DefaultElementNamespaceDecl</lhs>
               <rhs>"declare"  "default"  "element"  "namespace"  <nt def="prod-xpath40-URILiteral">URILiteral<!--$idref_lang_part = xpath40- --></nt>
               </rhs>
            </prod>

            <prod id="doc-xpath40-XPath-NamespaceDecl">
               <lhs>NamespaceDecl</lhs>
               <rhs>"declare"  "namespace"  <nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>  "="  <nt def="prod-xpath40-URILiteral">URILiteral<!--$idref_lang_part = xpath40- --></nt>
               </rhs>
            </prod>

            <prod id="doc-xpath40-XPath-Expr">
               <lhs>Expr</lhs>
               <rhs>(<nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt> ++ ",")</rhs>
            </prod>
         </scrap>
         <p role="xpath">The effect of a <nt def="doc-xpath40-DefaultElementNamespaceDecl">DefaultElementNamespaceDecl<!--$spec = xpath40--></nt> or
      <nt def="doc-xpath40-NamespaceDecl">NamespaceDecl<!--$spec = xpath40--></nt> is described in <specref ref="namespace-declarations"/>.</p>
         <scrap headstyle="show">
            <prod id="doc-xpath40-ExprSingle">
               <lhs>ExprSingle</lhs>
               <rhs>
                  <nt def="prod-xpath40-ForExpr">ForExpr<!--$idref_lang_part = xpath40- --></nt>
                  <br/>|  <nt def="prod-xpath40-LetExpr">LetExpr<!--$idref_lang_part = xpath40- --></nt>
                  <br/>|  <nt def="prod-xpath40-QuantifiedExpr">QuantifiedExpr<!--$idref_lang_part = xpath40- --></nt>
                  <br/>|  <nt def="prod-xpath40-IfExpr">IfExpr<!--$idref_lang_part = xpath40- --></nt>
                  <br/>|  <nt def="prod-xpath40-OrExpr">OrExpr<!--$idref_lang_part = xpath40- --></nt>
               </rhs>
            </prod>

            <prod id="doc-xpath40-ExprSingle-ForExpr">
               <lhs>ForExpr</lhs>
               <rhs>
                  <nt def="prod-xpath40-ForClause">ForClause<!--$idref_lang_part = xpath40- --></nt>
                  <nt def="prod-xpath40-ForLetReturn">ForLetReturn<!--$idref_lang_part = xpath40- --></nt>
               </rhs>
            </prod>

            <prod id="doc-xpath40-ExprSingle-LetExpr">
               <lhs>LetExpr</lhs>
               <rhs>
                  <nt def="prod-xpath40-LetClause">LetClause<!--$idref_lang_part = xpath40- --></nt>
                  <nt def="prod-xpath40-ForLetReturn">ForLetReturn<!--$idref_lang_part = xpath40- --></nt>
               </rhs>
            </prod>

            <prod id="doc-xpath40-ExprSingle-QuantifiedExpr">
               <lhs>QuantifiedExpr</lhs>
               <rhs>("some"  |  "every")  (<nt def="prod-xpath40-QuantifierBinding">QuantifierBinding<!--$idref_lang_part = xpath40- --></nt> ++ ",")  "satisfies"  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>
               </rhs>
            </prod>

            <prod id="doc-xpath40-ExprSingle-IfExpr">
               <lhs>IfExpr</lhs>
               <rhs>"if"  "("  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>  ")"  (<nt def="prod-xpath40-UnbracedActions">UnbracedActions<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-BracedAction">BracedAction<!--$idref_lang_part = xpath40- --></nt>)</rhs>
            </prod>

            <prod id="doc-xpath40-ExprSingle-OrExpr">
               <lhs>OrExpr</lhs>
               <rhs>
                  <nt def="prod-xpath40-AndExpr">AndExpr<!--$idref_lang_part = xpath40- --></nt>  ("or"  <nt def="prod-xpath40-AndExpr">AndExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
            </prod>
         </scrap>
         <p>The XPath 4.0 operator that has lowest precedence is the <termref def="dt-comma-operator">comma operator</termref>, which is used to combine two operands to form a sequence. 
         As shown in the grammar, a general expression (<nt def="doc-xpath40-Expr">Expr<!--$spec = xpath40--></nt>) can consist of multiple <nt def="doc-xpath40-ExprSingle">ExprSingle<!--$spec = xpath40--></nt> operands, separated by commas.</p>
         <p>The name <nt def="doc-xpath40-ExprSingle">ExprSingle<!--$spec = xpath40--></nt> denotes an expression that does not contain a top-level <termref def="dt-comma-operator">comma operator</termref> (despite its name, an <nt def="doc-xpath40-ExprSingle">ExprSingle<!--$spec = xpath40--></nt> may evaluate to a sequence containing more than one item.)</p>
         <p>The symbol <nt def="doc-xpath40-ExprSingle">ExprSingle<!--$spec = xpath40--></nt> 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 <nt def="doc-xpath40-ExprSingle">ExprSingle<!--$spec = xpath40--></nt>, because commas are 
         used to separate the arguments of a function call.</p>
         <p>After the comma, the expressions that have next lowest precedence are

         <phrase role="xpath">
               <nt def="doc-xpath40-ForExpr">ForExpr<!--$spec = xpath40--></nt>, <nt def="doc-xpath40-LetExpr">LetExpr<!--$spec = xpath40--></nt>, </phrase>
            <nt def="doc-xpath40-QuantifiedExpr">QuantifiedExpr<!--$spec = xpath40--></nt>,

         <nt def="doc-xpath40-IfExpr">IfExpr<!--$spec = xpath40--></nt>,

and <nt def="doc-xpath40-OrExpr">OrExpr<!--$spec = xpath40--></nt>. Each of these expressions is described in a separate section of this document.</p>
         <div2 id="namespace-declarations" role="xpath">
            <head>Namespace Declarations</head>
            <changes>
               <change issue="2179" date="2025-09-04">
               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.
            </change>
            </changes>
            <p>An XPath 4.0 expression may be preceded by a set of namespace declarations: specifically,
         an optional default namespace declaration, followed by zero or more bindings of specific
         namespace prefixes to specific namespace URIs.</p>
            <scrap role="xpath" headstyle="show">
               <prod id="doc-xpath40-DefaultElementNamespaceDecl">
                  <lhs>DefaultElementNamespaceDecl</lhs>
                  <rhs>"declare"  "default"  "element"  "namespace"  <nt def="prod-xpath40-URILiteral">URILiteral<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-DefaultElementNamespaceDecl-URILiteral">
                  <lhs>URILiteral</lhs>
                  <rhs>
                     <nt def="doc-xpath40-StringLiteral">StringLiteral<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-DefaultElementNamespaceDecl-StringLiteral">
                  <lhs>StringLiteral</lhs>
                  <rhs>
                     <nt def="prod-xpath40-AposStringLiteral">AposStringLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-QuotStringLiteral">QuotStringLiteral<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
                  <com>
                     <loc href="#ws-explicit">ws: explicit</loc>
                  </com>
               </prod>

               <prod id="doc-xpath40-NamespaceDecl">
                  <lhs>NamespaceDecl</lhs>
                  <rhs>"declare"  "namespace"  <nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>  "="  <nt def="prod-xpath40-URILiteral">URILiteral<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-NamespaceDecl-URILiteral">
                  <lhs>URILiteral</lhs>
                  <rhs>
                     <nt def="doc-xpath40-StringLiteral">StringLiteral<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-NamespaceDecl-StringLiteral">
                  <lhs>StringLiteral</lhs>
                  <rhs>
                     <nt def="prod-xpath40-AposStringLiteral">AposStringLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-QuotStringLiteral">QuotStringLiteral<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
                  <com>
                     <loc href="#ws-explicit">ws: explicit</loc>
                  </com>
               </prod>
            </scrap>
            <p>These namespace declarations are added to the <termref def="dt-static-context"/> of the expression, overriding any namespace bindings
         initialized by the host language.</p>
            <p>Specifically, if there is a <nt def="doc-xpath40-DefaultElementNamespaceDecl">DefaultNamespaceDecl<!--$spec = xpath40--></nt> then
         the relevant URI is set in the <termref def="dt-static-context"/> as the <termref def="dt-default-namespace-elements-and-types"/>,
         while a <nt def="doc-xpath40-NamespaceDecl">NamespaceDecl<!--$spec = xpath40--></nt> establishes a namespace binding from
         the given prefix to the given URI in the <termref def="dt-static-namespaces"/>.</p>
            <p>The namespace URI specified in a namespace declaration must not be
        <code nobreak="false">http://www.w3.org/XML/1998/namespace</code> or
        <code nobreak="false">http://www.w3.org/2000/xmlns/</code>, and the namespace prefix must not be
            <code nobreak="false">xml</code> or <code nobreak="false">xmlns</code>
               <errorref spec="XQ" class="ST" code="0070"/>.</p>
            <p>The namespace prefixes defined in namespace declarations must be distinct
            <errorref spec="XQ" class="ST" code="0033"/>.</p>
            <p>A <term>default element namespace declaration</term> declares how unprefixed element and type
          names are to be interpreted. The <code nobreak="false">URILiteral</code> may take one of the following forms:</p>
            <ulist>
               <item>
                  <p>A namespace URI. This namespace will typically be used for unprefixed names appearing
            where an element or type name is expected.</p>
               </item>
               <item>
                  <p>The empty string <code nobreak="false">""</code>. In this case unprefixed names appearing where
              an element or type name is expected are treated as being in no namespace: the
              <termref def="dt-default-namespace-elements-and-types"/> is set to <xtermref spec="DM40" ref="dt-absent"/>.</p>
               </item>
               <item>
                  <p>The string <code nobreak="false">"##any"</code>. In this case an unprefixed name appearing
              as a <nt def="prod-xpath40-NameTest">NameTest<!--$spec = xpath40--></nt> in an axis step whose principal node kind is element
              is interpreted as a wildcard (the unprefixed name <code nobreak="false">N</code> is treated as equivalent
              to the wildcard <code nobreak="false">*:N</code>); an unprefixed name used appearing where an item type name
              is expected is interpreted as a local name in namespace <code nobreak="false">http://www.w3.org/2001/XMLSchema</code>,
              while an unprefixed name appearing in any other context
              where an element or type name is expected is treated as being in no namespace.</p>
                  <note>
                     <p>To take an example, older versions of the internet index of RFCs (requests for comments)
              use the namespace URI <code nobreak="false">http://www.rfc-editor.org/rfc-index</code>, while newer
              versions use <code nobreak="false">https://www.rfc-editor.org/rfc-index</code> (note the change of URI scheme).
              XQuery code that needs to work with either version can be simplified by setting the
              default namespace to <code nobreak="false">##any</code>: but be aware that this might lead to spurious matching
              of names in an unrelated namespace.</p>
                  </note>
               </item>
            </ulist>
            <p>The following example illustrates the declaration of a
          default namespace for elements and types:</p>
            <eg role="frag-prolog-parse-test" xml:space="preserve">declare default element namespace "http://example.org/names";</eg>
         </div2>
         <div2 id="comments">
            <head>Comments</head>
            <scrap headstyle="show">
               <prod id="doc-xpath40-Comment">
                  <lhs>Comment</lhs>
                  <rhs>"(:"  (<nt def="prod-xpath40-CommentContents">CommentContents<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-Comment">Comment<!--$idref_lang_part = xpath40- --></nt>)*  ":)"</rhs>
                  <com>
                     <loc href="#ws-explicit">ws: explicit</loc>
                  </com>
                  <com>
                     <loc href="#parse-note-comments">gn: comments</loc>
                  </com>
               </prod>

               <prod id="doc-xpath40-Comment-CommentContents">
                  <lhs>CommentContents</lhs>
                  <rhs>(<nt def="prod-xpath40-Char">Char<!--$idref_lang_part = xpath40- --></nt>+ - (Char* ('(:' | ':)') Char*))</rhs>
                  <com>
                     <loc href="#ws-explicit">ws: explicit</loc>
                  </com>
               </prod>
            </scrap>
            <p>Comments may be used to provide information relevant to programmers who read 
            <phrase role="xpath">an expression</phrase>. Comments are lexical constructs only, and do not affect  
            <phrase role="xpath">expression</phrase> processing.</p>
            <p>Comments are strings, delimited by the symbols <code nobreak="false">(:</code> and <code nobreak="false">:)</code>. Comments may be nested.</p>
            <p>A comment may be used anywhere <termref def="IgnorableWhitespace">ignorable whitespace</termref> is allowed (see <specref ref="DefaultWhitespaceHandling"/>).</p>
            <p>The following is an example of a comment:</p>
            <eg xml:space="preserve">(: Houston, we have a problem :)</eg>
         </div2>
         <div2 id="id-primary-expressions">
            <head>Primary Expressions</head>
            <p>
               <termdef id="dt-primary-expression" term="primary expression">
               A <term>primary expression</term> is an instance of the production
               <nt def="doc-xpath40-PrimaryExpr">PrimaryExpr<!--$spec = xpath40--></nt>. 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.</termdef>
            Map and Array Constructors are described in <specref ref="id-maps"/> and <specref ref="id-arrays"/>.

</p>
            <scrap headstyle="show">
               <prod id="doc-xpath40-PrimaryExpr">
                  <lhs>PrimaryExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-Literal">Literal<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-VarRef">VarRef<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-ParenthesizedExpr">ParenthesizedExpr<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-ContextValueRef">ContextValueRef<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-FunctionCall">FunctionCall<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-NodeConstructor">NodeConstructor<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-FunctionItemExpr">FunctionItemExpr<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-MapConstructor">MapConstructor<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-ArrayConstructor">ArrayConstructor<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-StringTemplate">StringTemplate<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-UnaryLookup">UnaryLookup<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-PrimaryExpr-Literal">
                  <lhs>Literal</lhs>
                  <rhs>
                     <nt def="prod-xpath40-NumericLiteral">NumericLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="doc-xpath40-StringLiteral">StringLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-QNameLiteral">QNameLiteral<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-PrimaryExpr-VarRef">
                  <lhs>VarRef</lhs>
                  <rhs>"$"  <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-PrimaryExpr-ParenthesizedExpr">
                  <lhs>ParenthesizedExpr</lhs>
                  <rhs>"("  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>?  ")"</rhs>
               </prod>

               <prod id="doc-xpath40-PrimaryExpr-ContextValueRef">
                  <lhs>ContextValueRef</lhs>
                  <rhs>"."</rhs>
               </prod>

               <prod id="doc-xpath40-PrimaryExpr-FunctionCall">
                  <lhs>FunctionCall</lhs>
                  <rhs>
                     <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                     <nt def="prod-xpath40-ArgumentList">ArgumentList<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
                  <com>
                     <loc href="#parse-note-reserved-function-names">xgc: reserved-function-names</loc>
                  </com>
                  <com>
                     <loc href="#parse-note-parens">gn: parens</loc>
                  </com>
               </prod>

               <prod id="doc-xpath40-PrimaryExpr-NodeConstructor">
                  <lhs>NodeConstructor</lhs>
                  <rhs>
                     <nt def="prod-xpath40-ComputedConstructor">ComputedConstructor<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-PrimaryExpr-FunctionItemExpr">
                  <lhs>FunctionItemExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-NamedFunctionRef">NamedFunctionRef<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-InlineFunctionExpr">InlineFunctionExpr<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-PrimaryExpr-NamedFunctionRef">
                  <lhs>NamedFunctionRef</lhs>
                  <rhs>
                     <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>  "#"  <nt def="prod-xpath40-IntegerLiteral">IntegerLiteral<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
                  <com>
                     <loc href="#parse-note-reserved-function-names">xgc: reserved-function-names</loc>
                  </com>
               </prod>

               <prod id="doc-xpath40-PrimaryExpr-InlineFunctionExpr">
                  <lhs>InlineFunctionExpr</lhs>
                  <rhs>("function"  |  "fn")  <nt def="prod-xpath40-FunctionSignature">FunctionSignature<!--$idref_lang_part = xpath40- --></nt>?  <nt def="prod-xpath40-FunctionBody">FunctionBody<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-PrimaryExpr-MapConstructor">
                  <lhs>MapConstructor</lhs>
                  <rhs>"map"?  "{"  (<nt def="prod-xpath40-MapConstructorEntry">MapConstructorEntry<!--$idref_lang_part = xpath40- --></nt> ** ",")  "}"</rhs>
               </prod>

               <prod id="doc-xpath40-PrimaryExpr-ArrayConstructor">
                  <lhs>ArrayConstructor</lhs>
                  <rhs>
                     <nt def="prod-xpath40-SquareArrayConstructor">SquareArrayConstructor<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-CurlyArrayConstructor">CurlyArrayConstructor<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-PrimaryExpr-StringTemplate">
                  <lhs>StringTemplate</lhs>
                  <rhs>"`"  (<nt def="prod-xpath40-StringTemplateFixedPart">StringTemplateFixedPart<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-StringTemplateVariablePart">StringTemplateVariablePart<!--$idref_lang_part = xpath40- --></nt>)*  "`"</rhs>
                  <com>
                     <loc href="#ws-explicit">ws: explicit</loc>
                  </com>
               </prod>

               <prod id="doc-xpath40-PrimaryExpr-UnaryLookup">
                  <lhs>UnaryLookup</lhs>
                  <rhs>
                     <nt def="prod-xpath40-Lookup">Lookup<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>
            </scrap>
            <div3 id="id-literals">
               <head>Literals</head>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-Literal">
                     <lhs>Literal</lhs>
                     <rhs>
                        <nt def="prod-xpath40-NumericLiteral">NumericLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="doc-xpath40-StringLiteral">StringLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-QNameLiteral">QNameLiteral<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-Literal-NumericLiteral">
                     <lhs>NumericLiteral</lhs>
                     <rhs>
                        <nt def="prod-xpath40-IntegerLiteral">IntegerLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-HexIntegerLiteral">HexIntegerLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-BinaryIntegerLiteral">BinaryIntegerLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-DecimalLiteral">DecimalLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-DoubleLiteral">DoubleLiteral<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-Literal-StringLiteral">
                     <lhs>StringLiteral</lhs>
                     <rhs>
                        <nt def="prod-xpath40-AposStringLiteral">AposStringLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-QuotStringLiteral">QuotStringLiteral<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="doc-xpath40-Literal-QNameLiteral">
                     <lhs>QNameLiteral</lhs>
                     <rhs>"#"  <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>
               </scrap>
               <p>
                  <termdef id="dt-literal" term="literal">A <term>literal</term> is a direct syntactic representation of an
		atomic item.</termdef> XPath 4.0 supports three kinds of literals: numeric literals,
		string literals, and QName literals.</p>
               <div4 id="id-numeric-literals">
                  <head>Numeric Literals</head>
                  <changes>
                     <change issue="429" PR="433" date="2023-04-25">
                     Numeric literals can now be written in hexadecimal or binary notation; 
                     and underscores can be included for readability.
                  </change>
                  </changes>
                  <scrap headstyle="show">
                     <prod id="doc-xpath40-NumericLiteral">
                        <lhs>NumericLiteral</lhs>
                        <rhs>
                           <nt def="prod-xpath40-IntegerLiteral">IntegerLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-HexIntegerLiteral">HexIntegerLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-BinaryIntegerLiteral">BinaryIntegerLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-DecimalLiteral">DecimalLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-DoubleLiteral">DoubleLiteral<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-NumericLiteral-IntegerLiteral">
                        <lhs>IntegerLiteral</lhs>
                        <rhs>
                           <nt def="prod-xpath40-Digits">Digits<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                        <com>
                           <loc href="#ws-explicit">ws: explicit</loc>
                        </com>
                     </prod>

                     <prod id="doc-xpath40-NumericLiteral-Digits">
                        <lhs>Digits</lhs>
                        <rhs>
                           <nt def="prod-xpath40-DecDigit">DecDigit<!--$idref_lang_part = xpath40- --></nt>  ((<nt def="prod-xpath40-DecDigit">DecDigit<!--$idref_lang_part = xpath40- --></nt>  |  "_")*  <nt def="prod-xpath40-DecDigit">DecDigit<!--$idref_lang_part = xpath40- --></nt>)?</rhs>
                        <com>
                           <loc href="#ws-explicit">ws: explicit</loc>
                        </com>
                     </prod>

                     <prod id="doc-xpath40-NumericLiteral-DecDigit">
                        <lhs>DecDigit</lhs>
                        <rhs>[0-9]</rhs>
                        <com>
                           <loc href="#ws-explicit">ws: explicit</loc>
                        </com>
                     </prod>

                     <prod id="doc-xpath40-NumericLiteral-HexIntegerLiteral">
                        <lhs>HexIntegerLiteral</lhs>
                        <rhs>"0x"  <nt def="prod-xpath40-HexDigits">HexDigits<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                        <com>
                           <loc href="#ws-explicit">ws: explicit</loc>
                        </com>
                     </prod>

                     <prod id="doc-xpath40-NumericLiteral-HexDigits">
                        <lhs>HexDigits</lhs>
                        <rhs>
                           <nt def="prod-xpath40-HexDigit">HexDigit<!--$idref_lang_part = xpath40- --></nt>  ((<nt def="prod-xpath40-HexDigit">HexDigit<!--$idref_lang_part = xpath40- --></nt>  |  "_")*  <nt def="prod-xpath40-HexDigit">HexDigit<!--$idref_lang_part = xpath40- --></nt>)?</rhs>
                        <com>
                           <loc href="#ws-explicit">ws: explicit</loc>
                        </com>
                     </prod>

                     <prod id="doc-xpath40-NumericLiteral-HexDigit">
                        <lhs>HexDigit</lhs>
                        <rhs>[0-9a-fA-F]</rhs>
                        <com>
                           <loc href="#ws-explicit">ws: explicit</loc>
                        </com>
                     </prod>

                     <prod id="doc-xpath40-NumericLiteral-BinaryIntegerLiteral">
                        <lhs>BinaryIntegerLiteral</lhs>
                        <rhs>"0b"  <nt def="prod-xpath40-BinaryDigits">BinaryDigits<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                        <com>
                           <loc href="#ws-explicit">ws: explicit</loc>
                        </com>
                     </prod>

                     <prod id="doc-xpath40-NumericLiteral-BinaryDigits">
                        <lhs>BinaryDigits</lhs>
                        <rhs>
                           <nt def="prod-xpath40-BinaryDigit">BinaryDigit<!--$idref_lang_part = xpath40- --></nt>  ((<nt def="prod-xpath40-BinaryDigit">BinaryDigit<!--$idref_lang_part = xpath40- --></nt>  |  "_")*  <nt def="prod-xpath40-BinaryDigit">BinaryDigit<!--$idref_lang_part = xpath40- --></nt>)?</rhs>
                        <com>
                           <loc href="#ws-explicit">ws: explicit</loc>
                        </com>
                     </prod>

                     <prod id="doc-xpath40-NumericLiteral-BinaryDigit">
                        <lhs>BinaryDigit</lhs>
                        <rhs>[01]</rhs>
                        <com>
                           <loc href="#ws-explicit">ws: explicit</loc>
                        </com>
                     </prod>

                     <prod id="doc-xpath40-NumericLiteral-DecimalLiteral">
                        <lhs>DecimalLiteral</lhs>
                        <rhs>("."  <nt def="prod-xpath40-Digits">Digits<!--$idref_lang_part = xpath40- --></nt>)  |  (<nt def="prod-xpath40-Digits">Digits<!--$idref_lang_part = xpath40- --></nt>  "."  <nt def="prod-xpath40-Digits">Digits<!--$idref_lang_part = xpath40- --></nt>?)</rhs>
                        <com>
                           <loc href="#ws-explicit">ws: explicit</loc>
                        </com>
                     </prod>

                     <prod id="doc-xpath40-NumericLiteral-DoubleLiteral">
                        <lhs>DoubleLiteral</lhs>
                        <rhs>(("."  <nt def="prod-xpath40-Digits">Digits<!--$idref_lang_part = xpath40- --></nt>)  |  (<nt def="prod-xpath40-Digits">Digits<!--$idref_lang_part = xpath40- --></nt>  ("."  <nt def="prod-xpath40-Digits">Digits<!--$idref_lang_part = xpath40- --></nt>?)?))  [eE]  [+-]?  <nt def="prod-xpath40-Digits">Digits<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                        <com>
                           <loc href="#ws-explicit">ws: explicit</loc>
                        </com>
                     </prod>
                  </scrap>
                  <p diff="add" at="2023-04-07">The value of a numeric literal is determined as follows (taking the rules in order):</p>
                  <olist diff="chg" at="2023-04-07">
                     <item>
                        <p>Underscore characters are stripped out. Underscores may be included in a numeric
                  literal to aid readability, but have no effect on the value. For example, <code nobreak="false">1_000_000</code>
                  is equivalent to <code nobreak="false">1000000</code>.</p>
                        <note>
                           <p diff="add" at="2023-04-25">Underscores must not appear at the beginning or end of a sequence of digits, only
                  in intermediate positions. Multiple adjacent underscores are allowed.</p>
                        </note>
                     </item>
                     <item>
                        <p>A <code nobreak="false">HexIntegerLiteral</code> represents a non-negative integer
                      expressed in hexadecimal: for example <code nobreak="false">0xffff</code> represents the integer 65535, and
                     <code nobreak="false">0xFFFF_FFFF</code> represents the integer 4294967295.</p>
                     </item>
                     <item>
                        <p>A <code nobreak="false">BinaryIntegerLiteral</code> represents a non-negative integer
                     expressed in binary: for example <code nobreak="false">0b101</code> represents the integer 5, and
                     <code nobreak="false">0b1111_1111</code> represents the integer 255.</p>
                     </item>
                     <item>
                        <p>The value of a <term>numeric literal</term> containing no <code nobreak="false">.</code> and 
                     no <code nobreak="false">e</code> or <code nobreak="false">E</code> character is an atomic item of type <code nobreak="false">xs:integer</code>;
                     the value is obtained by casting from <code nobreak="false">xs:string</code> to <code nobreak="false">xs:integer</code> as specified in
                     <xspecref spec="FO40" ref="casting-from-strings"/>.</p>
                     </item>
                     <item>
                        <p>The value of a numeric literal containing <code nobreak="false">.</code> but no <code nobreak="false">e</code> or <code nobreak="false">E</code> 
                     character is an atomic item of type <code nobreak="false">xs:decimal</code>;
                     the value is obtained by casting from <code nobreak="false">xs:string</code> to <code nobreak="false">xs:decimal</code> as specified in
                     <xspecref spec="FO40" ref="casting-from-strings"/>.</p>
                     </item>
                     <item>
                        <p>The value of a numeric literal 
                     containing an <code nobreak="false">e</code> or <code nobreak="false">E</code> character is an atomic item of type 
                     <code nobreak="false">xs:double</code>;
                     the value is obtained by casting from <code nobreak="false">xs:string</code> to <code nobreak="false">xs:double</code> as specified in
                     <xspecref spec="FO40" ref="casting-from-strings"/>.</p>
                     </item>
                  </olist>
                  <note diff="add" at="2023-04-07">
                     <p>The value of a numeric literal is always non-negative. An expression may
                  appear to include a negative number such as <code nobreak="false">-1</code>, but this is technically
                  an arithmetic expression comprising a unary minus operator followed by a numeric literal.</p>
                  </note>
                  <note>
                     <p>The effect of the above rules is that in the case of an integer or decimal literal, a dynamic error <xerrorref spec="FO40" class="AR" code="0002"/> will generally be raised if the literal is outside the range of values supported by the implementation (other options are available: see <xspecref spec="FO40" ref="op.numeric"/> for details.)</p>
                     <p role="xpath">The XML Schema specification allows implementations to impose a limit (which
   must not be less than 18 digits) on the size of integer and decimal
   values. The full range of values of built-in subtypes of <code nobreak="false">xs:integer</code>,
   such as <code nobreak="false">xs:long</code> and <code nobreak="false">xs:unsignedLong</code>, can be supported only if the
   limit is 20 digits or higher. Negative numbers such as the minimum
   value of <code nobreak="false">xs:long</code> (<code nobreak="false">-9223372036854775808</code>) are technically unary
   expressions rather than literals, but implementations may prefer to
   ensure that they are expressible.</p>
                  </note>
                  <p>Here are some examples of numeric literals:</p>
                  <ulist>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">12</code> denotes the <code nobreak="false">xs:integer</code> value twelve.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">1_000_000</code> denotes the <code nobreak="false">xs:integer</code> value one million.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">12.5</code> denotes the <code nobreak="false">xs:decimal</code> value twelve and one half.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">3.14159_26535_89793e0</code>
                  is an <code nobreak="false">xs:double</code> value representing the mathematical constant
                  <var>π</var> to 15 decimal places. </p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">125E2</code> denotes the <code nobreak="false">xs:double</code> value twelve thousand, five hundred.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">0xffff</code> denotes the <code nobreak="false">xs:integer</code> value 65535.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">0b1000_0001</code> denotes the <code nobreak="false">xs:integer</code> value 129.</p>
                     </item>
                  </ulist>
               </div4>
               <div4 id="id-string-literal">
                  <head>String Literals</head>
                  <scrap headstyle="show">
                     <prod id="doc-xpath40-StringLiteral">
                        <lhs>StringLiteral</lhs>
                        <rhs>
                           <nt def="prod-xpath40-AposStringLiteral">AposStringLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-QuotStringLiteral">QuotStringLiteral<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                        <com>
                           <loc href="#ws-explicit">ws: explicit</loc>
                        </com>
                     </prod>

                     <prod id="doc-xpath40-StringLiteral-AposStringLiteral">
                        <lhs>AposStringLiteral</lhs>
                        <rhs>"'"  (<nt def="prod-xpath40-EscapeApos">EscapeApos<!--$idref_lang_part = xpath40- --></nt>  |  [^'])*  "'"</rhs>
                        <com>
                           <loc href="#ws-explicit">ws: explicit</loc>
                        </com>
                     </prod>

                     <prod id="doc-xpath40-StringLiteral-EscapeApos">
                        <lhs>EscapeApos</lhs>
                        <rhs>"''"</rhs>
                        <com>
                           <loc href="#ws-explicit">ws: explicit</loc>
                        </com>
                     </prod>

                     <prod id="doc-xpath40-StringLiteral-QuotStringLiteral">
                        <lhs>QuotStringLiteral</lhs>
                        <rhs>'"'  (<nt def="prod-xpath40-EscapeQuot">EscapeQuot<!--$idref_lang_part = xpath40- --></nt>  |  [^"])*  '"'</rhs>
                        <com>
                           <loc href="#ws-explicit">ws: explicit</loc>
                        </com>
                     </prod>

                     <prod id="doc-xpath40-StringLiteral-EscapeQuot">
                        <lhs>EscapeQuot</lhs>
                        <rhs>'""'</rhs>
                        <com>
                           <loc href="#ws-explicit">ws: explicit</loc>
                        </com>
                     </prod>
                  </scrap>
                  <p>The value of a <term>string literal</term> is an atomic item whose type is
               <code nobreak="false">xs:string</code> and whose value is the string denoted by the characters between the
		delimiting apostrophes or quotation marks. If the literal is delimited by apostrophes, two adjacent 
		apostrophes within the literal are interpreted as a single apostrophe. Similarly, if the literal 
		is delimited by quotation marks, two adjacent quotation marks within the literal are interpreted 
		as one quotation mark.</p>
                  <p>Here are some examples of string literals:</p>
                  <ulist>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">"He said, ""I don't like it."""</code> denotes a string containing two quotation marks and one apostrophe.</p>
                     </item>
                     <item>
                        <p>In XQuery, the string literal <code nobreak="false">"&amp;lt;"</code> denotes a string of length 1 containing the single character
                     <code nobreak="false">"&lt;"</code>. In XPath, the string literal <code nobreak="false">"&amp;lt;"</code> denotes a string of length 4 containing the four 
                     characters <code nobreak="false">"&amp;"</code>, <code nobreak="false">"l"</code>, <code nobreak="false">"t"</code>, <code nobreak="false">";"</code>. (However, when the XPath
                     expression is embedded in an XML document, the sequence <code nobreak="false">"&amp;lt;"</code> will typically have already been converted
                     to <code nobreak="false">"&lt;"</code> by the XML parser.)</p>
                     </item>
                  </ulist>
                  <note>
                     <p>When XPath or XQuery expressions are embedded in contexts where quotation
                     marks have special significance, such as inside XML attributes, or in string literals in a host language such
                     as Java or C#, then additional
                     escaping may be needed.</p>
                  </note>
                  <note>
                     <p>Fixed string values can also be written as string templates: 
                  see <specref ref="id-string-templates"/>. A string template with no enclosed
               expressions, such as <code nobreak="false">`Jamaica`</code> evaluates to the same value as
               the string literals <code nobreak="false">"Jamaica"</code> or <code nobreak="false">'Jamaica'</code>. 
               A string template can contain both single and double quotation marks:
               <code nobreak="false">`He said: "I don't like it"`</code>. However, there there are
               some subtle differences:</p>
                     <ulist>
                        <item>
                           <p>In string literals, the treatment of character and entity references
                  such as <code nobreak="false">&amp;amp;</code> varies between XQuery and XPath; in string templates,
                  such references are not expanded in either language.</p>
                        </item>
                        <item>
                           <p>String templates can only be used where an expression is expected. String
                  literals are also used in some non-expression contexts, for example in
                  defining an enumeration type: see <specref ref="id-enumeration-types"/>.</p>
                        </item>
                        <item>
                           <p>Curly brackets (<char>U+007B</char> and <char>U+007D</char>) and backticks 
                  (<char>U+0060</char>) have a reserved meaning in string templates.</p>
                        </item>
                     </ulist>
                  </note>
               </div4>
               <div4 id="id-qname-literals">
                  <head>QName Literals</head>
                  <changes>
                     <change issue="1661">QName literals are new in 4.0.</change>
                  </changes>
                  <p>A QName literal represents a value of type <code nobreak="false">xs:QName</code>.</p>
                  <scrap headstyle="show">
                     <prod id="doc-xpath40-QNameLiteral">
                        <lhs>QNameLiteral</lhs>
                        <rhs>"#"  <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-QNameLiteral-EQName">
                        <lhs>EQName</lhs>
                        <rhs>
                           <nt def="prod-xpath40-QName">QName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>
                  </scrap>
                  <p>For example, the expression <code nobreak="false">node-name($node) = #xml:space</code>
               returns true if the name of the node <code nobreak="false">$node</code> is the QName with local part <code nobreak="false">space</code>
                  and namespace URI <code nobreak="false">http://www.w3.org/XML/1998/namespace</code>.</p>
                  <p>If the <code nobreak="false">EQName</code> is an unprefixed <code nobreak="false">NCName</code>, then it is expanded using
                  the <termref def="dt-no-namespace-rule"/>. If there
                  is no binding for the prefix in the <termref def="dt-static-namespaces"/> then
                  a static error is raised <errorref class="ST" code="0081"/>.
               </p>
                  <note>
                     <p>No whitespace or comment is permitted between the <code nobreak="false">#</code> character
                  and the <code nobreak="false">EQName</code>.</p>
                     <p>In XQuery, the character pair <code nobreak="false">(#</code> is recognized as the start of
                     a pragma. In order to ensure that an expression such as <code nobreak="false">error(#err:XPTY0004)</code>
                     is correctly parsed, the rules for pragmas have changed to require whitespace
                     after the opening <code nobreak="false">(#</code> and before the <code nobreak="false">EQName</code>.</p>
                  </note>
                  <note>
                     <p>A <code nobreak="false">QNameLiteral</code> is an expression that evaluates to a single
                  item of type <code nobreak="false">xs:QName</code>; it is thus an alternative to calling the
                  <code nobreak="false">xs:QName</code> constructor function with a literal string argument.
                  This should not be confused with QNames that are used directly in XPath 4.0 to refer to constructs such as
               functions, variables, and elements.</p>
                     <p>A <code nobreak="false">QName</code> appearing on its own as an expression,
               for example <code nobreak="false">my:invoice</code>, is an abbreviation for the axis step <code nobreak="false">child::my:step</code>,
               which selects a child element of the context node having this particular element name. A different
               construct is therefore needed to represent an atomic item of type <code nobreak="false">xs:QName</code>.
               For example, the function <code nobreak="false">fn:error</code> expects an <code nobreak="false">xs:QName</code> value
               as its first argument, so (provided that the prefix <code nobreak="false">err</code> is defined in the static
               context) it is possible to use a call such as <code nobreak="false">error( #err:XPTY0004 )</code> to raise an
               error with this error code.</p>
                  </note>
               </div4>
               <div4 id="id-constants-other-types">
                  <head>Constants of Other Types</head>
                  <p>
               
      The <code nobreak="false">xs:boolean</code> values <code nobreak="false">true</code> and <code nobreak="false">false</code> can be constructed by calls to the
      <termref def="dt-system-function">system functions</termref>
                     <code nobreak="false">fn:true()</code> and <code nobreak="false">fn:false()</code>, respectively.
    </p>
                  <p>Values of other simple types can be constructed by calling the <termref def="dt-constructor-function">constructor function</termref> for the given type. The constructor functions for XML Schema
		built-in types are defined in <xspecref spec="FO40" ref="constructor-functions-for-xsd-types"/>. In general, the name of a constructor function for a given type is the same as the name of the type (including its namespace). For
		example:</p>
                  <ulist>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">xs:integer("12")</code> returns the integer value twelve.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">xs:date("2001-08-25")</code> returns an item whose type is <code nobreak="false">xs:date</code> and whose value represents the date 25th August 2001.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">xs:dayTimeDuration("PT5H")</code> returns an item whose type is <code nobreak="false">xs:dayTimeDuration</code> and whose value represents a duration of five hours.</p>
                     </item>
                  </ulist>
                  <p>Constructor functions can also be used to create special values that have no literal representation, as in the following examples:
<ulist>
                        <item>
                           <p>
                              <code role="parse-test" nobreak="false">xs:float("NaN")</code> returns the special floating-point value, "Not a Number."</p>
                        </item>
                        <item>
                           <p>
                              <code role="parse-test" nobreak="false">xs:double("INF")</code> returns the special double-precision value, "positive infinity."</p>
                        </item>
                     </ulist>
                  </p>
                  <p>Constructor functions are available for all simple types,
including union types. For example, if <code nobreak="false">my:dt</code> is a user-defined union
type whose member types are <code nobreak="false">xs:date</code>, <code nobreak="false">xs:time</code>, and <code nobreak="false">xs:dateTime</code>, then
the expression <code nobreak="false">my:dt("2011-01-10")</code> creates an atomic item of type
<code nobreak="false">xs:date</code>. The rules follow XML Schema validation rules for union types:
the effect is to choose the first member type that accepts the given
string in its lexical space.</p>
                  <p>It is also possible to construct values of various types by using a <code nobreak="false">cast</code> expression. For example:</p>
                  <ulist>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">9 cast as
                        hatsize</code> returns the atomic item <code nobreak="false">9</code>
			 whose type is  <code nobreak="false">hatsize</code>.</p>
                     </item>
                  </ulist>
               </div4>
            </div3>
            <div3 id="id-variables">
               <head>Variable References</head>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-VarRef">
                     <lhs>VarRef</lhs>
                     <rhs>"$"  <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-VarRef-EQName">
                     <lhs>EQName</lhs>
                     <rhs>
                        <nt def="prod-xpath40-QName">QName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>
               </scrap>
               <p>
                  <termdef id="dt-variable-reference" term="variable reference">A <term>variable reference</term> is an EQName preceded by a $-sign.</termdef>
                The variable name is expanded using the <termref def="dt-no-namespace-rule"/>.
                Two variable references are equivalent if their  <termref def="dt-expanded-qname">expanded QNames</termref>  are equal (as defined by the <code nobreak="false">eq</code> operator). The scope of a variable binding is defined separately for each kind of
expression that can bind variables.</p>
               <p>Every variable reference must match a name in the <termref def="dt-in-scope-variables">in-scope variables</termref>. </p>
               <p>Every variable binding has a static scope. The scope defines where
references to the variable can validly occur.

It is a <termref def="dt-static-error">static error</termref>
                  <errorref class="ST" code="0008"/> to reference a variable that is not in scope. If a variable is bound in the <termref def="dt-static-context">static context</termref> for an expression, that variable is in scope for the entire expression except where it is occluded by another binding that uses the same name within that scope.</p>
               <p>
At evaluation time, the value of a variable reference is the value to which the relevant variable is bound.</p>
               <!--<p diff="add" at="A">A <code>VarRef</code> consisting of a $-sign followed by an integer literal is refered to as a
            <term>numeric parameter reference</term>, and is allowed only within an inline function declared using hash notation:
            see <specref ref="id-hash-inline-functions"/></p>-->
            </div3>
            <div3 id="id-context-value-references">
               <head>Context Value References</head>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-ContextValueRef">
                     <lhs>ContextValueRef</lhs>
                     <rhs>"."</rhs>
                  </prod>
               </scrap>
               <p>A <term>context value reference</term> evaluates to
              the <termref def="dt-context-value"/>.</p>
               <p>In many syntactic contexts, the context value will be a single item.
               For example this applies on the right-hand side of the <code nobreak="false">/</code> 
               or <code nobreak="false">!</code> operators, or within a <nt def="doc-xpath40-Predicate">Predicate<!--$spec = xpath40--></nt>.</p>
               <p>If the <termref def="dt-context-value"/> is <xtermref spec="DM40" ref="dt-absent"/>, a context value reference raises a <termref def="dt-type-error"/>
                  <errorref class="DY" code="0002"/>.</p>
               <note>
                  <p>Being absent is not the same thing as being empty.</p>
               </note>
            </div3>
            <div3 id="id-paren-expressions">
               <head>Parenthesized Expressions</head>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-ParenthesizedExpr">
                     <lhs>ParenthesizedExpr</lhs>
                     <rhs>"("  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>?  ")"</rhs>
                  </prod>

                  <prod id="doc-xpath40-ParenthesizedExpr-Expr">
                     <lhs>Expr</lhs>
                     <rhs>(<nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt> ++ ",")</rhs>
                  </prod>
               </scrap>
               <p>Parentheses may be used to override the precedence rules.
        For example, the expression <code role="parse-test" nobreak="false">(2 + 4)
		    * 5</code> evaluates to thirty, since the parenthesized expression <code role="parse-test" nobreak="false">(2 + 4)</code> is evaluated first and its result is multiplied by five. Without
			 parentheses, the expression <code role="parse-test" nobreak="false">2 + 4 * 5</code> evaluates to twenty-two, because the multiplication operator has higher
			 precedence than the addition operator.</p>
               <p>Empty parentheses are used to denote the empty sequence, as
		described in <specref ref="construct_seq"/>.</p>
            </div3>
            <div3 id="id-enclosed-expr">
               <head>Enclosed Expressions</head>
               <p>
                  <scrap headstyle="show">
                     <prod id="doc-xpath40-EnclosedExpr">
                        <lhs>EnclosedExpr</lhs>
                        <rhs>"{"  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>?  "}"</rhs>
                     </prod>

                     <prod id="doc-xpath40-EnclosedExpr-Expr">
                        <lhs>Expr</lhs>
                        <rhs>(<nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt> ++ ",")</rhs>
                     </prod>
                  </scrap>
                  <termdef term="enclosed expression" id="dt-enclosed-expression">An <term>enclosed expression</term> is an instance of the <nt def="doc-xpath40-EnclosedExpr">EnclosedExpr<!--$spec = xpath40--></nt> production, which allows an optional expression within curly brackets.</termdef>
                  <termdef id="dt-content-expression" term="content expression">In an  <termref def="dt-enclosed-expression">enclosed expression</termref>, the optional expression enclosed in curly brackets is called the <term>content expression</term>.</termdef> If the <termref def="dt-content-expression">content expression</termref> is not provided explicitly,  the content expression is <code nobreak="false">()</code>.</p>
               <note diff="add" at="A">
                  <p>Despite the name, an enclosed expression is not actually an expression
                  in its own right; rather it is a construct that is used in the grammar of many other expressions.</p>
               </note>
            </div3>
         </div2>
         <div2 id="id-postfix-expression">
            <head>Postfix Expressions</head>
            <scrap headstyle="show">
               <head/>
               <prod id="doc-xpath40-PostfixExpr">
                  <lhs>PostfixExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-PrimaryExpr">PrimaryExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-FilterExpr">FilterExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-DynamicFunctionCall">DynamicFunctionCall<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-LookupExpr">LookupExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-MethodCall">MethodCall<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-FilterExprAM">FilterExprAM<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-PostfixExpr-PrimaryExpr">
                  <lhs>PrimaryExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-Literal">Literal<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-VarRef">VarRef<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-ParenthesizedExpr">ParenthesizedExpr<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-ContextValueRef">ContextValueRef<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-FunctionCall">FunctionCall<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-NodeConstructor">NodeConstructor<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-FunctionItemExpr">FunctionItemExpr<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-MapConstructor">MapConstructor<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-ArrayConstructor">ArrayConstructor<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-StringTemplate">StringTemplate<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-UnaryLookup">UnaryLookup<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-PostfixExpr-FilterExpr">
                  <lhs>FilterExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-PostfixExpr">PostfixExpr<!--$idref_lang_part = xpath40- --></nt>
                     <nt def="prod-xpath40-Predicate">Predicate<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-PostfixExpr-DynamicFunctionCall">
                  <lhs>DynamicFunctionCall</lhs>
                  <rhs>
                     <nt def="prod-xpath40-PostfixExpr">PostfixExpr<!--$idref_lang_part = xpath40- --></nt>
                     <nt def="prod-xpath40-PositionalArgumentList">PositionalArgumentList<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-PostfixExpr-LookupExpr">
                  <lhs>LookupExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-PostfixExpr">PostfixExpr<!--$idref_lang_part = xpath40- --></nt>
                     <nt def="prod-xpath40-Lookup">Lookup<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-PostfixExpr-MethodCall">
                  <lhs>MethodCall</lhs>
                  <rhs>
                     <nt def="prod-xpath40-PostfixExpr">PostfixExpr<!--$idref_lang_part = xpath40- --></nt>  "=?&gt;"  <nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>
                     <nt def="prod-xpath40-PositionalArgumentList">PositionalArgumentList<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-PostfixExpr-FilterExprAM">
                  <lhs>FilterExprAM</lhs>
                  <rhs>
                     <nt def="prod-xpath40-PostfixExpr">PostfixExpr<!--$idref_lang_part = xpath40- --></nt>  "?["  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>  "]"</rhs>
               </prod>
            </scrap>
            <p>A postfix expression takes one of the following forms:</p>
            <ulist>
               <item>
                  <p>
                     <termdef term="filter expression" id="dt-filter-expression">
               A <term>filter expression</term> is an
               instance of the construct <nt def="doc-xpath40-FilterExpr">FilterExpr<!--$spec = xpath40--></nt>:
               that is, it is an expression in the form <code nobreak="false">
                           <var>E1</var>[<var>E2</var>]</code>. 
               Its effect is to return those items from the value of <var>E1</var> that
               satisfy the predicate in <var>E2</var>.</termdef>
                  </p>
                  <p>Filter expressions are described in <specref ref="id-filter-expression"/>.</p>
                  <p>An example of a filter expression is <code nobreak="false">(1 to 100)[. mod 2 = 0]</code>
            which returns all even numbers in the range 1 to 100.</p>
                  <p>The base expression <var>E1</var> can itself be a postfix expression,
            so multiple predicates are allowed, in the form <code nobreak="false">
                        <var>E1</var>[<var>E2</var>][<var>E3</var>][<var>E4</var>]</code>.</p>
               </item>
               <item>
                  <p>
                     <termdef id="dt-dynamic-function-call" term="dynamic function call">A <term>dynamic function call</term>
               is an instance of the construct <nt def="doc-xpath40-DynamicFunctionCall">DynamicFunctionCall<!--$spec = xpath40--></nt>:
               that is, it is an expression in the form <code nobreak="false">
                           <var>E1</var>(<var>E2</var>, <var>E3</var>, ...)</code>
               in which <var>E1</var> identifies a <termref def="dt-function-item"/>
               to be called, and the parenthesized argument list
                <code nobreak="false">(<var>E2</var>, <var>E3</var>, ...)</code>) identifies the arguments supplied to the function.</termdef> Its
               effect is to evaluate <var>E1</var> to obtain a function,
               and then call that function, with the values of expressions
               <var>E2</var>, <var>E3</var>, <code nobreak="false">...</code> as
               arguments. Dynamic function calls are described in <specref ref="id-dynamic-function-invocation"/>.</p>
                  <p>An example of a dynamic function call is <code nobreak="false">$f("a", 2)</code> where
            the value of variable <code nobreak="false">$f</code> must be a function item.</p>
               </item>
               <item>
                  <p>
                     <termdef id="dt-lookup-expression" term="lookup expression">
               A <term>lookup expression</term> is an instance of the production
                  <nt def="doc-xpath40-LookupExpr">LookupExpr<!--$spec = xpath40--></nt>: that is, an expression in the form
                  <code nobreak="false">
                           <var>E1</var>?<var>KS</var>
                        </code>, where <var>E1</var> is an expression returning a sequence
            of maps or arrays, and <var>KS</var> is a key specifier, which indicates which
            entries in a map, or members in an array, should be selected.</termdef>
                  </p>
                  <p>Lookup expressions are described in <specref ref="id-postfix-lookup"/>.</p>
                  <p>An example of a lookup expression is <code nobreak="false">$emp?name</code>, where
            the value of variable <code nobreak="false">$emp</code> is a map, and the string <code nobreak="false">"name"</code>
            is the key of one of the entries in the map.</p>
               </item>
               <item>
                  <p>
                     <termdef term="filter expression for maps and arrays"
                              id="dt-filter-expression-ma">
               A <term>filter expression for maps and arrays</term> is an
               instance of the construct <nt def="doc-xpath40-FilterExprAM">FilterExprAM<!--$spec = xpath40--></nt>:
               that is, it is an expression in the form <code nobreak="false">
                           <var>E1</var>?[<var>E2</var>]</code>. 
               Its effect is to evaluate <var>E1</var> to return an array or map, and to select
               members of the array, or entries from the map, that satisfy the predicate in <var>E2</var>.</termdef>
                  </p>
                  <p>Filter expressions for maps and array are described in <specref ref="id-filter-maps-and-arrays"/>.</p>
               </item>
            </ulist>
            <p>Postfix expressions are evaluated from left-to-right. For example, the 
         expression <code nobreak="false">$E1[E2]?(E3)(E4)</code> is evaluated by first evaluating
            the filter expression <code nobreak="false">$E1[E2]</code> to produce a sequence of maps and arrays 
            (say <code nobreak="false">$S</code>), then evaluating the lookup expression <code nobreak="false">$S?(E3)</code>
            to produce a function item (say <code nobreak="false">$F</code>), then evaluating the dynamic
            function call <code nobreak="false">$F(E4)</code> to produce the final result.</p>
            <note>
               <p>The grammar for postfix expressions is defined here in a way designed
         to link clearly to the semantics of the different kinds of expression. For parsing
         purposes, the equivalent production rule:</p>
               <eg xml:space="preserve">PostfixExpr := PrimaryExpr (Predicate | PositionalArgumentList | Lookup)*</eg>
               <p>(as used in XPath 3.1) is probably more convenient.</p>
            </note>
         </div2>
         <div2 id="id-filter-expression">
            <head>Filter Expressions</head>
            <changes>
               <change issue="816" PR="996" date="2024-02-06">
                  The value of a predicate in a filter expression can now be a sequence of integers.
               </change>
            </changes>
            <scrap headstyle="show">
               <prod id="doc-xpath40-FilterExpr">
                  <lhs>FilterExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-PostfixExpr">PostfixExpr<!--$idref_lang_part = xpath40- --></nt>
                     <nt def="prod-xpath40-Predicate">Predicate<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-FilterExpr-PostfixExpr">
                  <lhs>PostfixExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-PrimaryExpr">PrimaryExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-FilterExpr">FilterExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-DynamicFunctionCall">DynamicFunctionCall<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-LookupExpr">LookupExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-MethodCall">MethodCall<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-FilterExprAM">FilterExprAM<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-FilterExpr-Predicate">
                  <lhs>Predicate</lhs>
                  <rhs>"["  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>  "]"</rhs>
               </prod>
            </scrap>
            <p>A <termref def="dt-filter-expression"/> consists of a base expression followed by
               a predicate, which is an expression written in square
               brackets. The result of the filter expression consists of the
               items returned by the base expression, filtered by applying the
               predicate to each item in turn. The ordering of the items
               returned by a filter expression is the same as their order in
               the result of the primary expression.</p>
            <note>
               <p>Where the expression before the square brackets is an
                  <nt def="doc-xpath40-AbbreviatedStep">AbbreviatedStep<!--$spec = xpath40--></nt> or <nt def="prod-xpath40-FullStep">FullStep<!--$spec = xpath40--></nt>, the expression is technically not a
                  filter expression but an <nt def="doc-xpath40-AxisStep">AxisStep<!--$spec = xpath40--></nt>. There are minor differences
                  in the semantics: see <specref ref="id-predicate"/>
               </p>
            </note>
            <p>Here are some examples of filter expressions:</p>
            <ulist>
               <item>
                  <p>Given a sequence of products in a variable, return only those products whose price is greater than 100.</p>
                  <eg role="parse-test" xml:space="preserve">$products[price gt 100]</eg>
               </item>
               <item>
                  <p>List all the integers from 1 to 100 that are divisible by 5. (See <specref ref="construct_seq"/> for an explanation of the <code nobreak="false">to</code> operator.)</p>
                  <eg role="parse-test" xml:space="preserve">(1 to 100)[. mod 5 eq 0]</eg>
               </item>
               <item>
                  <p>The result of the following expression is the integer 25:</p>
                  <eg role="parse-test" xml:space="preserve">(21 to 29)[5]</eg>
               </item>
               <item>
                  <p>The following example returns the fifth through ninth items in the sequence bound to variable <code nobreak="false">$orders</code>.</p>
                  <eg role="parse-test" diff="chg" at="issue816" xml:space="preserve">$orders[5 to 9]</eg>
               </item>
               <item>
                  <p>The following example illustrates the use of a filter expression as a <termref def="dt-step">step</termref> in a <termref def="dt-path-expression">path expression</termref>. It returns the last chapter or appendix within the book bound to variable <code nobreak="false">$book</code>:</p>
                  <eg role="parse-test" xml:space="preserve">$book/(chapter | appendix)[last()]</eg>
               </item>
            </ulist>
            <p>For each item in the input sequence, the predicate expression
               is evaluated using an <term>inner focus</term>, defined as
               follows: The context value is the item currently being tested
               against the predicate. The context size is the number of items
               in the input sequence. The context position is the position of
               the context value within the input sequence. </p>
            <p>For each item in the input sequence, the result of the
               predicate expression is coerced to an <code nobreak="false">xs:boolean</code>
               value, called the <termref def="dt-predicate-truth-value"/>, as
               described below. Those items for which the predicate truth value
               is <code nobreak="false">true</code> are retained, and those for which the
               predicate truth value is <code nobreak="false">false</code> are discarded.</p>
            <p>
               <termdef id="dt-predicate-truth-value" term="predicate truth value">The
            <term>predicate truth value</term> of a value <code nobreak="false">$V</code>
            is the result of the expression <code nobreak="false">if ($V instance of xs:numeric+)
            then ($V = position()) else fn:boolean($V)</code>.</termdef>
            </p>
            <p>Expanding this definition, the predicate truth value can be obtained 
               by applying the following rules, in order:</p>
            <olist>
               <item diff="chg" at="issue816">
                  <p>If the value <var>V</var> of the predicate expression 
                     is a sequence whose first item is an instance of the type <code nobreak="false">xs:numeric</code>,
                     then:</p>
                  <olist>
                     <item>
                        <p>
                           <var>V</var> must be an instance of the type
                        <code nobreak="false">xs:numeric+</code> (that is, every item in <var>V</var>
                           must be numeric). A type error <xerrorref spec="FO40" class="RG" code="0006"/> is
                        raised if this is not the case.</p>
                     </item>
                     <item>
                        <p>The predicate truth value is <code nobreak="false">true</code> if 
                           <var>V</var> is equal (by the
                           <code nobreak="false">=</code> operator) to the <term>context
                              position</term>, and is <code nobreak="false">false</code>
                           otherwise.</p>
                     </item>
                  </olist>
                  <p>In effect this means that an item in the input sequence is selected
                  if its position in the sequence is equal to one or more of the numeric
                  values in the predicate. For example, the predicate <code nobreak="false">[3 to 5]</code>
                  is true for the third, fourth, and fifth items in the input sequence.</p>
                  <p> 
                  </p>
                  <note>
                     <p>It is possible, though not generally useful, for the value of a numeric
                  predicate to depend on the focus, and thus to differ for different items
                  in the input sequence. For example, the predicate <code nobreak="false">[xs:integer(@seq)]</code>
                  selects those items in the input sequence whose <code nobreak="false">@seq</code> attribute
                  is numerically equal to their position in the input sequence.</p>
                     <p>It is also possible, and again not generally useful, for the value of the predicate
                  to be numeric for some items in the input sequence, and boolean for others.
                  For example, the predicate <code nobreak="false">[@special otherwise last()]</code>
                  is true for an item that either has an <code nobreak="false">@special</code> attribute,
                     or is the last item in the input sequence.</p>
                  </note>
                  <note>
                     <p>The truth value of a numeric predicate does not depend on the order
                  of the numbers in <var>V</var>. The predicates <code nobreak="false">[ 1, 2, 3 ]</code>
                  and <code nobreak="false">[ 3, 2, 1 ]</code> have exactly the same effect. The items in 
                  the result of a filter expression always retain the ordering of the input
                  sequence.</p>
                  </note>
                  <note>
                     <p>The truth value of a numeric predicate whose value is non-integral
                  or non-positive is always false.</p>
                  </note>
                  <note>
                     <p>Beware that using boolean operators (<code nobreak="false">and</code>, <code nobreak="false">or</code>,
                  <code nobreak="false">not()</code>) with numeric values may not have the intended effect.
                  For example the predicate <code nobreak="false">[1 or last()]</code> selects every item
                  in the sequence, because <code nobreak="false">or</code> operates on the <termref def="dt-ebv"/>
                  of its operands. The required effect can be achieved with the predicate
                  <code nobreak="false">[1, last()]</code>.</p>
                  </note>
               </item>
               <item>
                  <p>Otherwise, the predicate truth value is the <termref def="dt-ebv">effective boolean value</termref> of the
                     predicate expression.</p>
               </item>
            </olist>
         </div2>
         <div2 id="id-functions">
            <head>Functions</head>
            <p diff="chg" at="B">Functions in XPath 4.0 arise in two ways:</p>
            <ulist diff="chg" at="B">
               <item>
                  <p>A <termref def="dt-function-definition"/> contains information
               about a family of functions with the same name and a defined arity range. These functions
               are in most cases known statically (they appear in the <termref def="dt-statically-known-function-definitions"/>), 
               but there may be further function definitions
               that are known only dynamically (appearing in the <termref def="dt-dynamically-known-function-definitions"/>).</p>
               </item>
               <item>
                  <p>
                     <termref def="dt-function-item">Function items</termref> are XDM items that can be called
               using a <termref def="dt-dynamic-function-call"/>. They  are values that can be bound to variables, passed as
            arguments, returned as function results, and generally manipulated in the same way as other XDM values.</p>
               </item>
            </ulist>
            <p diff="chg" at="B">The functions defined by a statically known <termref def="dt-function-definition"/> can be invoked using a
            <termref def="dt-static-function-call"/>. <termref def="dt-function-item">Function items</termref> corresponding
            to these definitions can also be obtained, as dynamic values, by evaluating a <termref def="dt-named-function-ref"/>. 
            <termref def="dt-function-item">Function items</termref> can also be obtained using the <function>fn:function-lookup</function>
            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 <termref def="dt-static-context"/>, so long as it is in the <termref def="dt-dynamic-context"/>.</p>
            <p>Static and dynamic function calls are described in the following sections.</p>
            <div3 id="id-static-functions" diff="add" at="A">
               <head>Static Function Calls</head>
               <p>The <termref def="dt-static-context"/> for an expression includes a set 
                  of <termref def="dt-statically-known-function-definitions"/>. Every <termref def="dt-function-definition"/>
               in the static context has a name (which is an <termref def="dt-expanded-qname"/>) and 
                  an <termref def="dt-arity-range"/>, which is a range of permitted arities for
               calls on that function. Two <termref def="dt-function-definition">function definitions</termref> 
                  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.</p>
               <p>A <termref def="dt-static-function-call"/> is bound to a <termref def="dt-function-definition"/> 
                  in the static context by matching the name
               and arity. If the function call has <var>P</var> positional arguments followed by
                  <var>K</var> keyword arguments, then the required arity is <var>P+K</var>, and the static context 
                  must include a <termref def="dt-function-definition"/> whose name matches the <termref def="dt-expanded-qname"/> 
                  in the function call, and whose <termref def="dt-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 <specref ref="id-eval-static-function-call"/> below.</p>
               <p>Similarly, a <termref def="dt-named-function-ref"/> of the form <code nobreak="false">f#N</code> binds to a 
                  <termref def="dt-function-definition"/> in the
                  static context whose name matches <var>f</var> where <code nobreak="false">MinP ≤ N and MaxP ≥ N</code>.
               The result of evaluating a function reference is a <termref def="dt-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 <function>fn:concat#3</function>
               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 <function>fn:concat</function> with
               three positional arguments. <!--The arity must not exceed the number of arguments that
               can be supplied positionally. Therefore, in the case of a function reference to a map-variadic functions
               such as <function>fn:serialize#2</function>, a dynamic call must supply the map-valued argument
               (the serialization parameters) in the form of a map; the function reference <function>fn:serialize#3</function>
               is an error, because <var>MaxP</var> = 2.--></p>
               <p>The detailed rules for evaluating static function calls and function references are defined
               in subsequent sections.</p>
               <div4 id="id-function-calls">
                  <head>Static Function Call Syntax</head>
                  <changes>
                     <change issue="155" PR="159" date="2020-09-30">
                  Keyword arguments are allowed on static function calls, as well as positional arguments.
               </change>
                  </changes>
                  <scrap headstyle="show">
                     <prod id="doc-xpath40-FunctionCall">
                        <lhs>FunctionCall</lhs>
                        <rhs>
                           <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                           <nt def="prod-xpath40-ArgumentList">ArgumentList<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                        <com>
                           <loc href="#parse-note-reserved-function-names">xgc: reserved-function-names</loc>
                        </com>
                        <com>
                           <loc href="#parse-note-parens">gn: parens</loc>
                        </com>
                     </prod>

                     <prod id="doc-xpath40-FunctionCall-EQName">
                        <lhs>EQName</lhs>
                        <rhs>
                           <nt def="prod-xpath40-QName">QName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-FunctionCall-ArgumentList">
                        <lhs>ArgumentList</lhs>
                        <rhs>"("  ((<nt def="prod-xpath40-PositionalArguments">PositionalArguments<!--$idref_lang_part = xpath40- --></nt>  (","  <nt def="prod-xpath40-KeywordArguments">KeywordArguments<!--$idref_lang_part = xpath40- --></nt>)?)  |  <nt def="prod-xpath40-KeywordArguments">KeywordArguments<!--$idref_lang_part = xpath40- --></nt>)?  ")"</rhs>
                     </prod>

                     <prod id="doc-xpath40-FunctionCall-PositionalArguments">
                        <lhs>PositionalArguments</lhs>
                        <rhs>(<nt def="prod-xpath40-Argument">Argument<!--$idref_lang_part = xpath40- --></nt> ++ ",")</rhs>
                     </prod>

                     <prod id="doc-xpath40-FunctionCall-Argument">
                        <lhs>Argument</lhs>
                        <rhs>
                           <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ArgumentPlaceholder">ArgumentPlaceholder<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-FunctionCall-ExprSingle">
                        <lhs>ExprSingle</lhs>
                        <rhs>
                           <nt def="prod-xpath40-ForExpr">ForExpr<!--$idref_lang_part = xpath40- --></nt>
                           <br/>|  <nt def="prod-xpath40-LetExpr">LetExpr<!--$idref_lang_part = xpath40- --></nt>
                           <br/>|  <nt def="prod-xpath40-QuantifiedExpr">QuantifiedExpr<!--$idref_lang_part = xpath40- --></nt>
                           <br/>|  <nt def="prod-xpath40-IfExpr">IfExpr<!--$idref_lang_part = xpath40- --></nt>
                           <br/>|  <nt def="prod-xpath40-OrExpr">OrExpr<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-FunctionCall-ArgumentPlaceholder">
                        <lhs>ArgumentPlaceholder</lhs>
                        <rhs>"?"</rhs>
                     </prod>

                     <prod id="doc-xpath40-FunctionCall-KeywordArguments">
                        <lhs>KeywordArguments</lhs>
                        <rhs>(<nt def="prod-xpath40-KeywordArgument">KeywordArgument<!--$idref_lang_part = xpath40- --></nt> ++ ",")</rhs>
                     </prod>

                     <prod id="doc-xpath40-FunctionCall-KeywordArgument">
                        <lhs>KeywordArgument</lhs>
                        <rhs>
                           <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>  ":="  <nt def="prod-xpath40-Argument">Argument<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>
                  </scrap>
                  <p>
                     <termdef term="static function call" id="dt-static-function-call">A <term>static function call</term>
               is an instance of the production <nt def="doc-xpath40-FunctionCall">FunctionCall<!--$spec = xpath40--></nt>: it
               consists of an EQName followed by a parenthesized list of zero or more arguments.</termdef>.</p>
                  <p>The EQName is expanded using the <termref def="dt-default-function-namespace-rule"/>.</p>
                  <p diff="add" at="A">The argument list consists of zero or more positional arguments,
               followed by zero or more keyword arguments.</p>
                  <p>
                     <termdef term="argument expression" id="dt-arg-expr">An argument to a function call is either an
               <term>argument expression</term> or an <nt def="prod-xpath40-ArgumentPlaceholder">ArgumentPlaceholder<!--$spec = xpath40--></nt> 
               (<code nobreak="false">?</code>); in both cases it may
            either be supplied positionally, or identified by a name (called a keyword).</termdef>
                  </p>
                  <p>This section is concerned with static function calls in which none of the arguments are
               <nt def="prod-xpath40-ArgumentPlaceholder">ArgumentPlaceholders<!--$spec = xpath40--></nt>. 
               Calls using one or more <nt def="prod-xpath40-ArgumentPlaceholder">ArgumentPlaceholders<!--$spec = xpath40--></nt> are covered in the 
               section <specref ref="id-partial-function-application"/>.</p>
                  <p>The <termref def="dt-expanded-qname">expanded QName</termref> 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 <termref def="dt-function-definition"/> 
               in the <termref def="dt-static-context">static context</termref>
                     <phrase> using the rules defined in the previous section</phrase>; if there is no match, a
               <termref def="dt-static-error">static error</termref> is raised <errorref class="ST" code="0017"/>.
               </p>
                  <p>Evaluation of static function calls is described in <specref ref="id-eval-static-function-call"/>
                     <phrase diff="del" at="B">,
               while evaluation of dynamic function calls is described in 
               <specref ref="id-eval-dynamic-function-call"/>
                     </phrase>.</p>
                  <p>Since the arguments of a function call are separated by commas, any <termref def="dt-arg-expr">argument expression</termref> that contains a top-level <termref def="dt-comma-operator">comma operator</termref> must be
               enclosed in parentheses. Here are some illustrative examples of
               static function calls:</p>
                  <ulist>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">my:three-argument-function(1, 2, 3)</code> denotes a static function call with three 
                     <phrase diff="add" at="A">positional</phrase> arguments. <phrase diff="add" at="A">The 
                  corresponding function declaration must define at least three parameters, and may define
                  more, provided they are optional.</phrase>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">my:two-argument-function((1, 2), 3)</code> denotes a static function call with two arguments, the first of which is a
                     sequence of two values. <phrase diff="add" at="A">The 
                        corresponding function declaration must define at least two parameters, and may define
                        more, provided they are optional.</phrase>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">my:two-argument-function(1, ())</code> denotes a static function call with two arguments, 
                     the second of which is the empty sequence.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">my:one-argument-function((1, 2,
                        3))</code> denotes a static function call with one argument that is a sequence of three
                     values. </p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">my:one-argument-function(( ))</code> denotes a static function call with one argument that is the empty sequence.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">my:zero-argument-function( )</code> denotes a static function call with zero arguments.</p>
                     </item>
                     <item diff="add" at="A">
                        <p>
                           <code role="parse-test" nobreak="false">lang(node := $n, language := 'de')</code> is a static function 
                     call with two keyword arguments. The corresponding function declaration defines two parameters,
                     a required parameter <code nobreak="false">language</code> and an optional parameter <code nobreak="false">node</code>.
                     This call supplies values for both parameters. It is equivalent to the call 
                     <code nobreak="false">fn:lang('de', $n)</code>. Note that the keyword arguments are in a different
                     order from the parameter declarations.
                  </p>
                     </item>
                     <item diff="add" at="A">
                        <p>
                           <code role="parse-test" nobreak="false">sort(//employee, key := fn($e) { xs:decimal($e/salary) })</code> is a static function 
                     call with one positional argument and one keyword argument. 
                     The corresponding function declaration defines three parameters,
                     a required parameter <code nobreak="false">$input</code>, an optional parameter <code nobreak="false">$collation</code>,
                     and an optional parameter <code nobreak="false">$key</code>
                     This call supplies values for the first and third parameters, leaving the second parameter (<code nobreak="false">$collation</code>)
                     to take its default value. The default value of the <code nobreak="false">$collation</code> parameter
                     is given as <code nobreak="false">fn:default-collation()</code>, so the value supplied to the function is the
                     default collation from the dynamic context of the caller. It is equivalent to the call 
                     <code nobreak="false">fn:sort(//employee, fn:default-collation(), fn($e) { xs:decimal($e/salary) })</code>.
                  </p>
                     </item>
                  </ulist>
                  <p>An <code nobreak="false">EQName</code> in a <code nobreak="false">KeywordArgument</code> is expanded 
               using the <termref def="dt-no-namespace-rule"/>.
            The keywords used in a function call (after expansion) must be distinct 
               <errorref class="ST" code="0017"/>.</p>
               </div4>
               <div4 id="id-eval-static-function-call" diff="chg" at="A">
                  <head>Evaluating Static Function Calls</head>
                  <p>This section applies to static function calls where none of the
            arguments is an <code nobreak="false">ArgumentPlaceholder</code>. For function calls involving
            placeholders, see <specref ref="id-partial-function-application"/>.</p>
                  <p>
                      When a static function call <var>FC</var> is evaluated
                      with respect to a static context <var>SC</var> and
                      a dynamic context <var>DC</var>,
                      the result is obtained as follows:
                    </p>
                  <olist>
                     <item>
                        <p>
                          The <termref def="dt-function-definition"/>
                           <var>FD</var> to be used is found in 
                        the <termref def="dt-statically-known-function-definitions"/> of <var>SC</var>.
                        </p>
                        <p>The <term>required arity</term> is the total number of arguments in the
                        function call, including both positional and keyword arguments.</p>
                        <p>
                              There can be at most one <termref def="dt-function-definition"/>
                           <var>FD</var> in the 
                              <termref def="dt-statically-known-function-definitions"/> component of <var>SC</var> whose function name
                              matches the <termref def="dt-expanded-qname"/> in <var>FC</var> and whose <termref def="dt-arity-range"/>
                              includes the arity of <var>FC</var>’s <code nobreak="false">ArgumentList</code>.
                           </p>
                        <p>If there is no such <termref def="dt-function-definition"/>, a static error <errorref class="ST" code="0017"/> is raised.</p>
                     </item>
                     <item>
                        <p>Each parameter in the <termref def="dt-function-definition"/>
                           <var>FD</var> is matched to an argument
                     expression as follows:</p>
                        <olist>
                           <item>
                              <p>If there are <var>N</var> positional arguments in the function call <var>FC</var>,
                           <!--and <var>FD</var> is not <termref def="dt-variadic"/>, -->then
                           the corresponding argument expressions are matched pairwise to the first <var>N</var>
                           parameters in the declaration. For this purpose the required parameters and optional parameters
                           in <var>FD</var> are concatenated into a single list, in order.</p>
                           </item>
                           <!--<item><p>If there are <var>N</var> positional arguments and no keyword arguments
                           in the function call <var>FC</var>,
                           and <var>FD</var> is <termref def="dt-variadic"/> with <var>M</var> declared
                           parameters, then:</p>
                           <olist>
                              <item><p>If <var>N</var> = <var>M-1</var>, then the <var>N</var>
                              supplied arguments are matched to the first <var>N</var> declared parameters,
                              and the <var>M</var>th parameter is bound to the empty sequence (which might cause
                              a type error if the declared type does not allow the empty sequence).</p></item>
                              <item><p>If <var>N</var> = <var>M</var>, then the <var>N</var>
                                 supplied arguments are matched to the first <var>N</var> declared parameters.</p></item>
                              <item><p>If <var>N</var> &gt; <var>M</var>, the values of the <var>M</var>th and subsequent arguments
                              are sequence-concatenated into a single value, which is matched to the <var>M</var>th
                              declared parameter. This means, for example, that if a variadic function <var>F</var>
                              with two declared parameters is called using a static function call of the form 
                                 <code>F(a, b, c)</code>, then the call is effectively equivalent to
                              <code>F(a, (b, c))</code>.</p>
                              <note><p>The combined value <code>(b, c)</code> must satisfy the required type
                              for the relevant parameter, after the coercion rules are applied.</p></note>
                              </item>
                           </olist>
                        </item>-->
                           <item>
                              <p>Any keyword arguments in <var>FC</var> are then matched to
                           parameters (whether required or optional) in <var>FD</var> by comparing the keyword
                           used in <var>FC</var> with the paramater name declared in <var>FD</var>.
                           Each keyword must match the name of a declared parameter <errorref class="ST" code="0017"/>, 
                           and this must be one that has not already
                           been matched to a positional argument. <errorref class="ST" code="0017"/>.</p>
                           </item>
                           <item>
                              <p>If any required parameter has not been matched to any argument in <var>FC</var>
                           by applying the above rules, a static error is reported <errorref class="ST" code="0017"/>
                              </p>
                           </item>
                           <item>
                              <p>If any optional parameter has not been matched to any argument in <var>FC</var>
                           by applying the above rules, then the parameter is matched to the 
                           default value expression for that parameter in <var>FD</var>.</p>
                           </item>
                        </olist>
                     </item>
                     <item>
                        <p>
                          Each argument expression established by the above rules is evaluated with respect to DC.
                          The order of argument evaluation is <termref def="dt-implementation-dependent"/> and it is not
                        required that an argument be evaluated if the function body can be evaluated without evaluating
                        that argument.</p>
                        <note>
                           <p>All argument expressions, including default value expressions, are evaluated in the dynamic
                     context of the function call. It is therefore possible to use a default value expression such as 
                     <code nobreak="false">.</code>, or <code nobreak="false">/</code>, or <code nobreak="false">fn:current-dateTime()</code>, whose value depends on the
                     dynamic context of the function call.</p>
                        </note>
                        <p>If the expression used for the default value of a parameter has no dependencies on the dynamic
                     context, then an implementation <rfc2119>may</rfc2119> choose to reuse the same value on repeated
                     function calls rather than re-evaluating it on each function call.</p>
                        <note>
                           <p>This is relevant, for example, if the expression constructs new nodes.</p>
                        </note>
                     </item>
                     <item>
                        <p>The result of evaluating the argument expression is converted to the required type (the
                     declared type associated with the corresponding parameter in the function declaration, defaulting
                     to <code nobreak="false">item()*</code>) by applying the <termref def="dt-coercion-rules"/>.</p>
                        <p>
                           <phrase diff="add" at="2023-12-12">This applies both to explicitly supplied arguments, and
                        to values obtained by evaluating default value expressions. In both cases a type
                        error will be raised if the value (after coercion) does not match the required type.</phrase>
                        </p>
                        <!--<p>In the case of a <termref def="dt-variadic"/> function, the coercion rules are applied
                     to the sequence-concatenation of any supplied arguments that are combined to provide a value
                     for the parameter.</p>-->
                     </item>
                     <item>
                        <p>The result of the function call is obtained as follows:</p>
                        <ulist>
                           <item>
                              <p>
                                 <var>FD</var>’s <phrase diff="chg" at="2023-03-11">body</phrase> is invoked
                                      in an implementation-dependent way.
                                      The processor makes the following information
                                      available to that invocation:
                                      
                                    </p>
                              <ulist>
                                 <item>
                                    <p>The converted argument values;</p>
                                 </item>
                                 <item diff="del" at="2023-03-11">
                                    <p diff="del" at="2023-03-11">
                                                An empty set of nonlocal variable bindings; and</p>
                                 </item>
                                 <item>
                                    <p diff="chg" at="2023-03-11">If the function is <termref def="dt-context-dependent"/>,
                                          the static context <var>SC</var> and dynamic context <var>DC</var> of the function call.
                                           </p>
                                 </item>
                              </ulist>
                              <p diff="del" at="2023-03-11">
                                      How this information is used is <termref def="dt-implementation-defined">implementation-defined</termref>.
                                      An API used to call external functions must state
                                      how the static and dynamic contexts are provided
                                      to a function that is called.
                                      The F&amp;O specification states how the static and dynamic contexts
                                      are used in each function that it defines. 
                                      <phrase role="xpath">
                                      A host language must state how the static and dynamic contexts
                                      are used in functions that it provides.
                                      </phrase>
                              </p>
                           </item>
                           <item>
                              <p>The result is converted to the required type (the
                                             declared return type in the function declaration, defaulting
                                             to <code nobreak="false">item()*</code>) by applying the <termref def="dt-coercion-rules"/>.</p>
                              <p>The result of applying the coercion rules is either an instance of <var>FD</var>’s return type
                                      or a dynamic error.
                                      This result is then the result of evaluating <var>FC</var>.</p>
                              <note>
                                 <p>A host language may define alternative rules for processing the result, especially
                                      in the case of external functions implemented using a non-XDM type system.</p>
                              </note>
                           </item>
                           <item>
                              <p>
                                      Errors raised by system functions are defined in
                                      <bibref ref="xpath-functions-40"/>.
                                    </p>
                           </item>
                           <item role="xpath">
                              <p>
                                      Errors raised by host-language-dependent functions are
                                      <termref def="dt-implementation-defined">implementation-defined</termref>.
                                    </p>
                           </item>
                        </ulist>
                        <example>
                           <head>A System Function</head>
                           <p>The following function call uses the function 
                                  <xspecref spec="FO40" ref="func-base-uri"/>.  Use of <code nobreak="false">SC</code> and <code nobreak="false">DC</code> and errors raised by this function are all defined in 
                                  <bibref ref="xpath-functions-40"/>.</p>
                           <eg role="parse-test" xml:space="preserve">base-uri()</eg>
                        </example>
                     </item>
                  </olist>
               </div4>
            </div3>
            <div3 id="id-dynamic-functions">
               <head>Function Items</head>
               <p>A <termref def="dt-function-item"/> is an XDM
            value that can be bound to a variable, or manipulated in various ways by XPath 4.0 expressions.
            The most significant such expression is a <termref def="dt-dynamic-function-call"/>, which supplies
            values of arguments and evaluates the function to produce a result.</p>
               <p>The syntax of dynamic function calls is defined in <specref ref="id-dynamic-function-invocation"/>.</p>
               <p>A number of constructs can be used to produce a <termref def="dt-function-item"/>, notably:</p>
               <ulist>
                  <item>
                     <p>A <term>named function reference</term> (see <specref ref="id-named-function-ref"/>)
               constructs a function item by reference to <termref def="dt-function-definition">function definitions</termref>
                  in the static context. For example, <function>fn:node-name#1</function>
               returns a function item whose effect is to call the static <function>fn:node-name</function> function
               with one argument.</p>
                  </item>
                  <item>
                     <p>An <term>inline function</term> (see <specref ref="id-inline-func"/>
                        <!-- and <specref ref="id-lambda-expressions"/>-->)
                  constructs a function item whose <phrase diff="chg" at="2023-03-11">body</phrase> is defined locally. For example, the
               construct <code nobreak="false">fn($x) { $x + 1 }</code> returns a function item whose effect is to increment
               the value of the supplied argument.</p>
                  </item>
                  <item>
                     <p>A <term>partial function application</term> (see 
                  <specref ref="id-partial-function-application"/>) derives one function item from another by supplying
               the values of some of its arguments. For example, <code nobreak="false">fn:ends-with(?, ".txt")</code> returns
               a function item with one argument that tests whether the supplied string ends with the substring
                  <code nobreak="false">".txt"</code>.</p>
                  </item>
                  <item>
                     <p>Maps and arrays are also function items. See <specref ref="id-map-constructors"/>
               and <specref ref="id-array-constructors"/>.</p>
                  </item>
                  <item diff="add" at="B">
                     <p>The <function>fn:function-lookup</function> function can be called to discover functions
               that are present in the <termref def="dt-dynamic-context"/>.</p>
                  </item>
                  <item diff="add" at="B">
                     <p>The <function>fn:load-xquery-module</function> function can be called to load functions
                  dynamically from an external XQuery library module.</p>
                  </item>
                  <item diff="add" at="B">
                     <p>Some system functions such as <function>fn:random-number-generator</function> 
                  and <function>fn:op</function> return a <termref def="dt-function-item"/> as their result.</p>
                  </item>
               </ulist>
               <p>These constructs are described in detail in the following sections, or in
               <bibref ref="xpath-functions-40"/>.</p>
            </div3>
            <div3 id="id-dynamic-function-invocation">
               <head>Dynamic Function Calls</head>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-DynamicFunctionCall">
                     <lhs>DynamicFunctionCall</lhs>
                     <rhs>
                        <nt def="prod-xpath40-PostfixExpr">PostfixExpr<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-PositionalArgumentList">PositionalArgumentList<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-DynamicFunctionCall-PostfixExpr">
                     <lhs>PostfixExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-PrimaryExpr">PrimaryExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-FilterExpr">FilterExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-DynamicFunctionCall">DynamicFunctionCall<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-LookupExpr">LookupExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-MethodCall">MethodCall<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-FilterExprAM">FilterExprAM<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-DynamicFunctionCall-PositionalArgumentList">
                     <lhs>PositionalArgumentList</lhs>
                     <rhs>"("  <nt def="prod-xpath40-PositionalArguments">PositionalArguments<!--$idref_lang_part = xpath40- --></nt>?  ")"</rhs>
                  </prod>

                  <prod id="doc-xpath40-DynamicFunctionCall-PositionalArguments">
                     <lhs>PositionalArguments</lhs>
                     <rhs>(<nt def="prod-xpath40-Argument">Argument<!--$idref_lang_part = xpath40- --></nt> ++ ",")</rhs>
                  </prod>

                  <prod id="doc-xpath40-DynamicFunctionCall-Argument">
                     <lhs>Argument</lhs>
                     <rhs>
                        <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ArgumentPlaceholder">ArgumentPlaceholder<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-DynamicFunctionCall-ExprSingle">
                     <lhs>ExprSingle</lhs>
                     <rhs>
                        <nt def="prod-xpath40-ForExpr">ForExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-LetExpr">LetExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-QuantifiedExpr">QuantifiedExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-IfExpr">IfExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-OrExpr">OrExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-DynamicFunctionCall-ArgumentPlaceholder">
                     <lhs>ArgumentPlaceholder</lhs>
                     <rhs>"?"</rhs>
                  </prod>
               </scrap>
               <p>
                  A <termref def="dt-dynamic-function-call"/>
                     consists of a base expression that returns the function and a
                     parenthesized list of zero or more arguments (<termref def="dt-arg-expr">argument expressions</termref> or
                     ArgumentPlaceholders).
               </p>
               <p>
                  A dynamic function call is evaluated as described in
                  <specref ref="id-eval-dynamic-function-call"/>.
               </p>
               <p>The following are examples of dynamic function calls:</p>
               <ulist>
                  <item>
                     <p>This example calls the function contained in <code nobreak="false">$f</code>, passing the arguments 2 and 3:
                        <eg role="parse-test" xml:space="preserve">$f(2, 3)</eg>
                     </p>
                  </item>
                  <item>
                     <p>This example fetches the second item from sequence <code nobreak="false">$f</code>, treats it as a function and calls it, passing an <code nobreak="false">xs:string</code> argument:
                        <eg role="parse-test" xml:space="preserve">$f[2]("Hi there")</eg>
                     </p>
                  </item>
                  <item>
                     <p>This example calls the function <code nobreak="false">$f</code> passing no arguments, and filters the result with a positional predicate:
                        <eg role="parse-test" xml:space="preserve">$f()[2]</eg>
                     </p>
                  </item>
               </ulist>
               <note diff="add" at="A">
                  <p>Arguments in a dynamic function call are always supplied positionally.</p>
               </note>
               <div4 id="id-eval-dynamic-function-call">
                  <head>Evaluating Dynamic Function Calls</head>
                  <changes>
                     <change issue="1240">A dynamic function call can now be applied to a sequence of functions, and in particular
               to the empty sequence. This makes it easier to chain a sequence of calls.</change>
                     <change issue="2500">The coercion rules now apply to the target of a dynamic function call, making
                  it possible to supply a JNode that wraps an array or map.</change>
                  </changes>
                  <p>This section applies to dynamic function calls whose arguments do not include
            an <code nobreak="false">ArgumentPlaceholder</code>. For function calls that include a placeholder,
            see <specref ref="id-partial-function-application"/>.</p>
                  <p diff="add" at="B">A <termref def="dt-dynamic-function-call"/>
            is an expression that is evaluated by calling a <termref def="dt-function-item"/>, which is
            typically obtained dynamically.</p>
                  <p>
                      When a dynamic function call <var>FC</var> is evaluated,
                      the result is obtained as follows:
                    </p>
                  <olist>
                     <item>
                        <p>
                          The base expression of the function call is evaluated,
                          and the <termref def="dt-coercion-rules"/> are applied
                          to the result with a required type of <code nobreak="false">function(*)*</code> (a sequence
                        of zero or more function items).
                     </p>
                     </item>
                     <item>
                        <p>The result of the dynamic function call is the <termref def="dt-sequence-concatenation"/>
                        of the results of applying each function item individually, retaining order. That is, the
                        result of <code nobreak="false">
                              <var>F</var>(<var>X</var>, <var>Y</var>, ...)</code> is 
                        <code nobreak="false">for $FI in <var>F</var> return <var>$FI</var>(<var>X</var>, <var>Y</var>, ...)</code>.
                        The result of a dynamic function call applied to a single function item <var>FI</var> is defined
                        by the rules that follow.
                     </p>
                     </item>
                     <item>
                        <p>
                           <errorref class="TY" code="0004"/>.
                              If the arity of <var>FI</var> does not match the number of arguments in the <code nobreak="false">ArgumentList</code>,
                              a type error is raised
                              <errorref class="TY" code="0004"/>.
                            </p>
                     </item>
                     <item>
                        <p>
                           <termref def="dt-arg-expr">Argument expressions</termref> are evaluated, 
                        producing <term>argument values</term>. The order of argument evaluation is <termref def="dt-implementation-dependent">implementation-dependent</termref> and an argument need not be evaluated 
                        if the function body can be evaluated without evaluating that argument.</p>
                     </item>
                     <item>
                        <p>
                          Each argument value is converted
                          to the corresponding parameter type in <var>FI</var>’s signature
                          by applying the <termref def="dt-coercion-rules"/>, resulting in a
                        <term>converted argument value</term>
                        </p>
                     </item>
                     <item>
                        <p>If <var>FI</var> is a map, it is evaluated as described in <specref ref="id-map-lookup"/>.</p>
                     </item>
                     <item>
                        <p>If <var>FI</var> is an array, it is evaluated as described in <specref ref="id-array-lookup"/>.</p>
                     </item>
                     <item>
                        <p>
                                  If <var>FI</var>’s <phrase diff="chg" at="2023-03-11">body</phrase> is 
                                  
                                  an XPath 4.0 expression
                                  
                                    (for example, if <var>FI</var> is
                                    
                                    an <termref def="dt-anonymous-function">anonymous function</termref>,
                                    or a
                                    <termref def="dt-partially-applied-function">partial application</termref>
                                    of such a function):
                                  
                                </p>
                        <olist>
                           <item>
                              <p>
                                 <var>FI</var>’s <phrase diff="chg" at="2023-03-11">body</phrase> 
                                      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
                                      
                                          <phrase role="xpath">
                                    <code nobreak="false">InlineFunctionExpr</code>
                                 </phrase>
                                      that contains the <code nobreak="false">FunctionBody</code>, and
                                      making the following changes:
                                    </p>
                              <ulist>
                                 <item>
                                    <p>
                                          The <termref def="dt-focus">focus</termref>
                                          (context value, context position, and context size)
                                          is <xtermref spec="DM40" ref="dt-absent"/>.
                                        </p>
                                 </item>
                                 <item>
                                    <p>
                                          In the <termref def="dt-variable-values">variable values</termref> component of the dynamic context,
                                          each converted argument value is bound to the
                                          corresponding parameter name.
                                        </p>
                                    <p>
                                       <phrase diff="chg" at="B">When this is done,
                                          the converted argument values retain
                                          their <termref def="dt-dynamic-type">dynamic types</termref>,
                                          even where these are <termref def="dt-subtype">subtypes</termref> 
                                          of the declared parameter types.</phrase>
                                          For example, a function with
                                          a parameter <code nobreak="false">$p</code> of type <code nobreak="false">xs:decimal</code>
                                          can be called with an argument of type <code nobreak="false">xs:integer</code>,
                                          which is derived from <code nobreak="false">xs:decimal</code>.
                                          During the processing of this function
                                          call, the value of <code nobreak="false">$p</code> inside the body of the function 
                                          retains its <termref def="dt-dynamic-type"/> of <code nobreak="false">xs:integer</code>.
                                        </p>
                                 </item>
                                 <item>
                                    <p>
                                       <var>FI</var>’s nonlocal variable bindings
                                          are also added to the <termref def="dt-variable-values">variable values</termref>.
                                          (Note that the names of the nonlocal variables
                                          are by definition disjoint from the parameter names,
                                          so there can be no conflict.)
                                        </p>
                                 </item>
                              </ulist>
                           </item>
                           <item>
                              <p>
                                      The value returned by evaluating the function body
                                      is then converted to the declared return type of <var>FI</var>
                                      by applying the
                                      <termref def="dt-coercion-rules">coercion rules</termref>.
                                      The result is then the result of evaluating <var>FC</var>.
                                    </p>
                              <p>
                                      As with argument values,
                                      the value returned by a function
                                      retains its <termref def="dt-dynamic-type"/>,
                                      which may be a <termref def="dt-subtype"/> of the declared return type of <var>FI</var>.
                                      For example, a function that has
                                      a declared return type of <code nobreak="false">xs:decimal</code>
                                      may in fact return a value of dynamic type <code nobreak="false">xs:integer</code>.
                                    </p>
                           </item>
                        </olist>
                     </item>
                     <item>
                        <p>                                  
                                  If the implementation of <var>FI</var> is
                                  not an XPath 4.0 expression
                                  (for example, if <var>FI</var> is
                                  a <termref def="dt-system-function">system function</termref>
                                    ), 
                                    the <phrase diff="chg" at="2023-03-11">body</phrase> 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 <specref ref="id-function-calls"/>).</p>
                        <p>Errors may be raised in the same way.</p>
                     </item>
                  </olist>
                  <example>
                     <head>Derived Types and Nonlocal Variable Bindings</head>
                     <p>
                        <code nobreak="false">$incr</code> 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 <code nobreak="false">xs:decimal</code>,
                                  the more specific type <code nobreak="false">xs:integer</code> is preserved in both cases.</p>
                     <eg role="parse-test" xml:space="preserve">
let $incr := 1
let $f := function($i as xs:decimal) as xs:decimal { $i + $incr }
return $f(5)</eg>
                  </example>
                  <example>
                     <head>Using the Context Value in an Anonymous Function</head>
                     <p>The following example will raise a <termref def="dt-type-error"/>
                        <errorref class="DY" code="0002"/>:</p>
                     <eg role="parse-test" xml:space="preserve">
let $vat := function() { @vat + @price }
return doc('wares.xml')/shop/article/$vat()</eg>
                     <p>Instead, the context value can be used as an argument to the anonymous function:</p>
                     <eg role="parse-test" xml:space="preserve">
let $vat := function($art) { $art/@vat + $art/@price }
return doc('wares.xml')/shop/article/$vat(.)</eg>
                     <p>Alternatively, the value can be referenced as a nonlocal variable binding:</p>
                     <eg role="parse-test" xml:space="preserve">
let $ctx := doc('wares.xml')/shop/article
let $vat := function() { for $a in $ctx return $a/@vat + $a/@price }
return $vat()
</eg>
                     <p>Finally, a <termref def="dt-focus-function"/> can be used.
                                       This binds the value of the argument to the context value within the function body:</p>
                     <eg role="parse-test" xml:space="preserve">
let $vat := function { @vat + @price }
return $vat(doc('wares.xml')/shop/article)
</eg>
                  </example>
                  <example>
                     <head>Applying multiple functions</head>
                     <p>A dynamic function call can call zero or more functions with the same arguments, returning
               the <termref def="dt-sequence-concatenation"/> of the result. For example:</p>
                     <eg role="parse-test" xml:space="preserve">(abs#1, round#1, floor#1, ceiling#1)(3.2)</eg>
                     <p>returns the sequence <code nobreak="false">(3.2, 3, 3, 4)</code>.</p>
                     <p>A common case for supplying a sequence of functions arises when the functions are arrays.
               For example:</p>
                     <eg xml:space="preserve">csv-to-arrays( string-join(("a,b,c", "p,q,r", "x,y,z"), char(10)) ) (2)</eg>
                     <p>returns the sequence <code nobreak="false">("b", "q", "y")</code>.</p>
                     <p>If the base expression evaluates to the empty sequence, the result
               is the empty sequence.</p>
                  </example>
                  <example>
                     <head>Invoking a map wrapped in a JNode</head>
                     <p>Consider the JSON text:</p>
                     <eg xml:space="preserve">[
   { "first": "John", "last": "Lennon"},
   { "first": "Paul", "last": "McCartney"},
   { "first": "George", "last": "Harrison"},
   { "first": "Ringo", "last": "Starr"}
]</eg>
                     <p>And let <code nobreak="false">$Beatles</code> be the result of parsing this using <function>fn:parse-json</function>.</p>
                     <p>Then the result of the function call <code nobreak="false">$Beatles/*("first")</code> is
               <code nobreak="false">("John", "Paul", "George", "Ringo")</code>.</p>
                     <p>Explanation: the value of <code nobreak="false">$Beatles</code> is an array. This is implicitly converted to a JNode
               because it appears as the left-hand operand of the <code nobreak="false">/</code> operator. The result of the expression
               <code nobreak="false">$Beatles/*</code> is therefore a sequence of four JNodes, each of them having a map as its 
                  <term>·content·</term> property.
               When the target of a dynamic function call is a sequence of JNodes, the sequence is coerced to type <code nobreak="false">function(*)*</code>,
               delivering a sequence comprising the four maps. These are called as functions, returning the values of the
               corresponding entries as <code nobreak="false">xs:string</code> items.</p>
                     <p>The same result could be achieved with the expression <code nobreak="false">$Beatles/*/first/jvalue()</code>.</p>
                  </example>
               </div4>
            </div3>
            <div3 id="id-partial-function-application">
               <head>Partial Function Application</head>
               <p>
                  <termdef term="partial function application"
                           id="dt-partial-function-application">
                     A <termref def="dt-static-function-call">static</termref> or 
                     <termref def="dt-dynamic-function-call">dynamic</termref>
                     function call is a <term>partial function application</term>
                     if one or more arguments is an <nt def="prod-xpath40-ArgumentPlaceholder">ArgumentPlaceholder<!--$spec = xpath40--></nt>.</termdef>
               </p>
               <p>The rules for partial function application in static function calls and dynamic function
               calls have a great deal in common, but they are stated separately below for clarity.</p>
               <p>Partial function application delivers
                  <termref def="dt-function-item">function items</termref>, whose
                  arity is equal to the number of placeholders in the call.</p>
               <p>A static partial function application always delivers one <termref def="dt-function-item"/>.
               A dynamic partial function application delivers one <termref def="dt-function-item"/> for each
               <termref def="dt-function-item"/> in the input.</p>
               <p>More specifically, each function item in the result of the partial function application is 
                  a <termref def="dt-partially-applied-function">partially applied function</termref>.
                  <termdef term="partially applied function" id="dt-partially-applied-function">A <term>partially applied function</term>
                  is a function created by  <termref def="dt-partial-function-application">partial function application</termref>.</termdef>
               </p>
               <p>For static function calls, the result is obtained as follows:</p>
               <olist>
                  <item>
                     <p>The <termref def="dt-function-definition"/>
                        <var>FD</var> to be partially applied
                        is determined in the same way as for a static function call without placeholders, 
                        as described in <specref ref="id-function-calls"/>.
                        For this purpose an <code nobreak="false">ArgumentPlaceholder</code> contributes to the count of
                        arguments.</p>
                  </item>
                  <item>
                     <p>The parameters of <var>FD</var> are classified into three categories:</p>
                     <ulist>
                        <item>
                           <p>Parameters that map to a placeholder, referred to as <term>placeholder parameters</term>.</p>
                        </item>
                        <item>
                           <p>Parameters for which an explicit value is given in the function call (either
                        positionally or by keyword), referred to as <term>explicitly supplied parameters</term>.</p>
                        </item>
                        <item>
                           <p>Parameters (which are necessarily optional parameters) for which no corresponding
                        argument is supplied, either as a placeholder or with an explicit value. These are referred to
                        as <term>defaulted parameters</term>.</p>
                        </item>
                     </ulist>
                     <note>
                        <p>A partial function application need not have any explicitly supplied parameters.
                        For example, the partial function application <code nobreak="false">fn:string(?)</code>
                        is allowed; it has exactly the same effect as the <termref def="dt-named-function-ref"/>
                           <function>fn:string#1</function>. </p>
                     </note>
                  </item>
                  <item>
                     <p>Explicitly supplied parameters and defaulted parameters are evaluated and 
                        converted to the required type using the rules for a static function call.
                        This may result in an error being raised.</p>
                     <p diff="add" at="2023-12-12">A type error is raised if any of the explicitly supplied or defaulted
                        parameters, after applying the
                        <termref def="dt-coercion-rules"/>, does not match the required type 
                        of the corresponding parameter.</p>
                     <p diff="add" at="2023-12-12">In addition, a dynamic error <rfc2119>may</rfc2119> 
                        be raised if any of the explicitly supplied or defaulted parameters does not match other constraints on the
                        value of that parameter (for example, if the value supplied for a parameter expecting
                        a regular expression is not a valid regular expression); or if the processor is
                        able to establish that evaluation of the resulting function will fail
                        for any other reason (for example, if an error is raised while evaluating 
                        a subexpression in the function
                        body that depends only on explicitly supplied and defaulted parameters).</p>
                     <p diff="add" at="2023-12-12">In all cases the error code is the same as for a static
                        function call supplying the same invalid value(s).</p>
                     <p diff="add" at="2024-02-02">In the particular case where all the supplied arguments
                     are placeholders, the error behavior <rfc2119>should</rfc2119> be the same as
                     for an equivalent <termref def="dt-named-function-ref"/>: for example, <function>fn:id#1</function>
                     fails if there is no context node, and <code nobreak="false">fn:id(?)</code>
                        <rfc2119>should</rfc2119>
                     fail likewise.</p>
                  </item>
                  <item>
                     <p>
                        The result is a <termref def="dt-partially-applied-function">partially applied function</termref> having
                        the following properties (which are defined in <xspecref spec="DM40" ref="function-items"/>):
                     </p>
                     <ulist>
                        <item>
                           <p>
                              <term>name</term>: The name of <var>FD</var> if all parameters map
                              to placeholders, that is, if the partial function application is
                              equivalent to the corresponding <termref def="dt-named-function-ref"/>.
                              Otherwise, the name is absent.
                           </p>
                        </item>
                        <item>
                           <p diff="add" at="2023-05-25">
                              <term>identity</term>: A new function
                           identity distinct from the identity of any other function item.</p>
                           <note>
                              <p>See also <specref ref="id-function-identity"/>.</p>
                           </note>
                        </item>
                        <item>
                           <p>
                              <term>arity</term>: The number of placeholders in the function call.</p>
                        </item>
                        <item>
                           <p>
                              <term>signature</term>: The parameters in the returned function
                              are the parameters of <var>FD</var>
                              that have been identified as placeholder parameters,
                              retaining the order in which the placeholders appear in the
                              function call. The result type of the returned function
                              is the same as the result type of <var>FD</var>.</p>
                           <p>An implementation which can determine a more specific signature (for example, 
                              through use of type analysis) is permitted to do so.
                           </p>
                        </item>
                        <item>
                           <p>
                              <term>annotations</term>: The annotations of 
                           <var>FD</var>.</p>
                        </item>
                        <item>
                           <p>
                              <term>body</term>: The body of <var>FD</var>.</p>
                        </item>
                        <item>
                           <p>
                              <term>captured context</term>: The
                              static and dynamic context of the function call, augmented,
                              for each explicitly supplied parameter and each defaulted parameter, with
                              a binding of the converted argument value
                              to the corresponding parameter name.
                           </p>
                        </item>
                     </ulist>
                     <note>
                        <p>A partial function application can be used to change the order
                           of parameters, for example <code nobreak="false">fn:contains(substring := ?, value := ?)</code>
                           returns a function item that is equivalent to <function>fn:contains#2</function>,
                           but with the order of arguments reversed.</p>
                     </note>
                     <example>
                        <head>Partial Application of a System Function</head>
                        <p>The following partial function application creates a function 
                           item that computes the sum of squares of a sequence.</p>
                        <eg role="parse-test" xml:space="preserve">let $sum-of-squares := fold-right(?, 0, function($a, $b) { $a*$a + $b })
return $sum-of-squares(1 to 3)</eg>
                        <p>
                           <code nobreak="false">$sum-of-squares</code> is an anonymous function. It has one parameter, named <code nobreak="false">$seq</code>, which is taken from the corresponding parameter in <function>fn:fold-right</function> (the other two parameters are fixed). The implementation is the implementation of <function>fn:fold-right</function>, which is a context-independent system function. The nonlocal bindings contain the fixed bindings for the second and third parameters of <function>fn:fold-right</function>.</p>
                     </example>
                  </item>
               </olist>
               <p>For dynamic function calls,  the result is obtained as follows:</p>
               <olist>
                  <item>
                     <p>
                          The base expression of the function call is evaluated.
                          If this is not of type <code nobreak="false">function(*)*</code> (a sequence
                        of zero or more function items) then a type error is raised.
                     </p>
                  </item>
                  <item>
                     <p>The result of the dynamic function call is the <termref def="dt-sequence-concatenation"/>
                        of the results of partial applying each function item, retaining order. That is, the
                        result of <code nobreak="false">
                           <var>F</var>(<var>X</var>, <var>Y</var>, ...)</code> is 
                        <code nobreak="false">for $FI in <var>F</var> return <var>$FI</var>(<var>X</var>, <var>Y</var>, ...)</code>.
                        The result of a dynamic function call applied to a single function item <var>FI</var> is defined
                        by the rules that follow.
                     </p>
                  </item>
                  <item>
                     <p>An <code nobreak="false">ArgumentPlaceholder</code> contributes to the count of
                        arguments.</p>
                  </item>
                  <item>
                     <p>The parameters of <var>FI</var> are classified into two categories:</p>
                     <ulist>
                        <item>
                           <p>Parameters that map to a placeholder, referred to as <term>placeholder parameters</term>.</p>
                        </item>
                        <item>
                           <p>Parameters for which an explicit value is given in the function call, 
                           referred to as <term>supplied parameters</term>.</p>
                        </item>
                     </ulist>
                     <note>
                        <p>A partial function application need not have any explicitly supplied parameters.
                        For example, if <code nobreak="false">$f</code> is a function with arity 2, then
                           the partial function application <code nobreak="false">$f(?, ?)</code> returns
                           a function that has exactly the same effect as <code nobreak="false">$f</code>. </p>
                     </note>
                  </item>
                  <item>
                     <p>Arguments corresponding to supplied parameters are evaluated
                        and converted to the required
                     type of the parameter, using the rules for dynamic function calls.</p>
                     <p diff="add" at="2023-12-12">A type error is raised if any of the supplied
                        parameters, after applying the
                        <termref def="dt-coercion-rules"/>, does not match the required type.</p>
                     <p diff="add" at="2023-12-12">In addition, a dynamic error <rfc2119>may</rfc2119> 
                     be raised if any of the supplied parameters does not match other constraints on the
                     value of that parameter (for example, if the value supplied for a parameter expecting
                     a regular expression is not a valid regular expression); or if the processor is
                     able to establish that evaluation of the resulting function will fail
                     for any other reason (for example, if an error is raised while evaluating 
                     a subexpression in the function
                     body that depends only on explicitly supplied parameters).</p>
                     <p diff="add" at="2023-12-12">In both cases the error code is the same as for a dynamic
                     function call supplying the same invalid value.</p>
                  </item>
                  <item>
                     <p>
                              The result of the partial function application is a  <termref def="dt-partially-applied-function">partially applied function</termref> with
                              the following properties (which are defined in <xspecref spec="DM40" ref="function-items"/>):
                            </p>
                     <ulist>
                        <item>
                           <p>
                              <term>name</term>:
                                  Absent.
                                </p>
                        </item>
                        <item>
                           <p>
                              <term>arity</term>: The number of placeholders in the function call.</p>
                        </item>
                        <item>
                           <p>
                              <term>signature</term>:
                                  The signature of <var>FI</var>,
                                  removing the types of supplied parameters.
				  
				                      An implementation which can determine a more specific signature (for example, 
				                      through use of type analysis) is permitted to do so.
                                </p>
                        </item>
                        <item>
                           <p>
                              <term>annotations</term>: The annotations of <var>FI</var>.</p>
                        </item>
                        <item>
                           <p>
                              <term>body</term>: The body of <var>FI</var>.
                                </p>
                        </item>
                        <item>
                           <p>
                              <term>captured context</term>: the
                                    captured context of <var>FI</var>, augmented,
                                  for each supplied parameter, with
                                  a binding of the converted argument value
                                  to the corresponding parameter name.
                                </p>
                        </item>
                     </ulist>
                     <note>
                        <p>In a dynamic partial function application, argument keywords
                                 are not available, so it is not possible to change the order of parameters.</p>
                     </note>
                     <example>
                        <head>Partial Application of an Anonymous Function</head>
                        <p>In the following example, <code nobreak="false">$f</code> is an anonymous function, and <code nobreak="false">$paf</code> is a partially applied function created from <code nobreak="false">$f</code>.</p>
                        <eg role="parse-test" xml:space="preserve">
let $f := function($seq, $delim) { fold-left($seq, "", concat(?, $delim, ?)) }
let $paf := $f(?, ".")
return $paf(1 to 5)
</eg>
                        <p>
                           <code nobreak="false">$paf</code> is also an anonymous function.  It has one parameter, named <code nobreak="false">$delim</code>, which is taken from the corresponding parameter in <code nobreak="false">$f</code>
                              (the other parameter is fixed).  The implementation of <code nobreak="false">$paf</code> is the implementation of <code nobreak="false">$f</code>, which is <code nobreak="false">fn:fold-left($seq, "", fn:concat(?, $delim, ?))</code>.  This implementation is associated with the <code nobreak="false">SC</code> and <code nobreak="false">DC</code> of the original expression in <code nobreak="false">$f</code>.  The nonlocal bindings associate the value <code nobreak="false">"."</code> with the parameter <code nobreak="false">$delim</code>.</p>
                     </example>
                  </item>
               </olist>
               <p>Partial function application never returns a map or an array.  If <code nobreak="false">$f</code> is a map or an array, then <code nobreak="false">$f(?)</code> is 
                  a partial function application that returns a function, but the function it returns is neither a map nor an array.</p>
               <example>
                  <head>Partial Application of a Map</head>
                  <p>The following partial function application converts a map to an equivalent function that is not a map.</p>
                  <eg role="parse-test" xml:space="preserve">let $a := { "A": 1, "B": 2 }(?)
return $a("A")</eg>
               </example>
            </div3>
            <!-- ******************************************************************** -->
            <div3 id="id-named-function-ref">
               <head>Named Function References</head>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-NamedFunctionRef">
                     <lhs>NamedFunctionRef</lhs>
                     <rhs>
                        <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>  "#"  <nt def="prod-xpath40-IntegerLiteral">IntegerLiteral<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                     <com>
                        <loc href="#parse-note-reserved-function-names">xgc: reserved-function-names</loc>
                     </com>
                  </prod>

                  <prod id="doc-xpath40-NamedFunctionRef-EQName">
                     <lhs>EQName</lhs>
                     <rhs>
                        <nt def="prod-xpath40-QName">QName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-NamedFunctionRef-IntegerLiteral">
                     <lhs>IntegerLiteral</lhs>
                     <rhs>
                        <nt def="prod-xpath40-Digits">Digits<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="doc-xpath40-NamedFunctionRef-Digits">
                     <lhs>Digits</lhs>
                     <rhs>
                        <nt def="prod-xpath40-DecDigit">DecDigit<!--$idref_lang_part = xpath40- --></nt>  ((<nt def="prod-xpath40-DecDigit">DecDigit<!--$idref_lang_part = xpath40- --></nt>  |  "_")*  <nt def="prod-xpath40-DecDigit">DecDigit<!--$idref_lang_part = xpath40- --></nt>)?</rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="doc-xpath40-NamedFunctionRef-DecDigit">
                     <lhs>DecDigit</lhs>
                     <rhs>[0-9]</rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>
               </scrap>
               <p>
                  <termdef term="named function reference" id="dt-named-function-ref">
          A <term>named function reference</term> is an instance of the production
                  <nt def="doc-xpath40-NamedFunctionRef">NamedFunctionRef<!--$spec = xpath40--></nt>: 
                  it is an expression (written <code nobreak="false">name#arity</code>)
                  which evaluates to a <termref def="dt-function-item"/>, the details
                  of the function item being based on the properties of a <termref def="dt-function-definition"/>
                  in the <termref def="dt-static-context"/>.</termdef>
               </p>
               <p>The name and arity of the required function are known statically.</p>
               <p>The EQName is expanded using the <termref def="dt-default-function-namespace-rule"/>.</p>
               <p>The <termref def="dt-expanded-qname"/> and arity must correspond to a <termref def="dt-function-definition"/>
               present in the <termref def="dt-static-context">static context</termref>.
            <phrase diff="add" at="variadicity">More specifically, for a named function reference <code nobreak="false">F#N</code>,
               there must be a <termref def="dt-function-definition"/> in the <termref def="dt-statically-known-function-definitions"/>
               whose name matches <var>F</var>, and whose <termref def="dt-arity-range"/> includes <var>N</var>
                  </phrase>.
               Call this <termref def="dt-function-definition"/>
                  <var>FD</var>.</p>
               <p diff="chg" at="2023-03-11">If <var>FD</var> is
          <termref def="dt-context-dependent"/> for the given arity, then the returned function item has
               a captured context comprising
          the static and dynamic context of the named function reference.</p>
               <note diff="chg" at="2023-03-11">
                  <p>In practice, it is necessary to retain only those
            parts of the static and dynamic context that can affect the outcome. These means it is 
            unnecessary to retain parts of the context that no <termref def="dt-system-function"/>
            depends on (for example, local variables), or parts that are invariant within an
            execution scope (for example, the implicit timezone).</p>
               </note>
               <example diff="add" at="B">
                  <head>A Context-Dependent Named Function Reference</head>
                  <p>Consider:</p>
                  <eg role="parse-test" xml:space="preserve">let $f := &lt;foo/&gt;/fn:name#0 return &lt;bar/&gt;/$f()</eg>
                  <p>The function <code nobreak="false">fn:name()</code>, with no arguments, returns the name of the context node. The function
               item delivered by evaluating the expression <function>fn:name#0</function> returns the name of the element that was the
               context node at the point where the function reference was evaluated (that is, the <code nobreak="false">&lt;foo&gt;</code> element).
               This expression therefore returns <code nobreak="false">"foo"</code>, not <code nobreak="false">"bar"</code>.</p>
               </example>
               <p diff="add" at="2023-12-12">An error is raised if the identified function depends on components of the static or dynamic
                  context that are not present, or that have unsuitable values. For example <errorref class="DY" code="0002" type="type"/> is raised for the expression <function>fn:name#0</function>
                  if the context item is absent, and <xerrorref spec="FO" class="DC" code="0001" type="dynamic"/> is raised for the call <function>fn:id#1</function> if the context item is not a node
                  in a tree that is rooted at a document node. The error that is raised is the same as the error that would
                  be raised by the corresponding function if called with the same static and dynamic context.</p>
               <p>If the <termref def="dt-expanded-qname">expanded QName</termref> and arity in a named function reference do not match the 
               name and <termref def="dt-arity-range"/> of a <termref def="dt-function-definition"/> in the
          static context, a static error is raised <errorref class="ST" code="0017"/>.</p>
               <p diff="chg" at="variadicity">
            The value of a <code nobreak="false">NamedFunctionRef</code>
               is a <termref def="dt-function-item">function item</termref>
                  <var>FI</var> 
               obtained from <var>FD</var>
               as follows:
               <ulist>
                     <item>
                        <p>
                           <term>name</term>: The name of <var>FD</var>.</p>
                     </item>
                     <item>
                        <p diff="add" at="2023-05-25">
                           <term>identity</term>:</p>
                        <ulist>
                           <item>
                              <p>If <var>FD</var> is <termref def="dt-context-dependent"/> for the given arity, then a new function
                        identity distinct from the identity of any other function item.</p>
                              <note>
                                 <p>In the general case, a function reference to a context-dependent function
                           will produce different results every time it is evaluated, because the resulting function
                           item has a <term>captured context</term> 
                              (see <xspecref spec="DM40" ref="function-items"/>) that includes the dynamic context
                           of the particular evaluation. Optimizers, however, are allowed to detect cases where
                           the captured context happens to be the same, or where any variations are immaterial,
                           and where it is therefore safe to return the same function item each time. This might be
                           the case, for example, where the only context dependency of a function is on the default
                           collation, and the default collation for both evaluations is known to be the same.</p>
                              </note>
                           </item>
                           <item>
                              <p>Otherwise, a function identity that is the same as that produced by the evaluation
                           of any other named function reference with the same function name and arity.</p>
                              <p>This rule applies even across different 
                                <xtermref spec="FO40" ref="execution-scope">execution scopes</xtermref>:
                             for example if a parameter to a call to <function>fn:transform</function> is set to the
                             result of the expression <function>fn:abs#1</function>, then the function item passed as the parameter
                                value will be identical to that obtained by evaluating the expression <function>fn:abs#1</function>
                             within the target XSLT stylesheet.</p>
                              <p>This rule also applies when the target function definition is 
                           <xtermref spec="FO40" ref="dt-nondeterministic">nondeterministic</xtermref>. 
                           For example all evaluations of the named function reference <function>map:keys#2</function>
                           return identical function items, even though two evaluations of <function>map:keys</function>
                           with the same arguments may produce different results.</p>
                           </item>
                        </ulist>
                        <note>
                           <p>See also <specref ref="id-function-identity"/>.</p>
                        </note>
                     </item>
                     <item>
                        <p>
                           <term>arity</term>: As specified in the named function reference.</p>
                     </item>
                     <item>
                        <p>
                           <term>signature</term>: Formed from the required types of the first
                        <var>A</var> parameters of <var>FD</var>, and the function result type of
                        <var>FD</var>.</p>
                        <!--<p>In the case where <var>FD</var> is <termref def="dt-variadic"/> and
                     <var>A</var> exceeds the number of declared parameters in <var>FD</var>,
                     the required type of each excess parameter in the result is the same
                     as the required type of the last declared parameter of <var>FD</var>.</p>
                     <note><p>The required type of each
                     parameter of <function>fn:concat#3</function> is thus <code>xs:anyAtomicType*</code>,
                     which means that a call such as <code>concat#3(("a","b"), ("c","d"), ())</code>
                     is allowed.</p></note>-->
                     </item>
                     <item>
                        <p>
                           <term>annotations</term>: The annotations of 
                           <var>FD</var>.</p>
                     </item>
                     <item>
                        <p>
                           <term>body</term>: The body of <var>FD</var>.</p>
                     </item>
                     <item>
                        <p diff="chg" at="2023-03-12">
                           <term>captured context</term>: Comprises the
                        static and dynamic context of the named function reference, augmented with
                        bindings of the names of parameters of <var>FD</var> beyond the
                        <var>A</var>’th parameter, to their respective default values.</p>
                        <note diff="chg" at="2023-03-12">
                           <p>In practice, it is necessary to retain
                        only the parts of the context that the function actually depends on
                        (if any).</p>
                        </note>
                     </item>
                  </ulist>
               </p>
               <note diff="add" at="variadicity">
                  <p>Consider the system function <function>fn:format-date</function>,
            which has an arity range of 2 to 5. The named function reference <function>fn:format-date#3</function>
            returns a function item whose three parameters correspond to the first three parameters
            of <function>fn:format-date</function>; the remaining two arguments will take their default values.
               To obtain an arity-3 function that binds to arguments 1, 2, and 5 of <function>fn:format-date</function>,
            use the partial function application <code nobreak="false">format-date(?, ?, place := ?)</code>.</p>
               </note>
               <p>The following are examples of named function references:
          </p>
               <ulist>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">fn:abs#1</code> references the <function>fn:abs</function> function which takes a single argument.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">fn:concat#5</code> references the <function>fn:concat</function> function which takes 5 arguments.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">local:myfunc#2</code> references a function named <code nobreak="false">local:myfunc</code> which takes 2 arguments.</p>
                  </item>
               </ulist>
               <note diff="add" at="A">
                  <p>Function items, as values in the data model, have a fixed arity, and
            a dynamic function call always supplies the arguments positionally. <!--Although the base function
            referred to may be variadic, the result of evaluating the function reference is a function that
            has fixed arity. -->In effect, the result of evaluating <code nobreak="false">my:func#3</code> is the
            same as the result of evaluating the inline function expression <code nobreak="false">fn($x, $y, $z) { my:func($x, $y, $z) }</code>,
            except that the returned function has a name (it retains the name <code nobreak="false">my:func</code>).</p>
               </note>
            </div3>
            <div3 id="id-inline-func">
               <head>Inline Function Expressions</head>
               <changes>
                  <change issue="1192" PR="1197" date="2024-05-21">
                  In inline function expressions, the keyword <code nobreak="false">function</code> may be abbreviated
                  as <code nobreak="false">fn</code>.
               </change>
                  <change issue="503" PR="521" date="2023-05-30">New abbreviated syntax is introduced 
                     (<termref def="dt-focus-function"/>) 
                     for simple inline functions taking a single argument. 
                     An example is <code nobreak="false">fn { ../@code }</code>
                  </change>
               </changes>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-InlineFunctionExpr">
                     <lhs>InlineFunctionExpr</lhs>
                     <rhs>("function"  |  "fn")  <nt def="prod-xpath40-FunctionSignature">FunctionSignature<!--$idref_lang_part = xpath40- --></nt>?  <nt def="prod-xpath40-FunctionBody">FunctionBody<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-InlineFunctionExpr-FunctionSignature">
                     <lhs>FunctionSignature</lhs>
                     <rhs>"("  <nt def="prod-xpath40-ParamList">ParamList<!--$idref_lang_part = xpath40- --></nt>  ")"  <nt def="prod-xpath40-TypeDeclaration">TypeDeclaration<!--$idref_lang_part = xpath40- --></nt>?</rhs>
                  </prod>

                  <prod id="doc-xpath40-InlineFunctionExpr-ParamList">
                     <lhs>ParamList</lhs>
                     <rhs>(<nt def="prod-xpath40-VarNameAndType">VarNameAndType<!--$idref_lang_part = xpath40- --></nt> ** ",")</rhs>
                  </prod>

                  <prod id="doc-xpath40-InlineFunctionExpr-VarNameAndType">
                     <lhs>VarNameAndType</lhs>
                     <rhs>"$"  <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-TypeDeclaration">TypeDeclaration<!--$idref_lang_part = xpath40- --></nt>?</rhs>
                  </prod>

                  <prod id="doc-xpath40-InlineFunctionExpr-EQName">
                     <lhs>EQName</lhs>
                     <rhs>
                        <nt def="prod-xpath40-QName">QName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-InlineFunctionExpr-TypeDeclaration">
                     <lhs>TypeDeclaration</lhs>
                     <rhs>"as"  <nt def="prod-xpath40-SequenceType">SequenceType<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-InlineFunctionExpr-SequenceType">
                     <lhs>SequenceType</lhs>
                     <rhs>("empty-sequence"  "("  ")")<br/>|  (<nt def="prod-xpath40-ItemType">ItemType<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-OccurrenceIndicator">OccurrenceIndicator<!--$idref_lang_part = xpath40- --></nt>?)</rhs>
                  </prod>

                  <prod id="doc-xpath40-InlineFunctionExpr-FunctionBody">
                     <lhs>FunctionBody</lhs>
                     <rhs>
                        <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-InlineFunctionExpr-EnclosedExpr">
                     <lhs>EnclosedExpr</lhs>
                     <rhs>"{"  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>?  "}"</rhs>
                  </prod>
               </scrap>
               <p>
                  <termdef term="inline function expression" id="dt-inline-func">An 
                  <term>inline function expression</term> is an instance of the
                  construct <nt def="doc-xpath40-InlineFunctionExpr">InlineFunctionExpr<!--$spec = xpath40--></nt>. When evaluated, 
                  an inline function expression creates
          an <termref def="dt-anonymous-function">anonymous function</termref>
          whose properties are defined directly in the inline function expression.</termdef> 
               An inline function expression defines the names and types of the parameters to the function,
          the type of the result, and the body of the function.</p>
               <p diff="add" at="2023-05-25">An <termref def="dt-inline-func"/> whose 
               <nt def="prod-xpath40-FunctionSignature">FunctionSignature<!--$spec = xpath40--></nt> is omitted
               is known as a <termref def="dt-focus-function"/>. Focus functions are 
               described in <specref ref="id-focus-functions"/>.</p>
               <p>
                  <termdef id="dt-anonymous-function" term="anonymous function">
             An <term>anonymous function</term> is a <termref def="dt-function-item"/> with no name.  
             Anonymous functions may be created, for example, by evaluating an inline function 
             expression or by partial function application.</termdef>
               </p>
               <p diff="add" at="2023-07-04">The keywords <code nobreak="false">function</code> and <code nobreak="false">fn</code> 
               are synonymous.</p>
               <p>The syntax allows the names and types of the function argument to be declared, along
           with the type of the result:</p>
               <eg xml:space="preserve">function($x as xs:integer, $y as xs:integer) as xs:integer { $x + $y }</eg>
               <p>The types can be omitted<phrase diff="add" at="2023-07-04">, and the keyword can be abbreviated</phrase>:</p>
               <eg xml:space="preserve">fn($x, $y) { $x + $y }</eg>
               <p diff="add" at="A">A zero-arity function can be written as, for example, <code nobreak="false">fn() { current-date() }</code>.</p>
               <p>
          If a function parameter is declared using a name but no type, its default type is <code nobreak="false">item()*</code>.
                  <!--<phrase diff="add" at="A">If it is bound to the context value using the notation <code>.</code>,
                  the implicit type is <code>item()</code>.</phrase>-->
               If the result type is omitted, its default result type is <code nobreak="false">item()*</code>.
          </p>
               <p>
          The parameters of an inline function expression are considered to be variables whose scope is the function body. It is a static error
          <errorref class="ST" code="0039"/> for an inline function expression to have more than one parameter with the same name.
          </p>
               <p>
          The static context for the function body is inherited from the location of the inline function expression.
          </p>
               <p>
          The variables in scope for the function body include all variables representing the function parameters, as well as all variables that
          are in scope for the inline function expression.</p>
               <note>
                  <p>
            Function parameter names can mask variables that would otherwise be in scope for the function body.
          </p>
               </note>
               <p>The result of an inline function expression is a single function item
                  with the following properties (as defined in <xspecref spec="DM40" ref="function-items"/>):</p>
               <ulist>
                  <item>
                     <p>
                        <term>name</term>:
              Absent.
            </p>
                  </item>
                  <item>
                     <p diff="add" at="2023-05-25">
                        <term>identity</term>: A new function
                              identity distinct from the identity of any other function item.</p>
                     <note>
                        <p>See also <specref ref="id-function-identity"/>.</p>
                     </note>
                  </item>
                  <item>
                     <p>
                        <term>signature</term>:
              A <code nobreak="false">FunctionType</code>
              constructed from the
              
                           <code nobreak="false">SequenceType</code>s in the <code nobreak="false">InlineFunctionExpr</code>.
	      An implementation which can determine a more specific signature (for example, through use of type analysis of the function’s body) is permitted to do so.
            </p>
                  </item>
                  <item>
                     <p>
                        <term>annotations</term>: 
                              
                              <phrase role="xpath">None.</phrase>
                     </p>
                  </item>
                  <item>
                     <p>
                        <term>body</term>:
              The <code nobreak="false">FunctionBody</code> of the <code nobreak="false">InlineFunctionExpr</code>.
            </p>
                  </item>
                  <item>
                     <p diff="chg" at="2023-03-11">
                        <term>captured context</term>: the static context
                           is the static context of the inline function expression. The dynamic context has an absent
                           <termref def="dt-focus"/>, and a set of variable bindings
                           comprising the <termref def="dt-variable-values">variable values</termref> component
                           of the dynamic context of the <code nobreak="false">InlineFunctionExpr</code>.
            </p>
                  </item>
               </ulist>
               <p>The following are examples of some inline function expressions:</p>
               <ulist>
                  <item>
                     <p>This example creates a function that takes no arguments and returns a sequence of the first 6 primes:
                <eg role="parse-test" xml:space="preserve">function() as xs:integer+ { 2, 3, 5, 7, 11, 13 }</eg>
                     </p>
                  </item>
                  <item>
                     <p>This example creates a function that takes two <code nobreak="false">xs:double</code> arguments and returns their product:
                <eg role="parse-test" xml:space="preserve">fn($a as xs:double, $b as xs:double) as xs:double { $a * $b }</eg>
                     </p>
                  </item>
                  <item>
                     <p>This example creates and invokes a function that captures the value of a local variable in its scope:
                        <eg role="parse-test" xml:space="preserve">let $incrementors := (
  for $x in 1 to 10
  return function($y) as xs:integer { $x + $y }
)
return $incrementors[2](4)</eg>
                     </p>
                     <p>The result of this expression is <code nobreak="false">6</code>
                     </p>
                  </item>
               </ulist>
               <div4 id="id-focus-functions">
                  <head>Focus Functions</head>
                  <p>
                     <termdef id="dt-focus-function" term="focus function">A <term>focus function</term>
               is an inline function expression in which the function signature is implicit: the function takes
               a single argument of type <code nobreak="false">item()*</code> (that is, any value), and binds this to the 
                  context value when evaluating
               the function body, which returns a result of type <code nobreak="false">item()*</code>.</termdef>
                  </p>
                  <p>Here are some examples of focus functions:</p>
                  <ulist>
                     <item>
                        <p>
                           <code nobreak="false">fn { @age }</code> - a function that expects a node as its argument, and returns
                  the <code nobreak="false">@age</code> attribute of that node.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">fn { . + 1 }</code> - a function that expects a number as its argument, and returns
                  that number plus one.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">function { `${ . }` }</code> - a function that expects a string as its argument, and prepends
                     a <code nobreak="false">"$"</code> character.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">function { head(.) + foot(.) }</code> - a function that expects a sequence of numbers
                     as its argument, and returns the sum of the first and last items in the sequence.</p>
                     </item>
                  </ulist>
                  <p>Focus functions are often useful as arguments to simple higher-order functions such as <function>fn:sort</function>.
               For example, to sort employees by salary, write <code nobreak="false">sort(//employee, (), fn { +@salary })</code>.
               (The unary plus has the effect of converting the attribute’s value to a number, for numeric sorting).</p>
                  <p>Focus functions can also be useful on the right-hand side of the <termref def="dt-sequence-arrow-operator"/>
                  and <termref def="dt-mapping-arrow-operator"/>.
               For example, <code nobreak="false">$s =&gt; tokenize() =!&gt; fn { `"{.}"` }()</code> first tokenizes the string <code nobreak="false">$s</code>,
               then wraps each token in double quotation marks.</p>
                  <p>The result of calling the <code nobreak="false">function { EXPR }</code> (or <code nobreak="false">fn { EXPR }</code>), with
                  a single argument whose value is <var>$Z</var> arguments, is obtained by evaluating <code nobreak="false">EXPR</code>
                  with a <termref def="dt-fixed-focus"/> in which the context value is <var>$Z</var>, the context position is 1 (one),
                  and the context size is 1 (one).</p>
                  <p>The expression <code nobreak="false">function { EXPR }</code> is thus formally equivalent to the expression
               <code nobreak="false">function($Z as item()*) as item()* { $Z -&gt; (EXPR) }</code>, where <code nobreak="false">$Z</code> is some variable name
               that is otherwise unused. Here <code nobreak="false">-&gt;</code> is the pipeline operator described
               in <specref ref="id-pipeline-operator"/>.</p>
                  <p>For example, the expression <code nobreak="false">every(1 to 10, fn { . gt 0 })</code> returns <code nobreak="false">true</code>.</p>
               </div4>
            </div3>
            <div3 id="id-function-identity">
               <head>Function Identity</head>
               <p>It is sometimes useful to be able to establish whether two variables refer to the same function
               or to different functions. For this purpose, every function item has an identity. Functions with the
               same identity are indistinguishable in every way; in particular, any function call with identical
               arguments will produce an identical result.</p>
               <p>In general, evaluation of an expression that returns a function item other than one that was
               present in its operands delivers a function item whose identity is unique, and thus distinct
               from any other function item. There are two exceptions to this rule:</p>
               <ulist>
                  <item>
                     <p>Evaluating a function reference such as <code nobreak="false">count#1</code> returns the same function
                  every time. Specifically, if the function name identifies a <termref def="dt-function-definition"/>
                  that is not <termref def="dt-context-dependent"/> (which is the most usual case), then all 
                     function references using this function name and arity return the same function.
                  For more details see <specref ref="id-named-function-ref"/>.</p>
                  </item>
                  <item>
                     <p>An optimizer is permitted to rewrite <xtermref spec="FO40" ref="dt-deterministic"/>
                     expressions in such a way that repeated evaluation is avoided, and this may be
                     done without consideration of function identity. For example:</p>
                     <ulist>
                        <item>
                           <p>If the expression
                           <code nobreak="false">contains(?, "e")</code> appears within the body of a <code nobreak="false">for</code>
                           clause, or if the same expression is written repeatedly in a query, then an
                           optimizer may decide to evaluate it once only, and thus return the same function
                           item each time.</p>
                        </item>
                        <item>
                           <p>Similarly, if the expression <code nobreak="false">fn($x) { $x + 1 }</code>
                           appears more than once, or is evaluated repeatedly, then it may return the same
                           function each time.</p>
                        </item>
                        <item>
                           <p>Optimizers are allowed to replace any expression with an
                           equivalent expression. For example, <code nobreak="false">count(?)</code> may be rewritten as
                           <code nobreak="false">count#1</code>. Similarly, <code nobreak="false">fn($x) { $x + 1 }</code> may be
                           rewritten as <code nobreak="false">fn($y) { $y + 1 }</code>. This may lead to different
                           expressions returning identical function items.</p>
                        </item>
                        <item>
                           <p>In principle, two function items are not identical if they
                           differ in their captured context. Optimizers, however, will often
                           be able to eliminate parts of the captured context that a function does
                           not actually use. For example, an inline function expression delivers
                           a function item whose captured context includes the values of all nonlocal
                           in-scope variables; but in practice the implementation is unlikely to retain the
                           values of such variables unless they are actually referenced.
                        </p>
                        </item>
                     </ulist>
                  </item>
               </ulist>
            </div3>
         </div2>
         <div2 id="id-path-expressions">
            <head>Path Expressions</head>
            <changes>
               <change issue="2054">
               Path expressions are extended to handle JNodes (found in trees of maps and arrays)
               as well as XNodes (found in trees representing parsed XML).
            </change>
            </changes>
            <scrap headstyle="show">
               <prod id="doc-xpath40-PathExpr">
                  <lhs>PathExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-AbsolutePathExpr">AbsolutePathExpr<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-RelativePathExpr">RelativePathExpr<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
                  <com>
                     <loc href="#parse-note-leading-lone-slash">xgc: leading-lone-slash</loc>
                  </com>
               </prod>

               <prod id="doc-xpath40-PathExpr-AbsolutePathExpr">
                  <lhs>AbsolutePathExpr</lhs>
                  <rhs>("/"  <nt def="prod-xpath40-RelativePathExpr">RelativePathExpr<!--$idref_lang_part = xpath40- --></nt>?)  |  ("//"  <nt def="prod-xpath40-RelativePathExpr">RelativePathExpr<!--$idref_lang_part = xpath40- --></nt>)</rhs>
               </prod>

               <prod id="doc-xpath40-PathExpr-RelativePathExpr">
                  <lhs>RelativePathExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-StepExpr">StepExpr<!--$idref_lang_part = xpath40- --></nt>  (("/"  |  "//")  <nt def="prod-xpath40-StepExpr">StepExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
               </prod>
            </scrap>
            <p>
               <termdef id="dt-path-expression" term="path expression">A <term>path expression</term>
            is either an <termref def="dt-absolute-path-expression"/> or a
            <termref def="dt-relative-path-expression"/>
               </termdef>
            </p>
            <p>
               <termdef id="dt-absolute-path-expression" term="absolute path expression">
            An <term>absolute path expression</term> is an instance 
            of the production <nt def="prod-xpath40-AbsolutePathExpr">AbsolutePathExpr<!--$spec = xpath40--></nt>:
            it consists of either (a) the operator <code nobreak="false">/</code> followed by zero or more 
            operands separated by <code nobreak="false">/</code> or <code nobreak="false">//</code> operators, or (b) the operator <code nobreak="false">//</code>
            followed by one or more operands separated by <code nobreak="false">/</code> or <code nobreak="false">//</code>
            operators.</termdef>
            </p>
            <p>
               <termdef id="dt-relative-path-expression" term="relative path expression">
            A <term>relative path expression</term> is a <termref def="dt-non-trivial"/>
            instance of the production <nt def="doc-xpath40-RelativePathExpr">RelativePathExpr<!--$spec = xpath40--></nt>:
            it consists of two or more operand expressions 
            separated by <code nobreak="false">/</code> or <code nobreak="false">//</code> operators.</termdef>
            </p>
            <p>
               <termdef id="dt-step" term="step">The operands of a path expression
            are conventionally referred to as <term>steps</term>.</termdef>
            </p>
            <note>
               <p>The term <term>step</term> must not be confused with
         <termref def="dt-axis-step"/>. A <term>step</term> can be any kind of
         expression, often but not necessarily an <termref def="dt-axis-step"/>,
         while an <termref def="dt-axis-step"/> can be used in any expression
         context, not necessarily as a <termref def="dt-step"/> in a path
         expression.</p>
            </note>
            <p>A path expression is typically used to locate <termref def="dt-GNode">GNodes</termref> 
            within <termref def="dt-GTree">GTrees</termref>. </p>
            <note>
               <p>Note the terminology:</p>
               <ulist>
                  <item>
                     <p>A <termref def="dt-GNode"/> is a generalized node, either an
               <termref def="dt-XNode"/> or a <termref def="dt-JNode"/>.</p>
                  </item>
                  <item>
                     <p>A <termref def="dt-GTree"/> is a generalized tree, either an
               <termref def="dt-XTree"/> or a <termref def="dt-JTree"/>.</p>
                  </item>
               </ulist>
            </note>
            <p>The following definitions are copied from the data model specification,
         for convenience:</p>
            <ulist>
               <item>
                  <p>
                     <termdef id="dt-JTree" term="JTree">A tree that is rooted at a parentless
    <termref def="dt-JNode"/> is referred to as a <term>JTree</term>.</termdef>
                  </p>
               </item>
               <item>
                  <p>
                     <termdef id="dt-XTree" term="XTree">A tree that is rooted at a parentless
    <termref def="dt-XNode"/> is referred to as an <term>XTree</term>.</termdef>
                  </p>
               </item>
               <!--<item><p><termdef id="dt-GNode" term="GNode">The term <term>generic node</term> or <term>GNode</term>
    is a collective term for <termref def="dt-XNode">XNodes</termref> (more commonly called simply
      <termref def="dt-node">nodes</termref>) representing
    the parts of an XML document, and <termref def="dt-JNode">JNodes</termref>, 
    often used to represent the parts of a JSON document.</termdef></p></item>
         <item><p><termdef id="dt-JNode" term="JNode">A <term>JNode</term> is a kind of <termref def="dt-item"/>
      used to represent a value within the context of a tree of <termref def="dt-map">maps</termref>
      and <termref def="dt-array">arrays</termref>. A root <term>JNode</term> represents
      a map or array; a non-root <term>JNode</term> represents a <termref def="dt-member"/> of an 
      array or an <termref def="dt-entry"/> in a map.</termdef></p></item>-->
               <item>
                  <p>
                     <termdef id="dt-GTree" term="GTree">The term <term>GTree</term>
         means <termref def="dt-JTree"/> or <termref def="dt-XTree"/>.</termdef>
                  </p>
               </item>
            </ulist>
            <p>
               <termref def="dt-absolute-path-expression">Absolute path expressions</termref> 
            (those starting with an initial <code nobreak="false">/</code>
            or <code nobreak="false">//</code>), start their selection from the root GNode of a GTree;
            relative path expressions (those without a leading <code nobreak="false">/</code> or
            <code nobreak="false">//</code>) start from the <termref def="dt-context-value"/>.</p>
            <div3 id="id-absolute-path-expressions">
               <head>Absolute Path Expressions</head>
               <p>The expression consisting of <code nobreak="false">/</code> on its own
            is treated as an abbreviation for the 
            <termref def="dt-path-expression"/>
                  <code nobreak="false">/.</code>.</p>
               <p>An expression of the form <code nobreak="false">/<var>PP</var>
                  </code> (that is, a <termref def="dt-path-expression"/>
            with a leading <code nobreak="false">/</code>) is treated as an abbreviation for
	 the expression <code nobreak="false">self::gnode()/(fn:root(.) treat as (document-node()|jnode())/<var>PP</var>
                  </code>. 
            The effect of this expansion is that for every item <var>J</var> 
            in the context value <var>V</var>:</p>
               <olist>
                  <item>
                     <p>A <termref def="dt-type-error"/> occurs if <var>J</var> is not a GNode
	       <errorref class="TY" code="0020"/>.</p>
                  </item>
                  <item>
                     <p>The root GNode <var>R</var> of the GTree containing <var>J</var> is selected.</p>
                  </item>
                  <item>
                     <p>A <termref def="dt-type-error"/> occurs if <var>R</var> is neither a JNode nor 
	       a document node <errorref class="DY" code="0050"/>.</p>
                  </item>
                  <item>
                     <p>The expression that follows the leading <code nobreak="false">/</code> is evaluated with 
	       <var>R</var> as the context value.</p>
                  </item>
               </olist>
               <note>
                  <p>If the context value includes a map or array, it is <emph>not</emph>
            converted implicitly to a JNode; rather, a type error occurs.</p>
               </note>
               <p>The results of these multiple evaluations are then combined into a single sequence;
       if the result is a set of GNodes, the GNodes are delivered in document order with
       duplicates eliminated.</p>
               <note>
                  <p id="Chg-slash-note">The <code nobreak="false">/</code> character
	 can be used either as a complete expression or as the
	 beginning of a longer <termref def="dt-path-expression"/> such as
	 <code nobreak="false">/*</code>.  Also, <code role="parse-test" nobreak="false">*</code>
	 is both the multiply operator and a wildcard in path
	 expressions.  This can cause parsing difficulties when
	 <code nobreak="false">/</code> appears on the left-hand side of
	 <code nobreak="false">*</code>.  This is resolved using the <loc xmlns:xlink="http://www.w3.org/1999/xlink"
                          href="#parse-note-leading-lone-slash"
                          xlink:type="simple"
                          xlink:show="replace"
                          xlink:actuate="onRequest">leading-lone-slash
	 </loc> constraint.  For example, <code role="parse-test" nobreak="false">/*</code> and <code role="parse-test" nobreak="false">/
	 *</code> are valid path expressions containing wildcards,
	 but <code nobreak="false">/*5</code> and <code nobreak="false">/ * 5</code> raise syntax
	 errors. Parentheses must be used when <code nobreak="false">/</code> is
	 used on the left-hand side of an operator that could be confused with a node test, as in <code role="parse-test" nobreak="false">(/) * 5</code>. Similarly, <code nobreak="false">4 + / *
	 5</code> raises a syntax error, but <code role="parse-test" nobreak="false">4 + (/) * 5</code> is a valid expression.
	 The expression <code role="parse-test" nobreak="false">4 + /</code> is also
	 valid, because <code nobreak="false">/</code> does not occur on the left-hand
	 side of the operator.</p>
                  <p>Similarly, in the expression <code role="parse-test" nobreak="false">/
	 union /*</code>, <code nobreak="false">union</code> is interpreted as an element name
	 rather than an operator. For it to be parsed as an operator,
	 the expression should be written <code role="parse-test" nobreak="false">(/)
	 union /*</code>.</p>
               </note>
               <p>An expression of the form <code nobreak="false">//<var>PP</var>
                  </code> (that is, an <termref def="dt-absolute-path-expression"/>
            with a leading <code nobreak="false">//</code>) is treated as an abbreviation for
            the expression <code nobreak="false">self::gnode()/(fn:root(.) treat as (document-node()|jnode())/descendant-or-self::gnode()/<var>PP</var>
                  </code>. 
            The effect of this expansion is that for every item <var>J</var> 
            in the context value <var>V</var>:</p>
               <olist>
                  <item>
                     <p>A <termref def="dt-type-error"/> occurs if <var>J</var> is not a GNode
               <errorref class="TY" code="0020"/>.</p>
                  </item>
                  <item>
                     <p>The root GNode <var>R</var> of the GTree containing <var>J</var> is selected.</p>
                  </item>
                  <item>
                     <p>A <termref def="dt-type-error"/> occurs if <var>R</var> is neither a JNode nor a document node
               <errorref class="DY" code="0050"/>.</p>
                  </item>
                  <item>
                     <p>The descendants of <var>R</var> are selected, along with <var>R</var> itself.</p>
                  </item>
                  <item>
                     <p>For every GNode <var>D</var> in this set of GNodes, the expression that 
               follows the leading <code nobreak="false">//</code> is evaluated with <var>D</var> as the context value.</p>
                  </item>
               </olist>
               <p>The results of these multiple evaluations are then combined into a single sequence;
            if the result is a set of GNodes, the GNodes are delivered in document order with
            duplicates eliminated.</p>
               <p>If the context value is not a sequence of GNodes, a
	 <termref def="dt-type-error">type error</termref> is
	 raised <errorref class="TY" code="0020"/>. At evaluation time, if the
	 root GNode of any item in the context value is not a document node or a JNode, a
	 <termref def="dt-type-error"/> is
	 raised <errorref class="DY" code="0050"/>.</p>
               <note>
                  <p>The descendants of an XNode do not include attribute
	 nodes<phrase role="xpath"> or namespace nodes</phrase>. However, the rules for expanding <code nobreak="false">//</code>
            ensure that <code nobreak="false">.//@*</code> selects all attributes of all descendants<phrase role="xpath">,
            and similarly <code nobreak="false">.//namespace::*</code> selects all namespaces of all descendants.</phrase>
                  </p>
               </note>
               <note>
                  <p>
                     <code nobreak="false">//</code> on its own is not a valid expression.</p>
               </note>
            </div3>
            <div3 id="id-relative-path-expressions">
               <head>Relative Path Expressions</head>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-RelativePathExpr">
                     <lhs>RelativePathExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-StepExpr">StepExpr<!--$idref_lang_part = xpath40- --></nt>  (("/"  |  "//")  <nt def="prod-xpath40-StepExpr">StepExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
                  </prod>

                  <prod id="doc-xpath40-RelativePathExpr-StepExpr">
                     <lhs>StepExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-PostfixExpr">PostfixExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-AxisStep">AxisStep<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-RelativePathExpr-PostfixExpr">
                     <lhs>PostfixExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-PrimaryExpr">PrimaryExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-FilterExpr">FilterExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-DynamicFunctionCall">DynamicFunctionCall<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-LookupExpr">LookupExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-MethodCall">MethodCall<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-FilterExprAM">FilterExprAM<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-RelativePathExpr-AxisStep">
                     <lhs>AxisStep</lhs>
                     <rhs>(<nt def="doc-xpath40-AbbreviatedStep">AbbreviatedStep<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-FullStep">FullStep<!--$idref_lang_part = xpath40- --></nt>)  <nt def="prod-xpath40-Predicate">Predicate<!--$idref_lang_part = xpath40- --></nt>*</rhs>
                  </prod>
               </scrap>
               <p>
          A <termref def="dt-relative-path-expression"/> is a path expression that selects
          GNodes within a GTree by following a series of steps starting
          at the GNodes in the context value (which may be any kind of GNode,
          not necessarily the root of the tree).
          </p>
               <p>
          Each non-initial occurrence of <code nobreak="false">//</code> in a path expression is
          expanded as described in <specref ref="id-recursive-path-operator"/>, leaving a
          sequence of steps separated by <code nobreak="false">/</code>. This sequence of steps
          is then evaluated from left to right. So a path such as
          <code nobreak="false">
                     <var>E1</var>/<var>E2</var>/<var>E3</var>/<var>E4</var>
                  </code> is evaluated
          as <code nobreak="false">((<var>E1</var>/<var>E2</var>)/<var>E3</var>)/<var>E4</var>
                  </code>. 
               The semantics of a path
          expression are thus defined by the semantics of the
          binary <code nobreak="false">/</code> operator, which is defined in
          <specref ref="id-path-operator"/>.
          </p>
               <note>
                  <p>
         Although the semantics describe the evaluation of a path with
         more than two steps as proceeding from left to right, the <code nobreak="false">/</code>
         operator is in most cases associative, so evaluation from
         right to left usually delivers the same result. The cases
         where <code nobreak="false">/</code> is not associative arise when the functions
         <code nobreak="false">fn:position()</code> and <code nobreak="false">fn:last()</code> are
         used: <code nobreak="false">A/B/position()</code> delivers a sequence of
         integers from 1 to the size of <code nobreak="false">(A/B)</code>, whereas
         <code nobreak="false">A/(B/position())</code> restarts the counting at each <code nobreak="false">B</code> element.
         </p>
               </note>
               <p>The following example illustrates the use of a relative path expressions
               to select within an XTree.
            It is assumed that the context value is a single XNode,
            referred to as the context node.</p>
               <example>
                  <ulist>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">child::div1/child::para</code>
                        </p>
                        <p>Selects the
	     <code nobreak="false">para</code> element children of the <code nobreak="false">div1</code>
	     element children of the context node; that is, the
	     <code nobreak="false">para</code> element grandchildren of the context node
	     that have <code nobreak="false">div1</code> parents.</p>
                     </item>
                  </ulist>
               </example>
               <note>
                  <p>Since each step in a path provides context GNodes for the following step, 
                  in effect, only the last step in a path is allowed to return a sequence of non-GNodes.</p>
               </note>
            </div3>
            <div3 id="id-path-operator">
               <head>Path Operator (<code nobreak="false">/</code>)</head>
               <p>The path operator <code nobreak="false">/</code> is primarily used for 
                  locating GNodes within GTrees. The value of the left-hand operand
                  may include maps and arrays; such items are implicitly converted to JNodes
                  as if by a call on the <function>fn:jtree</function> function.
                  After this conversion, the left-hand operand must return 
                  a sequence of GNodes. The result of the operator is either a sequence of GNodes
                  (in document order, with no duplicates), or a sequence of non-GNodes.</p>
               <p>The operation <code nobreak="false">
                     <var>E1</var>/<var>E2</var>
                  </code> is evaluated as follows: Expression <var>E1</var> 
                  is evaluated. Any maps or arrays in the result are converted to JNodes
                  by applying the <function>fn:jtree</function> function. If the result is not a 
                  (possibly empty) sequence <var>S</var> of GNodes, 
                  a <termref def="dt-type-error">type error</termref> is raised <errorref class="TY" code="0019"/>. Each GNode in <var>S</var> then serves in turn to provide an inner focus 
                  (the GNode as the context value, its position in <var>S</var> as the context 
                  position, the length of <code nobreak="false">S</code> as the context size) for an evaluation 
                  of <var>E2</var>, as described in  <specref ref="eval_context"/>. The sequences resulting from all the evaluations of <var>E2</var> 
                  are combined as follows:</p>
               <olist>
                  <item>
                     <p>If every evaluation of <var>E2</var> returns a (possibly empty) sequence of GNodes, 
                        these sequences are combined, and duplicate GNodes are eliminated based on GNode identity.
                        The resulting GNode sequence is returned in <termref def="dt-document-order">document order</termref>.
                     </p>
                  </item>
                  <item>
                     <p>If every evaluation of <var>E2</var> returns a (possibly empty) 
                        sequence of non-GNodes, these sequences are concatenated, in order, and returned.
                        The returned sequence preserves the orderings within and among the subsequences 
                        generated by the evaluations of <var>E2</var>.
                     </p>
                     <note>
                        <p>The use of <termref def="dt-path-expression">path expressions</termref> 
                        to select values other than GNodes is for
                     backwards compatibility. Generally it is preferable to use the simple mapping
                     operator <code nobreak="false">!</code> for this purpose. For example, write <code nobreak="false">$nodes!node-name()</code>
                     in preference to <code nobreak="false">$nodes/node-name()</code>.</p>
                     </note>
                  </item>
                  <item>
                     <p>If the multiple evaluations of <var>E2</var> return at least one GNode and at least one non-GNode, a <termref def="dt-type-error">type error</termref> is raised <errorref class="TY" code="0018"/>.</p>
                  </item>
               </olist>
               <note>
                  <p>The semantics of the path operator can also be defined using the simple 
                     map operator (<code nobreak="false">!</code>) as follows (the function
                     <code nobreak="false">fn:distinct-ordered-nodes($R)</code> has the effect of 
                     eliminating duplicates and sorting nodes into document order):</p>
                  <eg xml:space="preserve">let $R := E1 ! E2
return if (every $r in $R satisfies $r instance of gnode())
       then (fn:distinct-ordered-nodes($R))
       else if (every $r in $R satisfies not($r instance of gnode()))
       then $R
       else error()</eg>
                  <p>For a table comparing the step operator to the map operator, see <specref ref="id-map-operator"/>.</p>
               </note>
            </div3>
            <div3 id="id-recursive-path-operator">
               <head>Recursive Path Operator (<code nobreak="false">//</code>)</head>
               <p>When <code nobreak="false">//</code> is used as an infix operator, it can be treated as an abbreviation
           for <code nobreak="false">/descendant-or-self::gnode()/</code>.</p>
               <p>In simple cases, an expression such as <code nobreak="false">$x//y</code> is equivalent to
            <code nobreak="false">$x/descendant::y</code>. But in some cases the semantics are more complex, for example:</p>
               <ulist>
                  <item>
                     <p>
                        <code nobreak="false">$x//@a</code> expands to <code nobreak="false">$x/descendant-or-self::gnode()/attribute::a</code>, which selects
               all attributes having <code nobreak="false">$x</code> as an ancestor.</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">$x//y[1]</code> expands to <code nobreak="false">$x/descendant-or-self::gnode()/child::y[1]</code>,
               which selects every descendant element of <code nobreak="false">$x</code> named <code nobreak="false">y</code> that is the 
                     first child of its parent. This is <emph>not</emph> the same as <code nobreak="false">($x//y)[1]</code>, which selects
               the first descendant of <code nobreak="false">$x</code> that is named <code nobreak="false">y</code>.</p>
                  </item>
               </ulist>
               <p>The <code nobreak="false">//</code> operator can be used both with XNodes and with JNodes: the same expansion applies
            in both cases. For example, if <code nobreak="false">$x</code> is the array:</p>
               <eg xml:space="preserve">[ {"a":10, "b":11}, [ {"a":20, "b":21} ] ]</eg>
               <p>then <code nobreak="false">$x//b</code> returns two JNodes whose contents are <code nobreak="false">11</code> and <code nobreak="false">21</code>
            respectively.</p>
               <p>It is valid, but rarely useful, to use the <code nobreak="false">//</code> operator in conjunction with an axis other than
            <code nobreak="false">child</code> or <code nobreak="false">attribute</code>. For example, <code nobreak="false">$x//following-sibling::y</code>
            expands to <code nobreak="false">$x/descendant-or-self::gnode()/following-sibling::y</code>, which selects every <code nobreak="false">y</code>
               descendant of <code nobreak="false">$x</code> that is not the first child of its parent, as well as the following siblings
               of <code nobreak="false">$x</code> itself.</p>
               <p>It is also valid to follow <code nobreak="false">//</code> with an expression other than an axis step. For example,
            <code nobreak="false">distinct-values($x//node-name())</code> has the same effect as 
               <code nobreak="false">$x/descendant-or-self::gnode() =!&gt; node-name() =&gt; distinct-values()</code>
               </p>
               <p>The effect of <code nobreak="false">//</code> at the start of an expression is explained in
               <specref ref="id-absolute-path-expressions"/>.</p>
            </div3>
            <div3 id="id-axis-steps">
               <head>Axis Steps</head>
               <scrap headstyle="show">
                  <head/>
                  <prod id="doc-xpath40-AxisStep">
                     <lhs>AxisStep</lhs>
                     <rhs>(<nt def="doc-xpath40-AbbreviatedStep">AbbreviatedStep<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-FullStep">FullStep<!--$idref_lang_part = xpath40- --></nt>)  <nt def="prod-xpath40-Predicate">Predicate<!--$idref_lang_part = xpath40- --></nt>*</rhs>
                  </prod>

                  <prod id="doc-xpath40-AxisStep-AbbreviatedStep">
                     <lhs>AbbreviatedStep</lhs>
                     <rhs>".."  |  ("@"  <nt def="doc-xpath40-NodeTest">NodeTest<!--$idref_lang_part = xpath40- --></nt>)  |  <nt def="prod-xpath40-SimpleNodeTest">SimpleNodeTest<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-AxisStep-FullStep">
                     <lhs>FullStep</lhs>
                     <rhs>
                        <nt def="prod-xpath40-Axis">Axis<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="doc-xpath40-NodeTest">NodeTest<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-AxisStep-Axis">
                     <lhs>Axis</lhs>
                     <rhs>("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")  "::"</rhs>
                  </prod>

                  <prod id="doc-xpath40-AxisStep-NodeTest">
                     <lhs>NodeTest</lhs>
                     <rhs>
                        <nt def="prod-xpath40-UnionNodeTest">UnionNodeTest<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-SimpleNodeTest">SimpleNodeTest<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-AxisStep-Predicate">
                     <lhs>Predicate</lhs>
                     <rhs>"["  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>  "]"</rhs>
                  </prod>
               </scrap>
               <p>
                  <termdef term="axis step" id="dt-axis-step">An <term>axis step</term> is an instance of the production
                  <nt def="doc-xpath40-AxisStep">AxisStep<!--$spec = xpath40--></nt>: 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
		<term>axis</term>, which defines the direction of
		movement for the step, a <termref def="dt-node-test">node test</termref>,
		which selects GNodes based on their properties, and zero or more predicates which are used
               to filter the results.</termdef>
               </p>
               <note>
                  <p>An <termref def="dt-axis-step"/> is an expression in its own right.
               While axis steps are often used as the operands of 
               <termref def="dt-path-expression">path expressions</termref>,
            they can also appear in other contexts (without a <code nobreak="false">/</code> or <code nobreak="false">//</code>
            operator); equally, the operands of a path expression can be any expression,
            not restricted to an <termref def="dt-axis-step"/>.</p>
               </note>
               <p>If the context value for an <termref def="dt-axis-step"/> includes a map or array, this is implicitly
               converted to a JNode as if by applying the <function>fn:jtree</function> function.
               If, after this conversion, the sequence contains a value that is not a GNode, 
               a <termref def="dt-type-error">type error</termref> is
		         raised <errorref class="TY" code="0020"/>. The result of evaluating the axis step
               is a sequence of zero or more GNodes.</p>
               <p>The <termref def="dt-axis-step"/>
                  <code nobreak="false">S</code> is equivalent to <code nobreak="false">./S</code>.
               Thus, if the context value is a sequence containing multiple GNodes,
               the semantics of a <termref def="dt-axis-step"/> are equivalent to a <termref def="dt-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 <term>origin</term>.</p>
               <note>
                  <p>The equivalence of a <termref def="dt-axis-step"/>
                     <code nobreak="false">S</code> to the
            <termref def="dt-path-expression"/>
                     <code nobreak="false">./S</code> means that 
            the resulting GNode sequence is returned in <termref def="dt-document-order">document
	         order</termref>.</p>
               </note>
               <!--<p>An axis step may be either a <term>forward
		step</term> or a <term>reverse step</term>, followed
		by zero or more <termref def="dt-predicate">predicates</termref>.</p>-->
               <p>In the <term>abbreviated syntax</term> for a step, the axis can
		be omitted and other shorthand notations can be used as described in
		<specref ref="abbrev"/>.</p>
               <p>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 <code role="parse-test" nobreak="false">child::para</code> selects the <code nobreak="false">para</code> element children of the origin XNode: 
               <code nobreak="false">child</code> is the name of the axis, and <code nobreak="false">para</code> is the name of the element nodes 
               to be selected on this axis. The available axes are described in <specref ref="axes"/>. The
		available node tests are described in <specref ref="node-tests"/>. Examples of
		steps are provided in <specref ref="unabbrev"/> and <specref ref="abbrev"/>.</p>
               <div4 id="axes">
                  <head>Axes</head>
                  <changes>
                     <change issue="1519" PR="1532" date="2024-10-29">
                     Four new axes have been defined: <code nobreak="false">preceding-or-self</code>, <code nobreak="false">preceding-sibling-or-self</code>,
                     <code nobreak="false">following-or-self</code>, and <code nobreak="false">following-sibling-or-self</code>.
                  </change>
                  </changes>
                  <scrap headstyle="show">
                     <prod id="doc-xpath40-Axis">
                        <lhs>Axis</lhs>
                        <rhs>("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")  "::"</rhs>
                     </prod>
                  </scrap>
                  <p>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.</p>
                  <p role="xpath">XPath defines a set of <term>axes</term>
		  for traversing documents, but a <term>host language</term> may define a subset
		  of these axes. The following axes are defined:</p>
                  <ulist>
                     <item>
                        <p>The <code nobreak="false">child</code> axis
				contains the children of the origin.</p>
                        <p>If the origin is an XNode, these are the XNodes returned by the
				<xspecref spec="DM40" ref="dm-children"/> accessor.
                                </p>
                        <note>
                           <p>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 the 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.</p>
                        </note>
                        <p>If the origin is a JNode, these are the JNodes returned
                     by the <xtermref spec="DM40" ref="dt-j-children"/> accessor.</p>
                     </item>
                     <item>
                        <p>The <code nobreak="false">descendant</code>
			 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).</p>
                        <p>More formally, <code nobreak="false">$node/descendant::gnode()</code> delivers the result
                     of <code nobreak="false">fn:transitive-closure($node, fn { child::gnode() })</code>.</p>
                     </item>
                     <item>
                        <p>The <code nobreak="false">descendant-or-self</code> axis contains the origin and the descendants 
                        of the origin.</p>
                        <p>More formally, <code nobreak="false">$node/descendant-or-self::gnode()</code> delivers the result
                     of <code nobreak="false">$node/(. | descendant::gnode())</code>.</p>
                     </item>
                     <item>
                        <p>The <code nobreak="false">parent</code> axis returns the parent of the origin.</p>
                        <p>If the origin is an XNode, this is the result of the 
                        <xspecref spec="DM40" ref="dm-parent"/> accessor.</p>
                        <p>If the origin is a JNode, this is the value of the
                        <term>·jparent·</term> property of the origin.</p>
                        <p>If the GNode has no parent, the axis returns the empty sequence.</p>
                        <note>
                           <p>An attribute node may have an element node as its parent, 
                           even though the attribute node is not a child of the element node.</p>
                        </note>
                     </item>
                     <item>
                        <p>The <code nobreak="false">ancestor</code> 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).</p>
                        <p>More formally, <code nobreak="false">$node/ancestor::gnode()</code> delivers the result
                     of <code nobreak="false">fn:transitive-closure($node, fn { parent::gnode() })</code>.</p>
                        <note>
                           <p>The ancestor axis includes the root GNode of the
                           GTree in which the origin is found, unless the origin is 
                           itself the root GNode.</p>
                        </note>
                     </item>
                     <item>
                        <p>The <code nobreak="false">ancestor-or-self</code> axis contains the origin and the ancestors of the origin;
				            thus, the ancestor-or-self axis will always include the root.</p>
                        <p>More formally, <code nobreak="false">$node/ancestor-or-self::gnode()</code> delivers the result
                     of <code nobreak="false">$node/(. | ancestor::gnode())</code>.</p>
                     </item>
                     <item>
                        <p>The <code nobreak="false">following-sibling</code>
			 axis returns the origin’s following
			 siblings, that is, those children of the origin’s parent that occur after the origin in <termref def="dt-document-order">document order</termref>. If the origin
			 is an attribute or namespace node, the
			 <code nobreak="false">following-sibling</code> axis is
			 empty.</p>
                        <p>More formally, <code nobreak="false">$node/following-sibling::gnode()</code> delivers the result
                     of <code nobreak="false">fn:siblings($node)[. &gt;&gt; $node])</code>.</p>
                     </item>
                     <item>
                        <p>The <code nobreak="false">following-sibling-or-self</code> axis contains the origin,
                     together with the contents of the <code nobreak="false">following-sibling</code> axis.</p>
                        <p>More formally, <code nobreak="false">$node/following-sibling-or-self::gnode()</code> delivers the result
                     of <code nobreak="false">fn:siblings($node)[not(. &lt;&lt; $node)]</code>
                        </p>
                     </item>
                     <item>
                        <p>The <code nobreak="false">preceding-sibling</code>
			 axis returns the origin’s preceding
			 siblings, that is, those children of the origin’s parent that occur before the context
			 node in <termref def="dt-document-order">document order</termref>. If the origin
			 is an attribute or namespace node, the
			 <code nobreak="false">preceding-sibling</code> axis is
			 empty.</p>
                        <p>More formally, <code nobreak="false">$node/preceding-sibling::gnode()</code> delivers the result
                     of <code nobreak="false">fn:siblings($node)[. &lt;&lt; $node]</code>.</p>
                     </item>
                     <item>
                        <p>The <code nobreak="false">preceding-sibling-or-self</code> axis contains the origin,
                     together with the contents of the <code nobreak="false">preceding-sibling</code> axis.</p>
                        <p>More formally, <code nobreak="false">$node/preceding-sibling-or-self::gnode()</code> delivers the result
                     of <code nobreak="false">fn:siblings($node)[not(. &gt;&gt; $node)</code>.</p>
                     </item>
                     <item>
                        <p>The <code nobreak="false">following</code> 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
				<termref def="dt-document-order">document order</termref>.
                     </p>
                        <p>More formally, <code nobreak="false">$node/following::gnode()</code> delivers the result
                     of <code nobreak="false">$node/ancestor-or-self::gnode()/following-sibling::gnode()/descendant-or-self::gnode()</code>
                        </p>
                     </item>
                     <item>
                        <p>The <code nobreak="false">following-or-self</code> axis contains the origin,
                     together with the contents of the <code nobreak="false">following</code> axis.</p>
                        <p>More formally, <code nobreak="false">$node/following-or-self::gnode()</code> delivers the result
                     of <code nobreak="false">$node/(. | following::gnode())</code>.</p>
                     </item>
                     <item>
                        <p>The <code nobreak="false">preceding</code> 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
				<termref def="dt-document-order">document order</termref>.
                     </p>
                        <p>More formally, <code nobreak="false">$node/preceding::gnode()</code> delivers the result
                     of <code nobreak="false">$node/ancestor-or-self::gnode()/preceding-sibling::gnode()/descendant-or-self::gnode()</code>.</p>
                     </item>
                     <item>
                        <p>The <code nobreak="false">preceding-or-self</code> axis returns the origin,
                     together with the contents of the <code nobreak="false">preceding</code> axis.</p>
                        <p>More formally, <code nobreak="false">$node/preceding-or-self::gnode()</code> delivers the result
                     of <code nobreak="false">$node/(. | preceding::gnode())</code>.</p>
                     </item>
                     <item>
                        <p>The <code nobreak="false">attribute</code> axis is defined only for XNodes.
			 It returns the attributes of the origin,
			 which are the nodes returned by the
			 <phrase diff="chg" at="B">
                              <xspecref spec="DM40" ref="dm-attributes"/>
                           </phrase>; the axis will be
			 empty unless the context node is an
			 element.</p>
                        <p>If the <code nobreak="false">attribute</code> axis is applied to a JNode,
                     a type error <errorref class="TY" code="0004"/> is raised.</p>
                     </item>
                     <item>
                        <p>The <code nobreak="false">self</code> axis contains just the origin itself.</p>
                        <p>The <code nobreak="false">self</code> axis is primarily useful when testing whether the origin
                     satisfies particular conditions, for example <code nobreak="false">if ($x[self::chapter])</code>.</p>
                        <p>More formally, <code nobreak="false">$node/self::gnode()</code> delivers the result
                     of <code nobreak="false">$node</code>.</p>
                     </item>
                     <item role="xpath">
                        <p>The <code nobreak="false">namespace</code> axis is defined only for XNodes.
				It returns the namespace nodes of the
				origin, which are the nodes
				returned by the
                                <xspecref spec="DM40" ref="dm-namespace-nodes"/>; this axis
				is empty unless the origin is an
				element node. The
				<code nobreak="false">namespace</code> axis is
				deprecated as of XPath 2.0. If <termref def="dt-xpath-compat-mode">XPath 1.0
		compatibility mode</termref> is <code nobreak="false">true</code>, the <code nobreak="false">namespace</code> axis must be supported. If <termref def="dt-xpath-compat-mode">XPath 1.0
		compatibility mode</termref> is <code nobreak="false">false</code>, then support for the
				<code nobreak="false">namespace</code> axis is
				<termref def="dt-implementation-defined">implementation-defined</termref>. An implementation
				that does not support the
				<code nobreak="false">namespace</code> axis when <termref def="dt-xpath-compat-mode">XPath 1.0
		compatibility mode</termref> is <code nobreak="false">false</code> must raise
				a <termref def="dt-static-error">static
				error</termref>
                           <errorref class="ST" code="0010"/> if it is
				used. Applications needing information
				about the <termref def="dt-in-scope-namespaces">in-scope namespaces</termref> of an element
				should use the function <function>fn:in-scope-namespaces</function>.
                                </p>
                        <p>If the <code nobreak="false">namespace</code> axis is applied to a JNode,
                     a type error <errorref class="TY" code="0004"/> is raised.</p>
                     </item>
                  </ulist>
                  <p>Axes can be categorized as <term>forward axes</term> and
		  <term>reverse axes</term>. An axis that only ever contains the origin or
		  nodes that are after the context node in <termref def="dt-document-order">document order</termref> is a forward axis. An
		  axis that only ever contains the context node or nodes that are before the
		  context node in <termref def="dt-document-order">document order</termref> is a reverse axis.</p>
                  <p>The <code nobreak="false">parent</code>, <code nobreak="false">ancestor</code>, <code nobreak="false">ancestor-or-self</code>, 
                  <code nobreak="false">preceding</code>, <code nobreak="false">preceding-or-self</code>, 
                  <code nobreak="false">preceding-sibling</code>, and <code nobreak="false">preceding-sibling-or-self</code> axes 
                  are reverse axes; all other axes are forward axes.</p>
                  <p>The <code nobreak="false">ancestor</code>, <code nobreak="false">descendant</code>, 
                  <code nobreak="false">following</code>, <code nobreak="false">preceding</code> and <code nobreak="false">self</code> axes partition a GTree (ignoring attribute <phrase role="xpath">and namespace</phrase> nodes):
		  they do not overlap and together they contain all the GNodes in the
		  GTree.</p>
                  <p>
                     <termdef id="dt-principal-node-kind" term="principal node kind">Every axis has a <term>principal node kind</term>. 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.</termdef> Thus:</p>
                  <ulist>
                     <item>
                        <p>For the attribute axis, the principal node kind is
				attribute.</p>
                     </item>
                     <item role="xpath">
                        <p>For the namespace axis, the principal node kind is
				namespace.</p>
                     </item>
                     <item>
                        <p>For all other axes, the principal node kind is element.</p>
                     </item>
                  </ulist>
               </div4>
               <div4 id="node-tests">
                  <head>Node Tests</head>
                  <changes>
                     <change issue="296" PR="1181" date="2024-04-30">
                     If the default namespace for elements and types has the special value <code nobreak="false">##any</code>,
                     then an unprefixed name in a <code nobreak="false">NameTest</code> acts as a wildcard, matching
                     names in any namespace or none.
                  </change>
                  </changes>
                  <p>
                     <termdef id="dt-node-test" term="node test">A <term>node test</term> is a condition 
                     on the properties of a <termref def="dt-GNode"/>. 
      A node test determines which GNodes returned by an axis are selected by a <termref def="dt-step">step</termref>.</termdef>
                  </p>
                  <scrap headstyle="show">
                     <prod id="doc-xpath40-NodeTest">
                        <lhs>NodeTest</lhs>
                        <rhs>
                           <nt def="prod-xpath40-UnionNodeTest">UnionNodeTest<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-SimpleNodeTest">SimpleNodeTest<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-NodeTest-UnionNodeTest">
                        <lhs>UnionNodeTest</lhs>
                        <rhs>"("  (<nt def="prod-xpath40-SimpleNodeTest">SimpleNodeTest<!--$idref_lang_part = xpath40- --></nt> ++ "|")  ")"</rhs>
                     </prod>

                     <prod id="doc-xpath40-NodeTest-SimpleNodeTest">
                        <lhs>SimpleNodeTest</lhs>
                        <rhs>
                           <nt def="prod-xpath40-TypeTest">TypeTest<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-Selector">Selector<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-NodeTest-TypeTest">
                        <lhs>TypeTest</lhs>
                        <rhs>
                           <nt def="prod-xpath40-GNodeType">GNodeType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-XNodeType">XNodeType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-JNodeType">JNodeType<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-NodeTest-Selector">
                        <lhs>Selector</lhs>
                        <rhs>
                           <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-Wildcard">Wildcard<!--$idref_lang_part = xpath40- --></nt>  |  ("get"  "("  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>  ")")</rhs>
                     </prod>

                     <prod id="doc-xpath40-NodeTest-EQName">
                        <lhs>EQName</lhs>
                        <rhs>
                           <nt def="prod-xpath40-QName">QName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-NodeTest-Wildcard">
                        <lhs>Wildcard</lhs>
                        <rhs>"*"<br/>|  (<nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>  ":*")<br/>|  ("*:"  <nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>)<br/>|  (<nt def="prod-xpath40-BracedURILiteral">BracedURILiteral<!--$idref_lang_part = xpath40- --></nt>  "*")</rhs>
                        <com>
                           <loc href="#ws-explicit">ws: explicit</loc>
                        </com>
                     </prod>

                     <prod id="doc-xpath40-NodeTest-ExprSingle">
                        <lhs>ExprSingle</lhs>
                        <rhs>
                           <nt def="prod-xpath40-ForExpr">ForExpr<!--$idref_lang_part = xpath40- --></nt>
                           <br/>|  <nt def="prod-xpath40-LetExpr">LetExpr<!--$idref_lang_part = xpath40- --></nt>
                           <br/>|  <nt def="prod-xpath40-QuantifiedExpr">QuantifiedExpr<!--$idref_lang_part = xpath40- --></nt>
                           <br/>|  <nt def="prod-xpath40-IfExpr">IfExpr<!--$idref_lang_part = xpath40- --></nt>
                           <br/>|  <nt def="prod-xpath40-OrExpr">OrExpr<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>
                  </scrap>
                  <p>Node tests fall into three categories:</p>
                  <ulist>
                     <item>
                        <p>Type tests, which test the type of the GNode;</p>
                     </item>
                     <item>
                        <p>Selectors, which act as keys used to identify the GNode
                     among its siblings (in the case of XNodes, this is the node name);</p>
                     </item>
                     <item>
                        <p>Union node tests, which provide multiple conditions: a GNode satisfies
                  the union node test if it satisfies any of its operand node tests.</p>
                     </item>
                  </ulist>
                  <p diff="add" at="2022-12-13">A <nt def="prod-xpath40-UnionNodeTest">UnionNodeTest<!--$spec = xpath40--></nt> matches a node <var>N</var>
                  if at least one of the constituent <nt def="prod-xpath40-SimpleNodeTest">SimpleNodeTest<!--$spec = xpath40--></nt>s matches <var>N</var>.</p>
                  <p diff="add" at="2022-12-13">For example, <code nobreak="false">(div1|div2|div3)</code> matches a node named <code nobreak="false">div1</code>, <code nobreak="false">div2</code>, or <code nobreak="false">div3</code>
                  </p>
                  <p>The semantics of selectors varies between XNodes and JNodes, so the two
               cases are described separately.</p>
               </div4>
               <div4 id="id-selectors-for-xnodes">
                  <head>Selectors for XNodes</head>
                  <p>This section describes the semantics of a name test in the case
               where the origin is an XNode.</p>
                  <p>
                     <termdef id="dt-name-test" term="name test">A node test that consists only of an EQName or a
		  Wildcard is called a <term>name test</term>.</termdef>
                  </p>
                  <p>A node test written as an NCName is expanded as follows:</p>
                  <ulist>
                     <item>
                        <p>If the principal node kind of the axis step is <code nobreak="false">element</code>, 
                  using the <termref def="dt-element-name-matching-rule"/>.</p>
                        <note>
                           <p>If the <termref def="dt-default-namespace-elements-and-types"/> has the
                     special value <code nobreak="false">"##any</code>, the result of the expanding an unprefixed name
                  <var>NN</var> is the wildcard <code nobreak="false">*:<var>NN</var>
                              </code>.</p>
                        </note>
                     </item>
                     <item>
                        <p>Otherwise, using the <termref def="dt-no-namespace-rule"/>.</p>
                     </item>
                  </ulist>
                  <p>If the expanded node test is an <termref def="dt-expanded-qname"/>
                     <var>Q</var>, then it
               matches a node <var>N</var> if and only if the <term>kind</term> of
                  node <var>N</var> is the <termref def="dt-principal-node-kind">principal node kind</termref> for the step axis and the
		  <termref def="dt-expanded-qname">expanded QName</termref> of the node is equal (as defined by the <code nobreak="false">eq</code> operator) to <var>Q</var>. For
		  example, <code role="parse-test" nobreak="false">child::para</code>
		  selects the <code nobreak="false">para</code> element children of
		  the context node; if the context node has no
		  <code nobreak="false">para</code> children, it selects an empty set
		  of nodes. <code role="parse-test" nobreak="false">attribute::abc:href</code> selects
		  the attribute of the context node with the QName
		  <code nobreak="false">abc:href</code>; if the context node has no
		  such attribute, it selects an empty set of
		  nodes.</p>
                  <note>
                     <p>A name test is not satisfied by an element node whose name does not match the <termref def="dt-expanded-qname">expanded QName</termref> of the name test, even if it is in a <termref def="dt-substitution-group">substitution group</termref> whose head is the named element.</p>
                  </note>
                  <p>Wildcard node tests are interpreted as follows:</p>
                  <ulist>
                     <item>
                        <p>The node test <code nobreak="false">*</code> is true for any node of the
		  <termref def="dt-principal-node-kind">principal node
		  kind</termref> of the step axis. For example, <code role="parse-test" nobreak="false">child::*</code> will select all element
		  children of the context node, and <code role="parse-test" nobreak="false">attribute::*</code> will select all
		  attributes of the context node.</p>
                     </item>
                     <item>
                        <p>A node test can have the form
		  <code role="parse-test" nobreak="false">NCName:*</code>. In this case, the prefix is
		  expanded in the same way as with a <termref def="dt-qname">lexical QName</termref>, using the
		  <termref def="dt-static-namespaces">statically known
		  namespaces</termref> in the <termref def="dt-static-context">static context</termref>. If
		  the prefix is not found in the statically known namespaces,
		  a <termref def="dt-static-error">static
		  error</termref> is raised <errorref class="ST" code="0081"/>.
		  The node test is true for any node of the <termref def="dt-principal-node-kind">principal
		  node kind</termref> of the step axis whose <termref def="dt-expanded-qname">expanded QName</termref> has the namespace URI
		  to which the prefix is bound, regardless of the
		  local part of the name.</p>
                     </item>
                     <item>
                        <p>A node test can contain a <nt def="prod-xpath40-BracedURILiteral">BracedURILiteral<!--$spec = xpath40--></nt>, for example
		  <code role="parse-test" nobreak="false">Q{http://example.com/msg}*</code>. Such a node test is true for any node of the principal 
                  node kind of the step axis whose <termref def="dt-expanded-qname"/> has the namespace URI specified in 
                  the <nt def="prod-xpath40-BracedURILiteral">BracedURILiteral<!--$spec = xpath40--></nt>, regardless of the local part of the name.</p>
                     </item>
                     <item>
                        <p>A node test can also
		  have the form <code role="parse-test" nobreak="false">*:NCName</code>. In this case,
		  the node test is true for any node of the <termref def="dt-principal-node-kind">principal
		  node kind</termref> of the step axis whose local name matches the given NCName,
		  regardless of its namespace or lack of a namespace.</p>
                     </item>
                  </ulist>
                  <p>A selector can also take the form <code nobreak="false">get(<var>E</var>)</code>
                  where <var>E</var> is an <nt def="doc-xpath40-ExprSingle">ExprSingle<!--$spec = xpath40--></nt>.
               The contained expression <var>E</var> is evaluated with an
                  <xtermref ref="dt-absent" spec="DM40"/>
                     <termref def="dt-focus"/>. 
                  An XNode satisfies the selector if its node kind is the principal
                  node kind of the axis and its node name
                  is equal to one of the values (necessarily an <code nobreak="false">xs:QName</code>)
                  present in the atomized value of the selector expression.</p>
                  <p>That is, if the context item is an XNode, then 
                  <code nobreak="false">
                        <var>Axis</var>::get(<var>E</var>)</code> returns the result
               of the expression:</p>
                  <eg xml:space="preserve">let $selector := fn(){ data(<var>E</var>) }()
return <var>Axis</var>::*[some($selector, atomic-equal(?, node-name()))]</eg>
                  <note>
                     <p>The purpose of evaluating <var>E</var> within the body of
                  an anonymous inline function is to ensure that it is evaluated
                  with an absent focus.</p>
                     <p>It is not an error if the atomized value of <var>E</var>
               includes atomic items that are not <code nobreak="false">xs:QName</code> values:
               such values are effectively ignored.</p>
                  </note>
                  <note>
                     <p>Unnamed nodes (such as text nodes) will never be selected</p>
                  </note>
                  <note>
                     <p>The result is in document order. The order of items in
               the result of the selector expression is immaterial.</p>
                  </note>
                  <p>For example, <code nobreak="false">child::get((#body, #x:body))</code> selects
               all child elements whose name is one of the QName values <code nobreak="false">body</code>
               or <code nobreak="false">x:body</code>. Note that the evaluation of QName literals
               is not sensitive to the default namespace for elements and types.</p>
                  <p>A further example: <code nobreak="false">descendant::(get(#para) | text())</code> returns
               all descendants of the context node that are either elements named
               <code nobreak="false">para</code> (in no namespace) or text nodes; the results are in document order.</p>
               </div4>
               <div4 id="id-selectors-for-JNodes">
                  <head>Selectors for JNodes</head>
                  <p>When the origin is a JNode, the selector filters the JNodes returned
               by the axis according to the JNode's <term>·jkey·</term> property.
               In the case of a JNode that wraps an entry in a map, this can be any
               atomic item; for a JNode that wraps a member of an array, it will
               be a non-negative integer.</p>
                  <p>If the selector takes the form <code nobreak="false">*</code>, then it matches
               every JNode (including one whose <term>·jkey·</term> property
               is absent).</p>
                  <p>If the selector takes the form of an <code nobreak="false">NCName</code>, then it matches
               every JNode whose <term>·jkey·</term> property is an atomic item
                  (necessarily an <code nobreak="false">xs:string</code>, <code nobreak="false">xs:anyURI</code>
                  or <code nobreak="false">xs:untypedAtomic</code> value) that is equal to this <code nobreak="false">NCName</code>
                  under the rules of the <function>fn:atomic-equal</function> function.</p>
                  <p>If the selector takes the form of any other <code nobreak="false">EQName</code> or wildcard,
               then it matches every JNode whose <term>·jkey·</term> property is a matching 
                  <code nobreak="false">xs:QName</code>, using the same rules as for wildcards in XNode steps
               (see <specref ref="id-selectors-for-xnodes"/>).</p>
                  <p>If the selector takes the form <code nobreak="false">get(<var>E</var>)</code>,
                  where <var>E</var> is an <nt def="doc-xpath40-ExprSingle">ExprSingle<!--$spec = xpath40--></nt>,
               the contained expression <var>E</var> is evaluated with an
                  <xtermref ref="dt-absent" spec="DM40"/>
                     <termref def="dt-focus"/>. 
                  A JNode satisfies the selector if the value of its 
                  <term>·jkey·</term> property is equal to one of the values
                  present in the atomized value of the selector expression <var>E</var>, under the rules
                  of the <function>atomic-equal</function> function.</p>
                  <p>That is, if the context item is a JNode, then 
                  <code nobreak="false">
                        <var>Axis</var>::get(<var>E</var>)</code> returns the result
               of the expression:</p>
                  <eg xml:space="preserve">let $selector := fn() { data(&lt;var&gt;E&lt;/var&gt;) }()
return &lt;var&gt;Axis&lt;/var&gt;::*[some($selector, atomic-equal(?, jkey()))]
</eg>
                  <note>
                     <p>The purpose of evaluating <var>E</var> within the body of
                  an anonymous inline function is to ensure that it is evaluated
                  with an absent focus.</p>
                     <p>It is not an error if the atomized value of <var>E</var>
               includes atomic items that select nothing: such values are effectively ignored.
               This is true both for maps and arrays.</p>
                  </note>
                  <note>
                     <p>The result is in document order. The order of items in
               the result of the selector expression is immaterial.</p>
                  </note>
                  <note>
                     <p>A performant implementation might reasonably be expected,
               at least in the case where the value of the selector is a single
               atomic item, to select an entry in a map or a member in an array
               in constant time.</p>
                  </note>
                  <p>For example:</p>
                  <ulist>
                     <item>
                        <p>
                           <code nobreak="false">child::code</code> selects
               an entry in a map whose key is the string <code nobreak="false">"code"</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">child::get("date of birth")</code> selects
               an entry in a map whose key is the string <code nobreak="false">"date of birth"</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">child::get(3)</code> selects the third member
                  of an array</p>
                        <note>
                           <p>The same result can be achieved using the expression <code nobreak="false">child::*[3]</code>.</p>
                        </note>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">child::get(1 to 3)</code> selects the first three members
                  of an array, in document order.</p>
                        <note>
                           <p>
                              <code nobreak="false">child::get((3, 2, 1))</code> also returns the first three
                  members in document order.</p>
                        </note>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">child::get(current-date())</code>
               selects an entry in a map whose key is an <code nobreak="false">xs:date</code> value
               equal to the current date.</p>
                     </item>
                  </ulist>
                  <p>All the above expressions return a sequence of JNodes. If the containing
               expression expects atomic items, then the JNodes are automatically atomized.</p>
               </div4>
               <div4 id="id-type-tests">
                  <head>Type Tests</head>
                  <p>A type test is a node test that selects JNodes or XNodes based on their type.</p>
                  <scrap headstyle="show">
                     <prod id="doc-xpath40-TypeTest">
                        <lhs>TypeTest</lhs>
                        <rhs>
                           <nt def="prod-xpath40-GNodeType">GNodeType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-XNodeType">XNodeType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-JNodeType">JNodeType<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-TypeTest-GNodeType">
                        <lhs>GNodeType</lhs>
                        <rhs>"gnode"  "("  ")"</rhs>
                     </prod>

                     <prod id="doc-xpath40-TypeTest-XNodeType">
                        <lhs>XNodeType</lhs>
                        <rhs>
                           <nt def="prod-xpath40-DocumentNodeType">DocumentNodeType<!--$idref_lang_part = xpath40- --></nt>
                           <br/>|  <nt def="prod-xpath40-ElementNodeType">ElementNodeType<!--$idref_lang_part = xpath40- --></nt>
                           <br/>|  <nt def="doc-xpath40-AttributeNodeType">AttributeNodeType<!--$idref_lang_part = xpath40- --></nt>
                           <br/>|  <nt def="prod-xpath40-SchemaElementNodeType">SchemaElementNodeType<!--$idref_lang_part = xpath40- --></nt>
                           <br/>|  <nt def="prod-xpath40-SchemaAttributeNodeType">SchemaAttributeNodeType<!--$idref_lang_part = xpath40- --></nt>
                           <br/>|  <nt def="prod-xpath40-ProcessingInstructionNodeType">ProcessingInstructionNodeType<!--$idref_lang_part = xpath40- --></nt>
                           <br/>|  <nt def="prod-xpath40-CommentNodeType">CommentNodeType<!--$idref_lang_part = xpath40- --></nt>
                           <br/>|  <nt def="prod-xpath40-TextNodeType">TextNodeType<!--$idref_lang_part = xpath40- --></nt>
                           <br/>|  <nt def="prod-xpath40-NamespaceNodeType">NamespaceNodeType<!--$idref_lang_part = xpath40- --></nt>
                           <br/>|  <nt def="prod-xpath40-AnyXNodeType">AnyXNodeType<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-TypeTest-DocumentNodeType">
                        <lhs>DocumentNodeType</lhs>
                        <rhs>"document-node"  "("  (<nt def="prod-xpath40-ElementNodeType">ElementNodeType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-SchemaElementNodeType">SchemaElementNodeType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-NameTestUnion">NameTestUnion<!--$idref_lang_part = xpath40- --></nt>)?  ")"</rhs>
                     </prod>

                     <prod id="doc-xpath40-TypeTest-ElementNodeType">
                        <lhs>ElementNodeType</lhs>
                        <rhs>"element"  "("  (<nt def="prod-xpath40-NameTestUnion">NameTestUnion<!--$idref_lang_part = xpath40- --></nt>  (","  <nt def="prod-xpath40-TypeName">TypeName<!--$idref_lang_part = xpath40- --></nt>  "?"?)?)?  ")"</rhs>
                     </prod>

                     <prod id="doc-xpath40-TypeTest-SchemaElementNodeType">
                        <lhs>SchemaElementNodeType</lhs>
                        <rhs>"schema-element"  "("  <nt def="prod-xpath40-ElementName">ElementName<!--$idref_lang_part = xpath40- --></nt>  ")"</rhs>
                     </prod>

                     <prod id="doc-xpath40-TypeTest-NameTestUnion">
                        <lhs>NameTestUnion</lhs>
                        <rhs>(<nt def="prod-xpath40-NameTest">NameTest<!--$idref_lang_part = xpath40- --></nt> ++ "|")</rhs>
                     </prod>

                     <prod id="doc-xpath40-TypeTest-NameTest">
                        <lhs>NameTest</lhs>
                        <rhs>
                           <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-Wildcard">Wildcard<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-TypeTest-EQName">
                        <lhs>EQName</lhs>
                        <rhs>
                           <nt def="prod-xpath40-QName">QName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-TypeTest-Wildcard">
                        <lhs>Wildcard</lhs>
                        <rhs>"*"<br/>|  (<nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>  ":*")<br/>|  ("*:"  <nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>)<br/>|  (<nt def="prod-xpath40-BracedURILiteral">BracedURILiteral<!--$idref_lang_part = xpath40- --></nt>  "*")</rhs>
                        <com>
                           <loc href="#ws-explicit">ws: explicit</loc>
                        </com>
                     </prod>

                     <prod id="doc-xpath40-TypeTest-AttributeNodeType">
                        <lhs>AttributeNodeType</lhs>
                        <rhs>"attribute"  "("  (<nt def="prod-xpath40-NameTestUnion">NameTestUnion<!--$idref_lang_part = xpath40- --></nt>  (","  <nt def="prod-xpath40-TypeName">TypeName<!--$idref_lang_part = xpath40- --></nt>)?)?  ")"</rhs>
                     </prod>

                     <prod id="doc-xpath40-TypeTest-SchemaAttributeNodeType">
                        <lhs>SchemaAttributeNodeType</lhs>
                        <rhs>"schema-attribute"  "("  <nt def="prod-xpath40-AttributeName">AttributeName<!--$idref_lang_part = xpath40- --></nt>  ")"</rhs>
                     </prod>

                     <prod id="doc-xpath40-TypeTest-ProcessingInstructionNodeType">
                        <lhs>ProcessingInstructionNodeType</lhs>
                        <rhs>"processing-instruction"  "("  (<nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="doc-xpath40-StringLiteral">StringLiteral<!--$idref_lang_part = xpath40- --></nt>)?  ")"</rhs>
                     </prod>

                     <prod id="doc-xpath40-TypeTest-StringLiteral">
                        <lhs>StringLiteral</lhs>
                        <rhs>
                           <nt def="prod-xpath40-AposStringLiteral">AposStringLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-QuotStringLiteral">QuotStringLiteral<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                        <com>
                           <loc href="#ws-explicit">ws: explicit</loc>
                        </com>
                     </prod>

                     <prod id="doc-xpath40-TypeTest-CommentNodeType">
                        <lhs>CommentNodeType</lhs>
                        <rhs>"comment"  "("  ")"</rhs>
                     </prod>

                     <prod id="doc-xpath40-TypeTest-TextNodeType">
                        <lhs>TextNodeType</lhs>
                        <rhs>"text"  "("  ")"</rhs>
                     </prod>

                     <prod id="doc-xpath40-TypeTest-NamespaceNodeType">
                        <lhs>NamespaceNodeType</lhs>
                        <rhs>"namespace-node"  "("  ")"</rhs>
                     </prod>

                     <prod id="doc-xpath40-TypeTest-AnyXNodeType">
                        <lhs>AnyXNodeType</lhs>
                        <rhs>"node"  "("  ")"</rhs>
                     </prod>

                     <prod id="doc-xpath40-TypeTest-JNodeType">
                        <lhs>JNodeType</lhs>
                        <rhs>"jnode"  "("  (("*"  |  <nt def="prod-xpath40-JRootSelector">JRootSelector<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-Constant">Constant<!--$idref_lang_part = xpath40- --></nt>)  (","  <nt def="prod-xpath40-SequenceType">SequenceType<!--$idref_lang_part = xpath40- --></nt>)?)?  ")"</rhs>
                     </prod>
                  </scrap>
                  <!--<p>The most general form of type test uses the syntax 
           <code>type(<var>ItemType</var>)</code>. This selects GNodes
        that are instances of </p>
               
        <ulist>
           <item><p>XNodes that are instances of the supplied <var>SequenceType</var>;</p></item>
           <item><p>JNodes whose <term>·jvalue·</term> property is an instance of the 
              supplied <var>SequenceType</var>.</p></item>
        </ulist>-->
                  <p>For example:</p>
                  <ulist>
                     <item>
                        <p>
                           <code nobreak="false">element(N)</code> (short for <code nobreak="false">child::element(N)</code>) selects
               elements named <var>N</var>.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">attribute(*, xs:integer)</code>selects
               attribute nodes whose type annotation is <code nobreak="false">xs:integer</code>.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">text()</code> selects text nodes.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">jnode("id")</code> selects JNodes having the <term>·jkey·</term> property <code nobreak="false">"id"</code>.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">jnode(*, map(*))</code> selects JNodes whose <term>·jvalue·</term> property is an instance
               of the type <code nobreak="false">map(*)</code>.</p>
                     </item>
                  </ulist>
                  <!--<p>For the most commonly encountered types, this syntax can be abbreviated: for example
           <code>node()</code>, <code>text()</code>, <code>array(*)</code>, and <code>record(x, y)</code>
           can be written directly without the enclosing <code>type(...)</code>.</p>
               
        <p>If the origin is an XNode the type used will normally be a 
           <nt def="NodeKindTest">NodeKindTest</nt> such as <code>node()</code>
           or <code>comment()</code>. Specifying a type that cannot select nodes,
           such as <code>map(*)</code>, is allowed but pointless.</p>
               
        <note><p>If <var>T</var> is a <nt def="NodeKindTest">NodeKindTest</nt>, there is
        a subtle difference between the expressions <code>$N/T</code> and
        <code>$N/type(T)</code>: if no explicit axis is specified, and if <var>T</var>
        is in the form <code>attribute(N)</code> or <code>schema-attribute(N)</code>, this
        changes the default axis to be the attribute axis; and similarly for tests implicitly
        using the namespace axis. This rule does not apply when the step is
        written as <code>type(attribute(N))</code> or <code>type(schema-attribute(N))</code>.
        Such constructs make sense, for example, when selecting members of an array that
        are XNodes: the expressions <code>$array/type(element(*))</code> and <code>$array/type(attribute(*))</code>
        can be used to select the members of an array that are element nodes or attribute nodes
        respectively.</p>
        <p>Such expressions return a sequence of JNodes, whose <term>·jvalue·</term> property is 
        an XNode. Note that it is not directly possible to start with a JNode, select
        a contained XNode, and then navigate from the XNode: a path such as <code>$array/type(element(p))/@id</code>
        will not work. This is because the first step, <code>$array/type(element(p))</code>, does not select
        an element node, it selects a JNode whose <term>·jvalue·</term> property is that element node, and use of the
        attribute axis starting from a JNode has no effect.</p>
        <p>Instead, the required effect can be achieved by adding a step that explicitly 
           extracts the content of the JNode: <code>$array/type(element(p))/jvalue()/@id</code>.</p>   
        </note>       -->
                  <p>The syntax
		  and semantics of <nt def="prod-xpath40-XNodeType"><!--$spec = xpath40--></nt> and <nt def="doc-xpath40-JNodeType"><!--$spec = xpath40--></nt>
           are described in <specref ref="id-sequencetype-syntax"/> and <specref ref="id-sequencetype-matching"/>.</p>
                  <p>Shown below are further examples of type tests that might
		  be used in path expressions selecting within an XTree:</p>
                  <ulist>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">node()</code> matches any XNode.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">text()</code> matches
		  any text
		  node.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">comment()</code>
		  matches any comment
		  node.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">namespace-node()</code> matches any
		  namespace node.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">element()</code>
		  matches any element
		  node.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">schema-element(person)</code>
		  matches any element node whose name is
		  <code nobreak="false">person</code> (or is in the <termref def="dt-substitution-group">substitution group</termref>
		  headed by <code nobreak="false">person</code>), and whose type
		  annotation is the same as (or is derived from) the declared type of the <code nobreak="false">person</code>
		  element in the <termref def="dt-is-elems">in-scope element declarations</termref>.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">element(person)</code> matches any element node whose name is
		  <code nobreak="false">person</code>, regardless of its type annotation.</p>
                     </item>
                     <item diff="add" at="Issue23">
                        <p>
                           <code role="parse-test" nobreak="false">element(doctor|nurse)</code> matches any element node whose name is
                        <code nobreak="false">doctor</code> or <code nobreak="false">nurse</code>, regardless of its type annotation.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">element(person, surgeon)</code> matches any non-nilled element node whose name
		  is <code nobreak="false">person</code>, and whose type
		  annotation is
		  <code nobreak="false">surgeon</code> or is derived from <code nobreak="false">surgeon</code>.</p>
                     </item>
                     <item diff="add" at="Issue23">
                        <p>
                           <code role="parse-test" nobreak="false">element(doctor|nurse, medical-staff)</code> matches any non-nilled element node whose name
                        is <code nobreak="false">doctor</code> or <code nobreak="false">nurse</code>, and whose type
                        annotation is
                        <code nobreak="false">medical-staff</code> or is derived from <code nobreak="false">medical-staff</code>.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">element(*,
		  surgeon)</code> matches any non-nilled element node whose type
		  annotation is <code nobreak="false">surgeon</code> (or is derived from <code nobreak="false">surgeon</code>), regardless of
		  its
		  name.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">attribute()</code> matches any
                  attribute node.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">attribute(price)</code> matches
                  any attribute whose name is <code nobreak="false">price</code>,
                  regardless of its type annotation.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">attribute(*,
                  xs:decimal)</code> matches any attribute whose type
                  annotation is <code nobreak="false">xs:decimal</code> (or is derived from <code nobreak="false">xs:decimal</code>), regardless of
                  its
                  name.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">document-node()</code>
                  matches any document
                  node.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">document-node(element(book))</code>
                  matches any document node whose children consist of
                  a single element node that satisfies the <nt def="doc-xpath40-ElementNodeType"><!--$spec = xpath40--></nt>
                           <code role="parse-test" nobreak="false">element(book)</code>, interleaved with zero or more
                  comments and processing
                  instructions, and no text nodes.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">document-node(book)</code> is an abbreviation
                  for <code nobreak="false">document-node(element(book))</code>.</p>
                     </item>
                  </ulist>
                  <p>The following examples show type type tests that might
		  be used in path expressions selecting within a JTree:</p>
                  <ulist>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">jnode(*, array(*))</code> matches any JNode
                        whose <term>·jvalue·</term> is an array.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">jnode(*, record(longitude, latitude, *))</code> matches any JNode
                     whose <term>·jvalue·</term> is a map having entries with keys
                     <code nobreak="false">"longitude"</code> and <code nobreak="false">"latitude"</code>.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">jnode(*, empty-sequence())</code> matches any JNode
                     whose <term>·jvalue·</term> is the empty sequence.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">jnode(*, xs:date)</code> matches any JNode
                     whose <term>·jvalue·</term> is an instance of <code nobreak="false">xs:date</code>.</p>
                     </item>
                  </ulist>
               </div4>
               <div4 id="implausible-axis-steps" diff="add" at="Issue602">
                  <head>Implausible Axis Steps</head>
                  <changes>
                     <change issue="602" PR="603" date="2023-07-25">
                     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 <code nobreak="false">@price/@value</code>, even though dynamic evaluation
                     is defined to return the empty sequence rather than an error.
                  </change>
                  </changes>
                  <p>Certain axis steps, given an inferred type for the context value, are
               classified as <termref def="dt-implausible"/>. During the static analysis
               phase, a processor <rfc2119>may</rfc2119> (subject to the rules in
               <specref ref="id-implausible-expressions"/>) report a static error
               when such axis steps are encountered: <errorref class="TY" code="0144"/>.</p>
                  <p>More specifically, an axis step is classified as <termref def="dt-implausible"/>
               if any of the following conditions applies:</p>
                  <olist>
                     <item>
                        <p>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 <code nobreak="false">attribute()</code> 
                     and the axis is <code nobreak="false">child</code>.</p>
                     </item>
                     <item>
                        <p>The node test exclusively selects node kinds that cannot appear
                  on the specified axis: for example, the axis is <code nobreak="false">child</code>
                  and the node test is <code nobreak="false">document-node()</code>.</p>
                     </item>
                     <item>
                        <p>In a schema-aware environment, when using the <code nobreak="false">child</code>,
                     <code nobreak="false">descendant</code>, <code nobreak="false">descendant-or-self</code>, or <code nobreak="false">attribute</code>
                     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 <code nobreak="false">schema-element(list)</code> and the relevant element declaration 
                     (taking into account substitution group membership and wildcards) 
                     only allows <code nobreak="false">item</code> children,
                  the axis step <code nobreak="false">child::li</code> will never select anything and is therefore
                  classified as <termref def="dt-implausible"/>.</p>
                     </item>
                  </olist>
                  <p>Examples of implausible axis steps include the following:</p>
                  <ulist>
                     <item>
                        <p>
                           <code nobreak="false">@code/text()</code>: attributes cannot have text node children.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">/@code</code>: document nodes cannot have attributes.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">ancestor::text()</code>: the ancestor axis never returns text nodes.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">element(*)/child::map</code>: the child axis starting at an element node
                     will never select a map.</p>
                     </item>
                  </ulist>
                  <note>
                     <p>Processors may choose not to classify the expression <code nobreak="false">/..</code>
               as implausible, since XSLT 1.0 users were sometimes advised to use this construct
               as an explicit way of denoting the empty sequence.</p>
                  </note>
               </div4>
            </div3>
            <div3 id="id-predicate">
               <head>Predicates within Steps</head>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-Predicate">
                     <lhs>Predicate</lhs>
                     <rhs>"["  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>  "]"</rhs>
                  </prod>

                  <prod id="doc-xpath40-Predicate-Expr">
                     <lhs>Expr</lhs>
                     <rhs>(<nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt> ++ ",")</rhs>
                  </prod>
               </scrap>
               <p id="dt-predicate">A predicate within an <nt def="doc-xpath40-AxisStep">AxisStep<!--$spec = xpath40--></nt> has similar syntax and semantics
	 to a predicate within a <termref def="dt-filter-expression"/>.  The
	 only difference is in the way the context position is set for
	 evaluation of the predicate.</p>
               <note>
                  <p>The operator <code nobreak="false">[]</code> binds more tightly than <code nobreak="false">/</code>.
            This means that the expression <code nobreak="false">a/b[1]</code> is interpreted as <code nobreak="false">child::a/(child::b[1])</code>:
                  it selects the first <code nobreak="false">b</code>
            child of every <code nobreak="false">a</code> element, in contrast to <code nobreak="false">(a/b)[1]</code> which
            selects the first <code nobreak="false">b</code> element that is a child of some <code nobreak="false">a</code>
            element.</p>
                  <p>A common mistake is to write <code nobreak="false">//a[1]</code> where <code nobreak="false">(//a)[1]</code>
               is intended. The first expression, <code nobreak="false">//a[1]</code>, selects every descendant 
                  <code nobreak="false">a</code> element that is the first child of its parent (it expands
                  to <code nobreak="false">/descendant-or-self::node()/child::a[1]</code>), whereas 
               <code nobreak="false">(//a)[1]</code> selects the <code nobreak="false">a</code> element in the document.
               </p>
               </note>
               <p>For the purpose of evaluating the context position within
	 a predicate, the input sequence is considered to be sorted as
	 follows: into document order if the predicate is in a
	 forward-axis step, into reverse document order if the
	 predicate is in a reverse-axis step, or in its original order
	 if the predicate is not in a step.</p>
               <p>More formally:</p>
               <ulist>
                  <item>
                     <p>For a step using a forwards axis, such as <code nobreak="false">child::<var>test</var>[<var>P</var>]</code>,
               the result is the same as for the equivalent <termref def="dt-filter-expression"/>
                        <code nobreak="false">(child::<var>test</var>)[<var>P</var>]</code> (note the parentheses). The same applies if there
               are multiple predicates, for example <code nobreak="false">child::<var>test</var>[<var>P1</var>][<var>P2</var>][<var>P3</var>]</code>
               is equivalent to <code nobreak="false">(child::<var>test</var>)[<var>P1</var>][<var>P2</var>][<var>P3</var>]</code>.</p>
                  </item>
                  <item>
                     <p>For a step using a reverse axis, such as <code nobreak="false">ancestor::<var>test</var>[<var>P</var>]</code>,
               the result is the same as the expression  
               <code nobreak="false">reverse(ancestor::<var>test</var>)[<var>P</var>] =&gt; reverse()</code>. The same applies if there
               are multiple predicates, for example <code nobreak="false">ancestor::<var>test</var>[<var>P1</var>][<var>P2</var>][<var>P3</var>]</code>
               is equivalent to <code nobreak="false">reverse(ancestor::<var>test</var>)[<var>P1</var>][<var>P2</var>][<var>P3</var>] =&gt; reverse()</code>.</p>
                  </item>
               </ulist>
               <note>
                  <p>The result of the expression <code nobreak="false">preceding-sibling::*</code> is in document order, but
               <code nobreak="false">preceding-sibling::*[1]</code> selects the last preceding sibling element,
               that is, the one that immediately precedes the context node.</p>
                  <p>Similarly, the expression <code nobreak="false">preceding-sibling::x[1, 2, 3]</code> selects the last three
               preceding siblings, returning them in document order. For example, given the input:</p>
                  <eg xml:space="preserve">&lt;doc&gt;&lt;a/&gt;&lt;b/&gt;&lt;c/&gt;&lt;d/&gt;&lt;e/&gt;&lt;f/&gt;&lt;/doc&gt;</eg>
                  <p>The result of <code nobreak="false">//e ! preceding-sibling::*[1, 2, 3]</code> is <code nobreak="false">&lt;b/&gt;, &lt;c/&gt;, &lt;d/&gt;</code>.
               The expression <code nobreak="false">//e ! preceding-sibling::*[3, 2, 1]</code> delivers exactly the same result.</p>
               </note>
               <p>Here are some examples of <termref def="dt-axis-step">axis steps</termref> that contain predicates to select XNodes:</p>
               <ulist>
                  <item>
                     <p>This example selects the second <code nobreak="false">chapter</code> element that is a child
			 of the context node:</p>
                     <eg role="parse-test" xml:space="preserve">child::chapter[2]</eg>
                  </item>
                  <item>
                     <p>This example selects all the descendants of the
		  context node that are elements named
		  <code nobreak="false">"toy"</code> and whose <code nobreak="false">color</code>
		  attribute has the value <code nobreak="false">"red"</code>:</p>
                     <eg role="parse-test" xml:space="preserve">descendant::toy[attribute::color = "red"]</eg>
                  </item>
                  <item>
                     <p>This example selects all the <code nobreak="false">employee</code> children of the context node
		that have both a <code nobreak="false">secretary</code> child element and an <code nobreak="false">assistant</code> child element:</p>
                     <eg role="parse-test" xml:space="preserve">child::employee[secretary][assistant]</eg>
                  </item>
                  <item>
                     <p>This example selects the innermost <code nobreak="false">div</code> ancestor of the context node:</p>
                     <eg role="parse-test" xml:space="preserve">ancestor::div[1]</eg>
                  </item>
                  <item>
                     <p>This example selects the outermost <code nobreak="false">div</code> ancestor of the context node:</p>
                     <eg role="parse-test" xml:space="preserve">ancestor::div[last()]</eg>
                  </item>
                  <item>
                     <p>This example selects the names of all the ancestor elements of the context node that have an
                     <code nobreak="false">@id</code> attribute, outermost element first:</p>
                     <eg role="parse-test" xml:space="preserve">ancestor::*[@id]</eg>
                  </item>
               </ulist>
               <note>
                  <p>The expression <code role="parse-test" nobreak="false">ancestor::div[1]</code> parses as an <nt def="doc-xpath40-AxisStep">AxisStep<!--$spec = xpath40--></nt>
                  with a reverse axis, and the position <code nobreak="false">1</code> therefore
                  refers to the first ancestor <code nobreak="false">div</code> in reverse document order,
                  that is, the innermost <code nobreak="false">div</code>. By
contrast, <code role="parse-test" nobreak="false">(ancestor::div)[1]</code> parses as a <nt def="doc-xpath40-FilterExpr">FilterExpr<!--$spec = xpath40--></nt>,
                  and therefore returns the first qualifying <code nobreak="false">div</code>
element in the order of the <code nobreak="false">ancestor::div</code> expression, which is
                  in <termref def="dt-document-order"/>.</p>
                  <p>The fact that a reverse-axis step assigns context positions in reverse
document order for the purpose of evaluating predicates does not alter the
fact that the final result of the step is always in document order.</p>
                  <p diff="add" at="2022-01-17">The expression <code nobreak="false">ancestor::(div1|div2)[1]</code> 
               does not have the same meaning as <code nobreak="false">(ancestor::div1|ancestor::div2)[1]</code>. 
                  In the first expression,
               the predicate <code nobreak="false">[1]</code> is within a step that uses a reverse axis, so nodes are counted
               in reverse document order. In the second expression, the predicate applies to the result of
               a union expression, so nodes are counted in document order.</p>
               </note>
               <p>When the context value for evaluation of a step includes multiple GNodes, the step is evaluated
            separately for each of those GNodes, and the results are combined, eliminating duplicates
            and sorting into document order.</p>
               <note>
                  <p>To avoid reordering and elimination of duplicates, replace the step <code nobreak="false">S</code> by <code nobreak="false">.!S</code>.</p>
               </note>
            </div3>
            <div3 id="unabbrev">
               <head>Unabbreviated Syntax</head>
               <p>This section provides a number of examples of path expressions in which the
axis is explicitly specified in each <termref def="dt-step">step</termref>. The syntax used in these examples is
called the <term>unabbreviated syntax</term>. In many common cases, it is
possible to write path expressions more concisely using an <term>abbreviated
syntax</term>, as explained in <specref ref="abbrev"/>.</p>
               <p>These examples assume that the context value is a single node, referred to as the context node.</p>
               <ulist>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">child::para</code> selects
the <code nobreak="false">para</code> element children of the context node.</p>
                  </item>
                  <item diff="add" at="2022-12-13">
                     <p>
                        <code role="parse-test" nobreak="false">child::(para|bullet)</code> selects
                     the <code nobreak="false">para</code> and <code nobreak="false">bullet</code> element children of the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">child::*</code> selects all element children of the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">child::text()</code> selects all text node children of the context node.</p>
                  </item>
                  <item diff="add" at="2022-12-13">
                     <p>
                        <code role="parse-test" nobreak="false">child::(text()|comment())</code> selects all text node and comment node children of the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">child::node()</code> selects all the children of the context node. Note that no attribute nodes are returned, because attributes are not children.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">attribute::name</code> selects the <code nobreak="false">name</code> attribute of the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">attribute::*</code> selects all the attributes of the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">parent::node()</code> 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.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">descendant::para</code> selects the <code nobreak="false">para</code> element descendants of the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">ancestor::div</code> selects all <code nobreak="false">div</code> ancestors of the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">ancestor-or-self::div</code> selects the <code nobreak="false">div</code> ancestors of the context node and, if the context node is a <code nobreak="false">div</code> element, the context node as well.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">descendant-or-self::para</code> selects the <code nobreak="false">para</code> element descendants of the context node and, if the context node is a <code nobreak="false">para</code> element, the context node as well.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">self::para</code> selects the context node if it is a <code nobreak="false">para</code> element, and otherwise returns the empty sequence.</p>
                  </item>
                  <item diff="add" at="2022-12-13">
                     <p>
                        <code role="parse-test" nobreak="false">self::(chapter|appendix)</code> selects the context node if it is a
                     <code nobreak="false">chapter</code> or <code nobreak="false">appendix</code> element, and otherwise returns the empty sequence.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">child::chapter/descendant::para</code> selects the <code nobreak="false">para</code> element
descendants of the <code nobreak="false">chapter</code> element children of the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">child::*/child::para</code> selects all <code nobreak="false">para</code> grandchildren of the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">/</code> selects the root of the tree that contains the context node, but raises a dynamic error if this root is not a document node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">/descendant::para</code> selects all the <code nobreak="false">para</code> elements in the same document as the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">/descendant::list/child::member</code> selects all
the <code nobreak="false">member</code> elements that have a <code nobreak="false">list</code> parent and that are in the same document as the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">child::para[position() = 1]</code> selects the first <code nobreak="false">para</code> child of the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">child::para[position() = last()]</code> selects the last <code nobreak="false">para</code> child of the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">child::para[position() = last()-1]</code> selects the last but one <code nobreak="false">para</code> child of the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">child::para[position() &gt; 1]</code> selects all the <code nobreak="false">para</code> children of the context node other than the first <code nobreak="false">para</code> child of the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">following-sibling::chapter[position() = 1]</code> selects the next <code nobreak="false">chapter</code> sibling of the context node.</p>
                  </item>
                  <item diff="add" at="2022-12-13">
                     <p>
                        <code role="parse-test" nobreak="false">following-sibling::(chapter|appendix)[position() = 1]</code> selects the next sibling of the context node
                        that is either a <code nobreak="false">chapter</code> or an <code nobreak="false">appendix</code>.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">preceding-sibling::chapter[position() = 1]</code> selects the previous <code nobreak="false">chapter</code> sibling of the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">/descendant::figure[position() = 42]</code> selects the forty-second <code nobreak="false">figure</code> element in the document containing the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">/child::book/child::chapter[position() = 5]/child::section[position() = 2]</code> selects the
second <code nobreak="false">section</code> of the fifth <code nobreak="false">chapter</code> of the <code nobreak="false">book</code> whose parent is the document node that contains the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">child::para[attribute::type eq "warning"]</code> selects
all <code nobreak="false">para</code> children of the context node that have a <code nobreak="false">type</code> attribute with value <code nobreak="false">warning</code>.
                  </p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">child::para[attribute::type eq 'warning'][position() = 5]</code> selects the fifth <code nobreak="false">para</code> child of the context node that has a <code nobreak="false">type</code> attribute with value <code nobreak="false">warning</code>.
                  </p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">child::para[position() = 5][attribute::type eq "warning"]</code> selects the fifth <code nobreak="false">para</code> child of the context node if that child has a <code nobreak="false">type</code> attribute with value <code nobreak="false">warning</code>.
                  </p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">child::chapter[child::title = 'Introduction']</code> selects
the <code nobreak="false">chapter</code> children of the context node that have one or
more <code nobreak="false">title</code> children whose <termref def="dt-typed-value">typed value</termref> is equal to the
string <code nobreak="false">Introduction</code>.
                  </p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">child::chapter[child::title]</code> selects the <code nobreak="false">chapter</code> children of the context node that have one or more <code nobreak="false">title</code> children.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">child::*[self::chapter or self::appendix]</code>
selects the <code nobreak="false">chapter</code> and <code nobreak="false">appendix</code> children of the context node.</p>
                  </item>
                  <item diff="chg" at="2022-12-13">
                     <p>
                        <code role="parse-test" nobreak="false">child::*[self::(chapter|appendix)][position() = last()]</code> selects the
last <code nobreak="false">chapter</code> or <code nobreak="false">appendix</code> child of the context node.</p>
                  </item>
               </ulist>
            </div3>
            <div3 id="abbrev">
               <head>Abbreviated Syntax</head>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-AbbreviatedStep">
                     <lhs>AbbreviatedStep</lhs>
                     <rhs>".."  |  ("@"  <nt def="doc-xpath40-NodeTest">NodeTest<!--$idref_lang_part = xpath40- --></nt>)  |  <nt def="prod-xpath40-SimpleNodeTest">SimpleNodeTest<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-AbbreviatedStep-NodeTest">
                     <lhs>NodeTest</lhs>
                     <rhs>
                        <nt def="prod-xpath40-UnionNodeTest">UnionNodeTest<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-SimpleNodeTest">SimpleNodeTest<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-AbbreviatedStep-SimpleNodeTest">
                     <lhs>SimpleNodeTest</lhs>
                     <rhs>
                        <nt def="prod-xpath40-TypeTest">TypeTest<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-Selector">Selector<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-AbbreviatedStep-TypeTest">
                     <lhs>TypeTest</lhs>
                     <rhs>
                        <nt def="prod-xpath40-GNodeType">GNodeType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-XNodeType">XNodeType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-JNodeType">JNodeType<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-AbbreviatedStep-Selector">
                     <lhs>Selector</lhs>
                     <rhs>
                        <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-Wildcard">Wildcard<!--$idref_lang_part = xpath40- --></nt>  |  ("get"  "("  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>  ")")</rhs>
                  </prod>

                  <prod id="doc-xpath40-AbbreviatedStep-EQName">
                     <lhs>EQName</lhs>
                     <rhs>
                        <nt def="prod-xpath40-QName">QName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-AbbreviatedStep-Wildcard">
                     <lhs>Wildcard</lhs>
                     <rhs>"*"<br/>|  (<nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>  ":*")<br/>|  ("*:"  <nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>)<br/>|  (<nt def="prod-xpath40-BracedURILiteral">BracedURILiteral<!--$idref_lang_part = xpath40- --></nt>  "*")</rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="doc-xpath40-AbbreviatedStep-ExprSingle">
                     <lhs>ExprSingle</lhs>
                     <rhs>
                        <nt def="prod-xpath40-ForExpr">ForExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-LetExpr">LetExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-QuantifiedExpr">QuantifiedExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-IfExpr">IfExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-OrExpr">OrExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>
               </scrap>
               <p>The abbreviated syntax for a step permits the following abbreviations:</p>
               <olist>
                  <item>
                     <p>The attribute axis <code nobreak="false">attribute::</code> can be
    abbreviated by <code nobreak="false">@</code>. For example, the expression <code role="parse-test" nobreak="false">para[@type = "warning"]</code> is short
    for <code role="parse-test" nobreak="false">child::para[attribute::type = "warning"]</code> and
    so selects <code nobreak="false">para</code> children with a <code nobreak="false">type</code> attribute with value
    equal to <code nobreak="false">warning</code>.</p>
                  </item>
                  <item>
                     <p>If the axis name is omitted from an <termref def="dt-axis-step">axis step</termref>, the default axis is
    <code nobreak="false">child</code>, with two exceptions:

    (1) if the <nt def="doc-xpath40-NodeTest">NodeTest<!--$spec = xpath40--></nt> in an axis step contains an 
                     <nt def="doc-xpath40-AttributeNodeType"><!--$spec = xpath40--></nt> or <nt def="doc-xpath40-SchemaAttributeNodeType"><!--$spec = xpath40--></nt> then the
    default axis is <code nobreak="false">attribute</code>;     
    (2) if the <nt def="doc-xpath40-NodeTest">NodeTest<!--$spec = xpath40--></nt> in an axis step is a <nt def="prod-xpath40-NamespaceNodeType"><!--$spec = xpath40--></nt>
                        <phrase role="xpath">then the default axis is <code nobreak="false">namespace</code>, but in an implementation that does not support
    the namespace axis, an error is raised <errorref class="ST" code="0134"/>.</phrase>
                        <note>
                           <p> The namespace
    axis is deprecated as of XPath 2.0, but is required in some languages
    that use XPath, including XSLT.</p>
                        </note>

    For example, the path expression <code role="parse-test" nobreak="false">section/para</code> is an abbreviation for <code role="parse-test" nobreak="false">child::section/child::para</code>, and the path
    expression <code role="parse-test" nobreak="false">section/@id</code> is an
    abbreviation for <code role="parse-test" nobreak="false">child::section/attribute::id</code>.  Similarly,
    <code role="parse-test" nobreak="false">section/attribute(id)</code> is an
    abbreviation for <code role="parse-test" nobreak="false">child::section/attribute::attribute(id)</code>. Note
    that the latter expression contains both an axis specification and
    a <termref def="dt-node-test">node test</termref>.</p>
                     <p>Similarly, within a JTree rooted at an array, the expression <code nobreak="false">get(1)/parts/get(2)/part-no</code>
                  gets the first member of the top-level array (presumably a map), then the <code nobreak="false">"parts"</code>
                  entry within this map (presumably an array), then the second member of this array (presumably
                  a map), and finally the <code nobreak="false">part-no</code> entry within this map.</p>
                     <note>
                        <p>The same selection could be made using the lookup expression <code nobreak="false">?1?parts?2?part-no</code>.
                  The main difference is that path expressions offer more flexibility in being able to navigate around
                  the containing JTree. Also, the lookup expression <code nobreak="false">$a?1</code> fails if the
                  array index is out of bounds; the path expression <code nobreak="false">$a/get(1)</code> 
                  (or <code nobreak="false">$a/*[1]</code>) instead returns the empty sequence.</p>
                     </note>
                     <note diff="add" at="2022-12-13">
                        <p>An abbreviated axis step that omits the axis name must use a
                  <nt def="prod-xpath40-SimpleNodeTest">SimpleNodeTest<!--$spec = xpath40--></nt> rather than a <nt def="prod-xpath40-UnionNodeTest">UnionNodeTest<!--$spec = xpath40--></nt>.
                  This means that a construct such as <code nobreak="false">(ul|ol)</code>
                  is treated as an abbreviation for <code nobreak="false">(child::ul|child::ol)</code> rather than <code nobreak="false">child::(ul|ol)</code>.
                  Since the two constructs have exactly the same semantics, this is not actually a restriction.</p>
                     </note>
                  </item>
                  <item>
                     <p>A step consisting
of <code role="parse-test" nobreak="false">..</code> is short
for <code role="parse-test" nobreak="false">parent::gnode()</code>. For example (assuming the context
                     item is an XNode), <code role="parse-test" nobreak="false">../title</code> is short for <code role="parse-test" nobreak="false">parent::gnode()/child::title</code> and so will select the 
                     <code nobreak="false">title</code> children of the parent of the context node.</p>
                     <p>Similarly, if <code nobreak="false">$dateOfBirth</code> is a JNode resulting from the expression
                  <code nobreak="false">$map/get("date of birth")</code>, then <code nobreak="false">$dateOfBirth/../gender</code>
                  will select the entry having key <code nobreak="false">"gender"</code> within <code nobreak="false">$map</code>.</p>
                     <note>
                        <p>The expression <code nobreak="false">.</code>, known as a <term>context value
   reference</term>, is a <termref def="dt-primary-expression">primary expression</termref>,
   and is described in <specref ref="id-context-value-references"/>.</p>
                     </note>
                  </item>
               </olist>
               <p>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:</p>
               <ulist>
                  <item>
                     <p>
                        <code nobreak="false">para</code> selects the <code nobreak="false">para</code> element children of the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">*</code> selects all element children of the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">text()</code> selects all text node children of the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">@name</code> selects
the <code nobreak="false">name</code> attribute of the context node.</p>
                  </item>
                  <item diff="add" at="2022-12-13">
                     <p>
                        <code role="parse-test" nobreak="false">@(id|name)</code> selects
                     the <code nobreak="false">id</code> and <code nobreak="false">name</code> attributes of the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">@*</code> selects all the attributes of the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">para[1]</code> selects the first <code nobreak="false">para</code> child of the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">para[last()]</code> selects the last <code nobreak="false">para</code> child of the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">*/para</code> selects
all <code nobreak="false">para</code> grandchildren of the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">/book/chapter[5]/section[2]</code> selects the
second <code nobreak="false">section</code> of the fifth <code nobreak="false">chapter</code> of the <code nobreak="false">book</code> whose parent is the document node that contains the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">chapter//para</code> selects the <code nobreak="false">para</code> element descendants of the <code nobreak="false">chapter</code> element children of the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">//para</code> selects all
the <code nobreak="false">para</code> descendants of the root document node and thus selects all <code nobreak="false">para</code> elements in the same document as the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">//@version</code> selects all the <code nobreak="false">version</code> attribute nodes that are in the same document as the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">//list/member</code> selects all the <code nobreak="false">member</code> elements in the same document as the context node that have a <code nobreak="false">list</code> parent.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">.//para</code> selects
the <code nobreak="false">para</code> element descendants of the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">..</code> selects the parent of the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">../@lang</code> selects
the <code nobreak="false">lang</code> attribute of the parent of the context node.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">para[@type = "warning"]</code> selects all <code nobreak="false">para</code> children of the context node that have a <code nobreak="false">type</code> attribute with value <code nobreak="false">warning</code>.
                  </p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">para[@type = "warning"][5]</code> selects the fifth <code nobreak="false">para</code> child of the context node that has a <code nobreak="false">type</code> attribute with value <code nobreak="false">warning</code>.
                  </p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">para[5][@type = "warning"]</code> selects the fifth <code nobreak="false">para</code> child of the context node if that child has a <code nobreak="false">type</code> attribute with value <code nobreak="false">warning</code>.
                  </p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">chapter[title = "Introduction"]</code> selects the <code nobreak="false">chapter</code> children of the context node that have one
or more <code nobreak="false">title</code> children whose <termref def="dt-typed-value">typed value</termref> is equal to the string <code nobreak="false">Introduction</code>.
                  </p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">chapter[title]</code> selects the <code nobreak="false">chapter</code> children of the context node that have one or more <code nobreak="false">title</code> children.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">employee[@secretary and @assistant]</code> selects all
the <code nobreak="false">employee</code> children of the context node that have both a <code nobreak="false">secretary</code> attribute and
an <code nobreak="false">assistant</code> attribute.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">book/(chapter|appendix)/section</code> selects
every <code nobreak="false">section</code> element that has a parent that is either a <code nobreak="false">chapter</code> or an <code nobreak="false">appendix</code> element, that in turn is a child of a <code nobreak="false">book</code> element that is a child of the context node.</p>
                  </item>
                  <item>
                     <p>If <code nobreak="false">E</code> is any expression that returns a sequence of nodes, then the expression <code role="parse-test" nobreak="false">E/.</code> returns the same nodes in <termref def="dt-document-order">document order</termref>, with duplicates eliminated based on node identity.</p>
                  </item>
               </ulist>
               <p>The following examples use abbreviated paths to access data within the JTree
               obtained by parsing the JSON text:</p>
               <eg xml:space="preserve">[
  { "first": "John", 
    "last": "Baker", 
    "date of birth": "2003-04-19", 
    "occupation": "cook"}, 
  { "first": "Mary", 
    "last": "Smith", 
    "date of birth": "2006-08-12", 
    "occupation": "teacher"},                 
]</eg>
               <ulist>
                  <item>
                     <p>
                        <code nobreak="false">get(1)/first</code> returns a JNode whose <term>·jvalue·</term>
               is the string <code nobreak="false">"John"</code>.</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">//first[. = "Mary"]/../last</code> returns a JNode whose <term>·jvalue·</term>
               is the string <code nobreak="false">"Smith"</code>.</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">//first[. = "Mary"]/../get("date of birth")</code> returns a JNode whose <term>·jvalue·</term>
               is the string <code nobreak="false">"2006-08-12"</code>.</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">//*[occupation = "cook"]!`{first} {last}`</code> returns the
               string <code nobreak="false">"John Baker"</code>.</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">//*[occupation = "cook"]/following-sibling::*[1]!`{first} {last}`</code> returns the
               string <code nobreak="false">"Mary Smith"</code>.</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">//*[last = "Smith"]/../get(1)/last</code> returns the
               string <code nobreak="false">"Baker"</code>.</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">//record(first, last, *) ! string(last)</code> returns the sequence of two
               strings <code nobreak="false">"Baker"</code>, <code nobreak="false">"Smith"</code>.</p>
                  </item>
               </ulist>
            </div3>
            <div3 id="comparison-with-JSONPath">
               <head>Comparison with JSONPath</head>
               <p>Path expressions applied to a JTree offer similar capability to
            JSONPath, which is an XPath-like language design for querying JSON.</p>
               <example>
                  <head>Comparison with JSONPath</head>
                  <p>This example provides XPath equivalents to some examples given in the
                  JSONPath specification. [TODO: add a reference].</p>
                  <p>The examples query the result of parsing the following JSON value, representing
                     a store whose stock consists of four books and a bicycle:</p>
                  <eg xml:space="preserve">{
  "store": {
    "book": [
      {
        "category": "reference",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": 8.95
      },
      {
        "category": "fiction",
        "author": "Evelyn Waugh",
        "title": "Sword of Honour",
        "price": 12.99
      },
      {
        "category": "fiction",
        "author": "Herman Melville",
        "title": "Moby Dick",
        "isbn": "0-553-21311-3",
        "price": 8.99
      },
      {
        "category": "fiction",
        "author": "J. R. R. Tolkien",
        "title": "The Lord of the Rings",
        "isbn": "0-395-19395-8",
        "price": 22.99
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 399
    }
  }
}</eg>
                  <p>The following table illustrates some queries on this data, expressed
                  both in JSONPath and in XPath 4.0.</p>
                  <table role="small" width="100%">
                     <caption>JSONPath vs XPath 4.0 Comparison</caption>
                     <col width="40%" span="1"/>
                     <col width="30%" span="1"/>
                     <col width="30%" span="1"/>
                     <thead>
                        <tr>
                           <th rowspan="1" colspan="1">Query</th>
                           <th rowspan="1" colspan="1">JSONPath</th>
                           <th rowspan="1" colspan="1">XPath 4.0</th>
                        </tr>
                     </thead>
                     <tbody>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">The authors of all books in the store</td>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">$.store.book[*].author</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">/store/book//author</code>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">All authors</td>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">$..author</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">//author</code>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">All things in store (four books and a red bicycle)</td>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">$.store.*</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">/store/*</code>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">The prices of everything in the store</td>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">$.store..price</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">/store//price</code>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">The third book</td>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">$..book[2]  </code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">//book/*[3]</code>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">The third book's author</td>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">$..book[2].author</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">//book/*[3]/author</code>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">The third book's publisher (empty result)</td>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">$..book[2].publisher</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">//book/*[3]/publisher</code>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">The last book (in order)</td>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">$..book[-1]</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">//book/*[last()]</code>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">The first two books</td>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">$..book[0,1]</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">//book/*[1,2]</code>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">All books with an ISBN</td>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">$..book[?@.isbn]</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">//book[isbn]</code>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">All books cheaper than 10</td>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">$..book[?@.price&lt;10]</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">//book[price lt 10]</code>
                           </td>
                        </tr>
                        <tr>
                           <td valign="top" rowspan="1" colspan="1">All member values and array elements contained in the input value</td>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">$..*</code>
                           </td>
                           <td valign="top" rowspan="1" colspan="1">
                              <code nobreak="false">//*</code>
                           </td>
                        </tr>
                     </tbody>
                  </table>
               </example>
            </div3>
         </div2>
         <div2 id="id-sequence-expressions">
            <head>Sequence Expressions</head>
            <p>XPath 4.0 supports operators to construct, filter,  and combine
<termref def="dt-sequence">sequences</termref> of <termref def="dt-item">items</termref>.
Sequences are never nested—for
example, combining the values <code nobreak="false">1</code>, <code nobreak="false">(2, 3)</code>, and <code nobreak="false">( )</code> into a single sequence results
in the sequence <code nobreak="false">(1, 2, 3)</code>.</p>
            <div3 id="construct_seq">
               <head>Sequence Concatenation</head>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-Expr">
                     <lhs>Expr</lhs>
                     <rhs>(<nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt> ++ ",")</rhs>
                  </prod>

                  <prod id="doc-xpath40-Expr-ExprSingle">
                     <lhs>ExprSingle</lhs>
                     <rhs>
                        <nt def="prod-xpath40-ForExpr">ForExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-LetExpr">LetExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-QuantifiedExpr">QuantifiedExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-IfExpr">IfExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-OrExpr">OrExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>
               </scrap>
               <p>
                  <termdef id="dt-sequence-expression" term="sequence expression">A
            <term>sequence expression</term> is a <termref def="dt-non-trivial"/> instance
            of the production rule <nt def="doc-xpath40-Expr">Expr<!--$spec = xpath40--></nt>, that is, an expression
            containing two or more instances of the production <nt def="doc-xpath40-ExprSingle">ExprSingle<!--$spec = xpath40--></nt>
            separated by the comma operator.</termdef>
               </p>
               <p>The result of a <termref def="dt-sequence-expression"/> is the
            <termref def="dt-sequence-concatenation"/> of the values of its operands.
            See <nt def="doc-xpath40-Expr"><!--$spec = xpath40--></nt>
               </p>
               <p>
                  <termdef term="comma operator" id="dt-comma-operator">A <term>comma operator</term> is a comma used specifically
                  as the operator in a <termref def="dt-sequence-expression"/>.</termdef>
               </p>
               <p>Empty parentheses can be used to denote the empty sequence.</p>
               <p>A sequence may contain duplicate
<termref def="dt-item">items</termref>, 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.</p>
               <p>
                  <termdef id="dt-sequence-concatenation" term="sequence concatenation">The 
               <term>sequence concatenation</term> of a number of sequences <var>S/1</var>, <var>S/2</var>, ... <var>S/n</var>
               is defined to be the sequence formed from the items of <var>S/1</var>, followed by the items
               from <var>S/2</var>, and so on, retaining order.</termdef> The 
               <termref def="dt-comma-operator"/> returns the sequence
            concatenation of its two operands; repeated application (for example <code nobreak="false">$s1, $s2, $s3, $s4</code>)
            delivers the sequence concatenation of multiple sequences.</p>
               <note>
                  <p>In places where the grammar calls for <nt def="doc-xpath40-ExprSingle">ExprSingle<!--$spec = xpath40--></nt>, such as the arguments of a function call, any expression that contains a top-level comma operator must be enclosed in parentheses.</p>
               </note>
               <p>Here are some examples of expressions that construct sequences:
</p>
               <ulist>
                  <item>
                     <p>The result of this expression is a sequence of five integers:</p>
                     <eg role="parse-test" xml:space="preserve">(10, 1, 2, 3, 4)</eg>
                  </item>
                  <item>
                     <p>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 <code nobreak="false">10, 1, 2, 3, 4</code>.</p>
                     <eg role="parse-test" xml:space="preserve">(10, (1, 2), (), (3, 4))</eg>
                  </item>
                  <item>
                     <p>The result of this expression is a sequence containing
all <code nobreak="false">salary</code> children of the context node followed by all <code nobreak="false">bonus</code> children.</p>
                     <eg role="parse-test" xml:space="preserve">(salary, bonus)</eg>
                  </item>
                  <item>
                     <p>Assuming that <code nobreak="false">$price</code> is bound to
the value <code nobreak="false">10.50</code>, the result of this expression is the sequence <code nobreak="false">10.50, 10.50</code>.</p>
                     <eg role="parse-test" xml:space="preserve">($price, $price)</eg>
                  </item>
               </ulist>
            </div3>
            <div3 id="id-range-expressions" diff="chg" at="A">
               <head>Range Expressions</head>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-RangeExpr">
                     <lhs>RangeExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-AdditiveExpr">AdditiveExpr<!--$idref_lang_part = xpath40- --></nt>  ("to"  <nt def="prod-xpath40-AdditiveExpr">AdditiveExpr<!--$idref_lang_part = xpath40- --></nt>)?</rhs>
                  </prod>

                  <prod id="doc-xpath40-RangeExpr-AdditiveExpr">
                     <lhs>AdditiveExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-MultiplicativeExpr">MultiplicativeExpr<!--$idref_lang_part = xpath40- --></nt>  (("+"  |  "-")  <nt def="prod-xpath40-MultiplicativeExpr">MultiplicativeExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
                  </prod>
               </scrap>
               <p>
                  <termdef id="dt-range-expression" term="range expression">A 
               <term>range expression</term> is a <termref def="dt-non-trivial"/>
               instance of the production <nt def="doc-xpath40-RangeExpr">RangeExpr<!--$spec = xpath40--></nt>. A range expression
               is used to construct a sequence of 
               integers.</termdef>
               </p>
               <p>Each of the operands is coerced to the required
               type <code nobreak="false">xs:integer?</code> using the <termref def="dt-coercion-rules"/>.
               If either operand is the 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 the 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. </p>
               <p>The following examples illustrate the semantics:</p>
               <ulist>
                  <item>
                     <p>
                        <code nobreak="false">1 to 4</code> returns the sequence <code nobreak="false">1, 2, 3, 4</code>
                     </p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">10 to 10</code> returns the <termref def="dt-singleton"/> sequence <code nobreak="false">10</code>
                     </p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">10 to 1</code> returns the empty sequence</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">-13 to -10</code> returns the sequence <code nobreak="false">-13, -12, -11, -10</code>
                     </p>
                  </item>
               </ulist>
               <p>More formally, a <termref def="dt-range-expression"/> is evaluated as follows:</p>
               <olist>
                  <item>
                     <p>Each of the operands of the <code nobreak="false">to</code> operator is converted as though it was an argument of a function
                  with the expected parameter type <code nobreak="false">xs:integer?</code>.</p>
                  </item>
                  <item>
                     <p>If either operand is the 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 the empty sequence.</p>
                  </item>
                  <item>
                     <p>If the two operands convert to the same integer, the result of the range expression is that integer.</p>
                  </item>
                  <item>
                     <p>Otherwise, the result is a sequence containing the two integer operands and every integer between the 
                  two operands, in increasing order.</p>
                  </item>
               </olist>
               <p>The following examples illustrate the use of 
               <termref def="dt-range-expression">range expressions</termref>.</p>
               <example>
                  <p>This example uses a range expression as one operand in constructing a sequence. 
                  It evaluates to the sequence <code nobreak="false">10, 1, 2, 3, 4</code>.</p>
                  <eg role="parse-test" xml:space="preserve">(10, 1 to 4)</eg>
                  <p>This example selects the first four items from an input sequence:</p>
                  <eg role="parse-test" xml:space="preserve">$input[1 to 4]</eg>
                  <p>This example returns the sequence <code nobreak="false">(0, 0.1, 0.2, 0.3, 0.5)</code>:</p>
                  <eg role="parse-test" xml:space="preserve">$x = (1 to 5) ! . * 0.1</eg>
                  <p>This example constructs a sequence of length one containing the single integer 10.</p>
                  <eg role="parse-test" xml:space="preserve">10 to 10</eg>
                  <p>The result of this example is a sequence of length zero.</p>
                  <eg role="parse-test" xml:space="preserve">15 to 10</eg>
                  <p>This example uses the <function>fn:reverse</function> function to construct a sequence of six integers in decreasing order. 
                  It evaluates to the sequence 15, 14, 13, 12, 11, 10.</p>
                  <eg role="parse-test" xml:space="preserve">reverse(10 to 15)</eg>
               </example>
               <note>
                  <p>To construct a sequence of integers based on steps other than 1, use the <function>fn:slice</function>
               function, as defined in <xspecref spec="FO31" ref="general-seq-funcs"/>.</p>
               </note>
            </div3>
            <div3 id="combining_seq">
               <head>Combining GNode Sequences</head>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-UnionExpr">
                     <lhs>UnionExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-IntersectExceptExpr">IntersectExceptExpr<!--$idref_lang_part = xpath40- --></nt>  (("union"  |  "|")  <nt def="prod-xpath40-IntersectExceptExpr">IntersectExceptExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
                  </prod>

                  <prod id="doc-xpath40-UnionExpr-IntersectExceptExpr">
                     <lhs>IntersectExceptExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-InstanceofExpr">InstanceofExpr<!--$idref_lang_part = xpath40- --></nt>  (("intersect"  |  "except")  <nt def="prod-xpath40-InstanceofExpr">InstanceofExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
                  </prod>

                  <prod id="doc-xpath40-UnionExpr-InstanceofExpr">
                     <lhs>InstanceofExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-TreatExpr">TreatExpr<!--$idref_lang_part = xpath40- --></nt>  ("instance"  "of"  <nt def="prod-xpath40-SequenceType">SequenceType<!--$idref_lang_part = xpath40- --></nt>)?</rhs>
                  </prod>
               </scrap>
               <p>XPath 4.0 provides the following operators for combining sequences of
<termref def="dt-GNode">GNodes</termref>:</p>
               <ulist>
                  <item>
                     <p>The <code nobreak="false">union</code> and <code nobreak="false">|</code> operators are equivalent. They take two node sequences as operands and
return a sequence containing all the GNodes that occur in either of the
operands.</p>
                  </item>
                  <item>
                     <p>The <code nobreak="false">intersect</code> operator takes two GNodes sequences as operands and returns a sequence
containing all the GNodes that occur in both operands.</p>
                  </item>
                  <item>
                     <p>The <code nobreak="false">except</code> operator takes two node sequences as operands and returns a sequence
containing all the GNodes that occur in the first operand but not in the second
operand.</p>
                  </item>
               </ulist>
               <p>All these operators eliminate duplicate GNodes from their result sequences based on GNode identity. 
               The resulting sequence is returned in <termref def="dt-document-order">document order</termref>.
            </p>
               <p>If an operand
of <code nobreak="false">union</code>, <code nobreak="false">intersect</code>, or <code nobreak="false">except</code> contains an item that is not a <termref def="dt-GNode"/>, a <termref def="dt-type-error">type error</termref> is raised <errorref class="TY" code="0004"/>.</p>
               <p>
If an <nt def="prod-xpath40-IntersectExceptExpr">IntersectExceptExpr<!--$spec = xpath40--></nt> contains more than two 
               <nt def="doc-xpath40-InstanceofExpr">InstanceofExpr<!--$spec = xpath40--></nt> operands,
they are evaluated from left to right.
With a <code nobreak="false">UnionExpr</code>, it makes no difference how operands are grouped,
the results are the same.
</p>
               <example>
                  <p>Here are some examples of expressions that combine sequences. 
                  Assume the existence of three element nodes that we will refer to by symbolic names A, B, and C. 
                  Assume that the variables <code nobreak="false">$seq1</code>, <code nobreak="false">$seq2</code>  and <code nobreak="false">$seq3</code> 
                  are bound to the following sequences of these nodes:</p>
                  <ulist>
                     <item>
                        <p>
                           <code nobreak="false">$seq1</code> is bound to (A, B)</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">$seq2</code> is bound to (A, B)</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">$seq3</code> is bound to (B, C)</p>
                     </item>
                  </ulist>
                  <p>Then: </p>
                  <ulist>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">$seq1 union $seq2</code>  evaluates to the sequence (A, B). </p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">$seq2 union $seq3</code>   evaluates to the sequence (A, B, C). </p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">$seq1 intersect $seq2</code>  evaluates to the sequence (A, B). </p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">$seq2 intersect $seq3</code>  evaluates to the sequence containing B only.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">$seq1 except $seq2</code>   evaluates to the empty sequence.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">$seq2 except $seq3</code>  evaluates to the sequence containing A only.</p>
                     </item>
                  </ulist>
               </example>
               <p>The following example demonstrates the use of the <code nobreak="false">except</code> operator
            with JNodes:</p>
               <eg xml:space="preserve">let $m := jtree($map)
for $e in $m/child::* except $m/child::xx 
return ...</eg>
               <note>
                  <p>Because the <function>fn:jtree</function> creates a new JTree root,
            calling it twice potentially creates two different trees, in which the JNodes have
            different identity. The expression <code nobreak="false">$map/child::* except $map/child::xx</code>
            might therefore have the wrong effect, because JNodes in two different trees 
            are being compared. For more details see the specification of the
            <function>fn:jtree</function> function.</p>
               </note>
               <p>In addition to the sequence operators described here, see <xspecref spec="FO40" ref="sequence-functions"/> for functions defined on sequences.
</p>
            </div3>
         </div2>
         <div2 id="id-arithmetic">
            <head>Arithmetic Expressions</head>
            <changes>
               <change>
               The symbols <code nobreak="false">×</code> and <code nobreak="false">÷</code> can be used for multiplication and division.
            </change>
            </changes>
            <p>XPath 4.0 provides binary arithmetic operators for addition, subtraction,
multiplication, division, and modulus:</p>
            <scrap headstyle="show">
               <prod id="doc-xpath40-AdditiveExpr">
                  <lhs>AdditiveExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-MultiplicativeExpr">MultiplicativeExpr<!--$idref_lang_part = xpath40- --></nt>  (("+"  |  "-")  <nt def="prod-xpath40-MultiplicativeExpr">MultiplicativeExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
               </prod>

               <prod id="doc-xpath40-AdditiveExpr-MultiplicativeExpr">
                  <lhs>MultiplicativeExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-UnionExpr">UnionExpr<!--$idref_lang_part = xpath40- --></nt>  (("*"  |  "×"  |  "div"  |  "÷"  |  "idiv"  |  "mod")  <nt def="prod-xpath40-UnionExpr">UnionExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
               </prod>

               <prod id="doc-xpath40-AdditiveExpr-UnionExpr">
                  <lhs>UnionExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-IntersectExceptExpr">IntersectExceptExpr<!--$idref_lang_part = xpath40- --></nt>  (("union"  |  "|")  <nt def="prod-xpath40-IntersectExceptExpr">IntersectExceptExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
               </prod>
            </scrap>
            <p>In addition, unary operators are provided for addition and subtraction:</p>
            <scrap headstyle="show">
               <prod id="doc-xpath40-UnaryExpr">
                  <lhs>UnaryExpr</lhs>
                  <rhs>("-"  |  "+")*  <nt def="prod-xpath40-ValueExpr">ValueExpr<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-UnaryExpr-ValueExpr">
                  <lhs>ValueExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-SimpleMapExpr">SimpleMapExpr<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-UnaryExpr-SimpleMapExpr">
                  <lhs>SimpleMapExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-PathExpr">PathExpr<!--$idref_lang_part = xpath40- --></nt>  ("!"  <nt def="prod-xpath40-PathExpr">PathExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
               </prod>
            </scrap>
            <p>A subtraction operator must be preceded by whitespace if
it could otherwise be interpreted as part of the previous token. For
example, <code role="parse-test" nobreak="false">a-b</code> will be interpreted as a
name, but <code role="parse-test" nobreak="false">a - b</code> and <code role="parse-test" nobreak="false">a -b</code> will be interpreted as arithmetic expressions. (See <specref ref="whitespace-rules"/> for further details on whitespace handling.)</p>
            <p diff="add" at="2023-05-02">The arithmetic operator symbols <code nobreak="false">*</code> and <char>U+00D7</char> are interchangeable,
         and denote multiplication.</p>
            <p diff="add" at="2023-05-02">The arithmetic operator symbols <code nobreak="false">div</code> and <char>U+00F7</char> are interchangeable,
            and denote division.</p>
            <p>
If an <code nobreak="false">AdditiveExpr</code> contains more than two <code nobreak="false">MultiplicativeExprs</code>,
they are grouped from left to right. So, for instance,
<eg role="parse-test" xml:space="preserve">A - B + C - D</eg>
is equivalent to
<eg role="parse-test" xml:space="preserve">((A - B) + C) - D</eg>
Similarly, the operands of a <code nobreak="false">MultiplicativeExpr</code> are grouped from left to right.
</p>
            <p>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 <termref def="dt-implementation-dependent">implementation-dependent</termref>.</p>
            <p role="xpath">If <termref def="dt-xpath-compat-mode">XPath 1.0 compatibility mode</termref> is <code nobreak="false">true</code>, each operand is evaluated by applying the following steps, in order:</p>
            <olist role="xpath">
               <item>
                  <p>
                     <termref def="dt-atomization">Atomization</termref> is applied to the operand. The result of this
    operation is called the <term>atomized operand</term>.</p>
               </item>
               <item>
                  <p>If the atomized operand is the empty sequence, the result of
    the arithmetic expression is the <code nobreak="false">xs:double</code> value <code nobreak="false">NaN</code>, 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.</p>
               </item>
               <item>
                  <p>If the atomized operand is a sequence of length greater than one, any items after the first item in the sequence are discarded.</p>
               </item>
               <item>
                  <p>If the atomized operand is now an instance of type <code nobreak="false">xs:boolean</code>, <code nobreak="false">xs:string</code>,
<code nobreak="false">xs:decimal</code> (including <code nobreak="false">xs:integer</code>), <code nobreak="false">xs:float</code>, or <code nobreak="false">xs:untypedAtomic</code>, then it
is converted to the type <code nobreak="false">xs:double</code> by applying the <function>fn:number</function> function. (Note that <function>fn:number</function> returns the value <code nobreak="false">NaN</code> if its operand cannot be converted to a number.)</p>
               </item>
            </olist>
            <p>
               <phrase role="xpath">If <termref def="dt-xpath-compat-mode">XPath 1.0 compatibility mode</termref> is <code nobreak="false">false</code>, each</phrase>
             operand is evaluated by applying the following steps, in order:</p>
            <olist>
               <item>
                  <p>
                     <termref def="dt-atomization">Atomization</termref> is applied to the operand. The result of this
    operation is called the <term>atomized operand</term>.</p>
               </item>
               <item>
                  <p>If the atomized operand is the empty sequence, the result of
    the arithmetic expression is the 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.</p>
               </item>
               <item>
                  <p> If the atomized operand is a sequence of
length greater than one, a <termref def="dt-type-error">type error</termref> is raised <errorref class="TY" code="0004"/>.</p>
               </item>
               <item>
                  <p>If the atomized operand is of type <code nobreak="false">xs:untypedAtomic</code>, it is cast to  <code nobreak="false">xs:double</code>. If
the cast fails, a <termref def="dt-dynamic-error">dynamic
error</termref> is raised. <xerrorref spec="FO40" class="RG" code="0001"/>
                  </p>
               </item>
            </olist>
            <p>If, after this process, both operands of a binary arithmetic operator
            are instances of <code nobreak="false">xs:numeric</code>
         but have different primitive types, they are coerced to a common type by applying
         the following rules:</p>
            <olist>
               <item>
                  <p>If either of the items is of type <code nobreak="false">xs:double</code>, then 
            both the values are cast to type <code nobreak="false">xs:double</code>.</p>
               </item>
               <item>
                  <p>Otherwise, if either of the items is of type <code nobreak="false">xs:float</code>, then 
              both the values are cast to type <code nobreak="false">xs:float</code>.</p>
               </item>
               <item>
                  <p>Otherwise, no casting takes place: the values remain as <code nobreak="false">xs:decimal</code>.</p>
               </item>
            </olist>
            <p>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 <bibref ref="xpath-functions-40"/>.</p>
            <table border="1" role="small">
               <caption>Unary Arithmetic Operators</caption>
               <thead>
                  <tr>
                     <th rowspan="1" colspan="1">Expression</th>
                     <th rowspan="1" colspan="1">Type of A</th>
                     <th rowspan="1" colspan="1">Function</th>
                     <th rowspan="1" colspan="1">Result type</th>
                  </tr>
               </thead>
               <tbody>
                  <tr>
                     <td rowspan="1" colspan="1">+ A</td>
                     <td rowspan="1" colspan="1">xs:numeric</td>
                     <td rowspan="1" colspan="1">
                        <function>op:numeric-unary-plus</function>
                        <code nobreak="false">(A)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:numeric</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">- A</td>
                     <td rowspan="1" colspan="1">xs:numeric</td>
                     <td rowspan="1" colspan="1">
                        <function>op:numeric-unary-minus</function>
                        <code nobreak="false">(A)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:numeric</td>
                  </tr>
               </tbody>
            </table>
            <table border="1" role="small">
               <caption>Binary Arithmetic Operators</caption>
               <tbody>
                  <tr>
                     <th rowspan="1" colspan="1">Expression</th>
                     <th rowspan="1" colspan="1">Type of A</th>
                     <th rowspan="1" colspan="1">Type of B</th>
                     <th rowspan="1" colspan="1">Function</th>
                     <th rowspan="1" colspan="1">Result type</th>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A + B</td>
                     <td rowspan="1" colspan="1">xs:numeric</td>
                     <td rowspan="1" colspan="1">xs:numeric</td>
                     <td rowspan="1" colspan="1">
                        <function>op:numeric-add</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:numeric</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A + B</td>
                     <td rowspan="1" colspan="1">xs:date</td>
                     <td rowspan="1" colspan="1">xs:yearMonthDuration</td>
                     <td rowspan="1" colspan="1">
                        <function>op:add-yearMonthDuration-to-date</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:date</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A + B</td>
                     <td rowspan="1" colspan="1">xs:yearMonthDuration</td>
                     <td rowspan="1" colspan="1">xs:date</td>
                     <td rowspan="1" colspan="1">
                        <function>op:add-yearMonthDuration-to-date</function>
                        <code nobreak="false">(B, A)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:date</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A + B</td>
                     <td rowspan="1" colspan="1">xs:date</td>
                     <td rowspan="1" colspan="1">xs:dayTimeDuration</td>
                     <td rowspan="1" colspan="1">
                        <function>op:add-dayTimeDuration-to-date</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:date</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A + B</td>
                     <td rowspan="1" colspan="1">xs:dayTimeDuration</td>
                     <td rowspan="1" colspan="1">xs:date</td>
                     <td rowspan="1" colspan="1">
                        <function>op:add-dayTimeDuration-to-date</function>
                        <code nobreak="false">(B, A)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:date</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A + B</td>
                     <td rowspan="1" colspan="1">xs:time</td>
                     <td rowspan="1" colspan="1">xs:dayTimeDuration</td>
                     <td rowspan="1" colspan="1">
                        <function>op:add-dayTimeDuration-to-time</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:time</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A + B</td>
                     <td rowspan="1" colspan="1">xs:dayTimeDuration</td>
                     <td rowspan="1" colspan="1">xs:time</td>
                     <td rowspan="1" colspan="1">
                        <function>op:add-dayTimeDuration-to-time</function>
                        <code nobreak="false">(B, A)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:time</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A + B</td>
                     <td rowspan="1" colspan="1">xs:dateTime</td>
                     <td rowspan="1" colspan="1">xs:yearMonthDuration</td>
                     <td rowspan="1" colspan="1">
                        <function>op:add-yearMonthDuration-to-dateTime</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:dateTime</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A + B</td>
                     <td rowspan="1" colspan="1">xs:yearMonthDuration</td>
                     <td rowspan="1" colspan="1">xs:dateTime</td>
                     <td rowspan="1" colspan="1">
                        <function>op:add-yearMonthDuration-to-dateTime</function>
                        <code nobreak="false">(B, A)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:dateTime</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A + B</td>
                     <td rowspan="1" colspan="1">xs:dateTime</td>
                     <td rowspan="1" colspan="1">xs:dayTimeDuration</td>
                     <td rowspan="1" colspan="1">
                        <function>op:add-dayTimeDuration-to-dateTime</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:dateTime</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A + B</td>
                     <td rowspan="1" colspan="1">xs:dayTimeDuration</td>
                     <td rowspan="1" colspan="1">xs:dateTime</td>
                     <td rowspan="1" colspan="1">
                        <function>op:add-dayTimeDuration-to-dateTime</function>
                        <code nobreak="false">(B, A)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:dateTime</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A + B</td>
                     <td rowspan="1" colspan="1">xs:yearMonthDuration</td>
                     <td rowspan="1" colspan="1">xs:yearMonthDuration</td>
                     <td rowspan="1" colspan="1">
                        <function>op:add-yearMonthDurations</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:yearMonthDuration</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A + B</td>
                     <td rowspan="1" colspan="1">xs:dayTimeDuration</td>
                     <td rowspan="1" colspan="1">xs:dayTimeDuration</td>
                     <td rowspan="1" colspan="1">
                        <function>op:add-dayTimeDurations</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:dayTimeDuration</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A - B</td>
                     <td rowspan="1" colspan="1">xs:numeric</td>
                     <td rowspan="1" colspan="1">xs:numeric</td>
                     <td rowspan="1" colspan="1">
                        <function>op:numeric-subtract</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:numeric</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A - B</td>
                     <td rowspan="1" colspan="1">xs:date</td>
                     <td rowspan="1" colspan="1">xs:date</td>
                     <td rowspan="1" colspan="1">
                        <function>op:subtract-dates</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:dayTimeDuration</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A - B</td>
                     <td rowspan="1" colspan="1">xs:date</td>
                     <td rowspan="1" colspan="1">xs:yearMonthDuration</td>
                     <td rowspan="1" colspan="1">
                        <function>op:subtract-yearMonthDuration-from-date</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:date</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A - B</td>
                     <td rowspan="1" colspan="1">xs:date</td>
                     <td rowspan="1" colspan="1">xs:dayTimeDuration</td>
                     <td rowspan="1" colspan="1">
                        <function>op:subtract-dayTimeDuration-from-date</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:date</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A - B</td>
                     <td rowspan="1" colspan="1">xs:time</td>
                     <td rowspan="1" colspan="1">xs:time</td>
                     <td rowspan="1" colspan="1">
                        <function>op:subtract-times</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:dayTimeDuration</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A - B</td>
                     <td rowspan="1" colspan="1">xs:time</td>
                     <td rowspan="1" colspan="1">xs:dayTimeDuration</td>
                     <td rowspan="1" colspan="1">
                        <function>op:subtract-dayTimeDuration-from-time</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:time</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A - B</td>
                     <td rowspan="1" colspan="1">xs:dateTime</td>
                     <td rowspan="1" colspan="1">xs:dateTime</td>
                     <td rowspan="1" colspan="1">
                        <function>op:subtract-dateTimes</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:dayTimeDuration</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A - B</td>
                     <td rowspan="1" colspan="1">xs:dateTime</td>
                     <td rowspan="1" colspan="1">xs:yearMonthDuration</td>
                     <td rowspan="1" colspan="1">
                        <function>op:subtract-yearMonthDuration-from-dateTime</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:dateTime</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A - B</td>
                     <td rowspan="1" colspan="1">xs:dateTime</td>
                     <td rowspan="1" colspan="1">xs:dayTimeDuration</td>
                     <td rowspan="1" colspan="1">
                        <function>op:subtract-dayTimeDuration-from-dateTime</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:dateTime</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A - B</td>
                     <td rowspan="1" colspan="1">xs:yearMonthDuration</td>
                     <td rowspan="1" colspan="1">xs:yearMonthDuration</td>
                     <td rowspan="1" colspan="1">
                        <function>op:subtract-yearMonthDurations</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:yearMonthDuration</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A - B</td>
                     <td rowspan="1" colspan="1">xs:dayTimeDuration</td>
                     <td rowspan="1" colspan="1">xs:dayTimeDuration</td>
                     <td rowspan="1" colspan="1">
                        <function>op:subtract-dayTimeDurations</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:dayTimeDuration</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A * B</td>
                     <td rowspan="1" colspan="1">xs:numeric</td>
                     <td rowspan="1" colspan="1">xs:numeric</td>
                     <td rowspan="1" colspan="1">
                        <function>op:numeric-multiply</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:numeric</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A * B</td>
                     <td rowspan="1" colspan="1">xs:yearMonthDuration</td>
                     <td rowspan="1" colspan="1">xs:numeric</td>
                     <td rowspan="1" colspan="1">
                        <function>op:multiply-yearMonthDuration</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:yearMonthDuration</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A * B</td>
                     <td rowspan="1" colspan="1">xs:numeric</td>
                     <td rowspan="1" colspan="1">xs:yearMonthDuration</td>
                     <td rowspan="1" colspan="1">
                        <function>op:multiply-yearMonthDuration</function>
                        <code nobreak="false">(B, A)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:yearMonthDuration</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A * B</td>
                     <td rowspan="1" colspan="1">xs:dayTimeDuration</td>
                     <td rowspan="1" colspan="1">xs:numeric</td>
                     <td rowspan="1" colspan="1">
                        <function>op:multiply-dayTimeDuration</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:dayTimeDuration</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A * B</td>
                     <td rowspan="1" colspan="1">xs:numeric</td>
                     <td rowspan="1" colspan="1">xs:dayTimeDuration</td>
                     <td rowspan="1" colspan="1">
                        <function>op:multiply-dayTimeDuration</function>
                        <code nobreak="false">(B, A)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:dayTimeDuration</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A idiv B</td>
                     <td rowspan="1" colspan="1">xs:numeric</td>
                     <td rowspan="1" colspan="1">xs:numeric</td>
                     <td rowspan="1" colspan="1">
                        <function>op:numeric-integer-divide</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:integer</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A div B</td>
                     <td rowspan="1" colspan="1">xs:numeric</td>
                     <td rowspan="1" colspan="1">xs:numeric</td>
                     <td rowspan="1" colspan="1">
                        <function>op:numeric-divide</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">numeric; but xs:decimal if both operands are xs:integer</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A div B</td>
                     <td rowspan="1" colspan="1">xs:yearMonthDuration</td>
                     <td rowspan="1" colspan="1">xs:numeric</td>
                     <td rowspan="1" colspan="1">
                        <function>op:divide-yearMonthDuration</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:yearMonthDuration</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A div B</td>
                     <td rowspan="1" colspan="1">xs:dayTimeDuration</td>
                     <td rowspan="1" colspan="1">xs:numeric</td>
                     <td rowspan="1" colspan="1">
                        <function>op:divide-dayTimeDuration</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:dayTimeDuration</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A div B</td>
                     <td rowspan="1" colspan="1">xs:yearMonthDuration</td>
                     <td rowspan="1" colspan="1">xs:yearMonthDuration</td>
                     <td rowspan="1" colspan="1">
                        <function>op:divide-yearMonthDuration-by-yearMonthDuration</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:decimal</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A div B</td>
                     <td rowspan="1" colspan="1">xs:dayTimeDuration</td>
                     <td rowspan="1" colspan="1">xs:dayTimeDuration</td>
                     <td rowspan="1" colspan="1">
                        <function>op:divide-dayTimeDuration-by-dayTimeDuration</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:decimal</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">A mod B</td>
                     <td rowspan="1" colspan="1">xs:numeric</td>
                     <td rowspan="1" colspan="1">xs:numeric</td>
                     <td rowspan="1" colspan="1">
                        <function>op:numeric-mod</function>
                        <code nobreak="false">(A, B)</code>
                     </td>
                     <td rowspan="1" colspan="1">xs:numeric</td>
                  </tr>
               </tbody>
            </table>
            <note>
               <p>The operator symbol <code nobreak="false">×</code> is a synonym of <code nobreak="false">*</code>, while <code nobreak="false">÷</code> is
a synonym of <code nobreak="false">div</code>.</p>
            </note>
            <p>If there is no entry in the table for the combination of operator and operands,
    then a <termref def="dt-type-error"/> is raised <errorref class="TY" code="0004"/>.</p>
            <p>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).</p>
            <note>
               <p>XPath 4.0 provides three division operators:</p>
               <ulist>
                  <item>
                     <p>The <code nobreak="false">div</code> and <code nobreak="false">÷</code> operators are synonyms, and implement
               numeric division as well as division of duration values; the semantics are defined in
               <xspecref spec="FO40" ref="func-numeric-divide"/>
                     </p>
                  </item>
                  <item>
                     <p>The <code nobreak="false">idiv</code> operator implements integer division; the semantics are defined
               in <xspecref spec="FO40" ref="func-numeric-integer-divide"/>
                     </p>
                  </item>
               </ulist>
            </note>
            <p>Here are some examples of arithmetic expressions:</p>
            <ulist>
               <item>
                  <p>The first expression below returns the <code nobreak="false">xs:decimal</code> value <code role="parse-test" nobreak="false">-1.5</code>, and the second expression returns the <code nobreak="false">xs:integer</code> value <code role="parse-test" nobreak="false">-1</code>:</p>
                  <eg role="parse-test" xml:space="preserve">-3 div 2
-3 idiv 2</eg>
               </item>
               <item>
                  <p>Subtraction of two date values results in a value of type <code nobreak="false">xs:dayTimeDuration</code>:</p>
                  <eg role="parse-test" xml:space="preserve">$emp/hiredate - $emp/birthdate</eg>
               </item>
               <item>
                  <p>This example illustrates the difference between a subtraction operator and a
hyphen:</p>
                  <eg role="parse-test" xml:space="preserve">$unit-price - $unit-discount</eg>
               </item>
               <item>
                  <p>Unary operators have higher precedence than binary operators (other than <code nobreak="false">!</code>, <code nobreak="false">/</code>, and <code nobreak="false">[]</code>), subject of
course to the use of parentheses. Therefore, the following two examples have different meanings:</p>
                  <eg xml:space="preserve">-$bellcost + $whistlecost
-($bellcost + $whistlecost)</eg>
               </item>
            </ulist>
            <note>
               <p id="note-consecutive-unary-ops">Multiple consecutive unary arithmetic operators are permitted (though not useful).</p>
            </note>
            <note>
               <p>Negation is not the same as subtraction from zero: if <code nobreak="false">$x</code> is positive zero,
            then <code nobreak="false">-$x</code> returns negative zero, wheras <code nobreak="false">0 - $x</code> returns positive zero.</p>
            </note>
         </div2>
         <div2 id="id-string-expr">
            <head>String Expressions</head>
            <p>This section describes several ways of constructing strings.</p>
            <div3 id="id-string-concat-expr">
               <head>String Concatenation Expressions</head>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-StringConcatExpr">
                     <lhs>StringConcatExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-RangeExpr">RangeExpr<!--$idref_lang_part = xpath40- --></nt>  ("||"  <nt def="prod-xpath40-RangeExpr">RangeExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
                  </prod>

                  <prod id="doc-xpath40-StringConcatExpr-RangeExpr">
                     <lhs>RangeExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-AdditiveExpr">AdditiveExpr<!--$idref_lang_part = xpath40- --></nt>  ("to"  <nt def="prod-xpath40-AdditiveExpr">AdditiveExpr<!--$idref_lang_part = xpath40- --></nt>)?</rhs>
                  </prod>
               </scrap>
               <p>String concatenation expressions allow the string representations of values to be
               concatenated. In XPath 4.0, <code nobreak="false">$a || $b</code> is equivalent to
               <code nobreak="false">fn:concat($a, $b)</code>.
               The following expression evaluates to the string <code nobreak="false">concatenate</code>:</p>
               <eg xml:space="preserve">() || "con" || ("cat", "enate")</eg>
            </div3>
            <div3 id="id-string-templates" diff="add" at="2023-01-29">
               <head>String Templates</head>
               <changes>
                  <change issue="58" PR="324" date="2023-01-29">
                  String templates provide a new way of constructing strings: for example <code nobreak="false">`{$greeting}, {$planet}!`</code>
                  is equivalent to <code nobreak="false">$greeting || ', ' || $planet || '!'</code>
                  </change>
               </changes>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-StringTemplate">
                     <lhs>StringTemplate</lhs>
                     <rhs>"`"  (<nt def="prod-xpath40-StringTemplateFixedPart">StringTemplateFixedPart<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-StringTemplateVariablePart">StringTemplateVariablePart<!--$idref_lang_part = xpath40- --></nt>)*  "`"</rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="doc-xpath40-StringTemplate-StringTemplateFixedPart">
                     <lhs>StringTemplateFixedPart</lhs>
                     <rhs>((<nt def="prod-xpath40-Char">Char<!--$idref_lang_part = xpath40- --></nt> - ('{' | '}' | '`'))  |  "{{"  |  "}}"  |  "``")+</rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="doc-xpath40-StringTemplate-Char">
                     <lhs>Char</lhs>
                     <rhs>
                        <xnt ref="NT-Char" spec="XML">[http://www.w3.org/TR/REC-xml#NT-Char]</xnt>
                     </rhs>
                     <com>
                        <loc href="#parse-note-xml-version">xgc: xml-version</loc>
                     </com>
                  </prod>

                  <prod id="doc-xpath40-StringTemplate-StringTemplateVariablePart">
                     <lhs>StringTemplateVariablePart</lhs>
                     <rhs>
                        <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-StringTemplate-EnclosedExpr">
                     <lhs>EnclosedExpr</lhs>
                     <rhs>"{"  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>?  "}"</rhs>
                  </prod>
               </scrap>
               <p>String templates provide an alternative way of constructing strings. For example,
            the expression <code nobreak="false">`Pi is { round(math:pi(), 4) }`</code> returns the string <code nobreak="false">"Pi is 3.1416"</code>.</p>
               <p>A string template starts and ends with <char>U+0060</char>, popularly known as a back-tick. Between
               the back-ticks is a string consisting of an sequence of fixed parts and
               variable parts:</p>
               <ulist>
                  <item>
                     <p>A variable part consists of an optional XPath expression enclosed in curly brackets (<code nobreak="false">{}</code>):
                  more specifically, a string conforming 
                  to the XPath production <code nobreak="false">Expr?</code>.</p>
                     <note>
                        <p>An expression within a variable part may contain an unescaped <char>U+007B</char> 
                        or <char>U+007D</char> within
                        a <nt def="doc-xpath40-StringLiteral">StringLiteral<!--$spec = xpath40--></nt> or within
                        a comment.</p>
                        <p>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. </p>
                     </note>
                  </item>
                  <item>
                     <p>A fixed part may contain any characters, except that:</p>
                     <ulist>
                        <item>
                           <p>The character <char>U+007B</char>
                              <rfc2119>must</rfc2119>
                        be written as <code nobreak="false">{{</code>.</p>
                        </item>
                        <item>
                           <p>The character <char>U+007D</char>
                              <rfc2119>must</rfc2119> be
                        written as <code nobreak="false">}}</code>.</p>
                        </item>
                        <item>
                           <p>The character <char>U+0060</char>
                              <rfc2119>must</rfc2119> be
                        written as <code nobreak="false">``</code>.</p>
                        </item>
                     </ulist>
                     <p>Following the principles of the “longest token” rule, any occurrence
                  of <code nobreak="false">{{</code> within the fixed part is interpreted as an escaped left
                  curly bracket. This means that the enclosed expression must not start with
                  <char>U+007B</char>: if this is required, the two left curly brackets can
                  be separated by whitespace. For example the string template
                     <code nobreak="false">`{{"key":"{ {1:"yes", 0:"no"}?$condition}"}}`</code>
                     evaluates to the string <code nobreak="false">{"key":"yes"}</code> or <code nobreak="false">{"key":"no"}</code>
                     depending on the value of <code nobreak="false">$condition</code>.</p>
                     <p>By contrast, if the enclosed expression ends with <char>U+007D</char>,
                  this can be immediately followed by the closing <char>U+007D</char>
                  delimiter without intervening whitespace.</p>
                  </item>
               </ulist>
               <p>
               The result of evaluating a
                  string template is the string obtained by concatenating the expansions of the fixed
               and variable parts:</p>
               <ulist>
                  <item>
                     <p>The expansion of a fixed part is obtained by replacing any double curly
                     brackets (<code nobreak="false">{{</code> or <code nobreak="false">}}</code>) by the corresponding single curly
                     bracket, and replacing doubled back-ticks (<code nobreak="false">``</code>) by a single back-tick.</p>
                  </item>
                  <item>
                     <p>The expansion of a variable part containing an expression is as follows:</p>
                     <olist>
                        <item>
                           <p>
                              <termref def="dt-atomization">Atomization</termref> is applied to the value of the enclosed expression, 
                           converting it to a sequence of atomic items.</p>
                        </item>
                        <item>
                           <p>If the result of atomization is the empty sequence, the result 
                           is the zero-length string. Otherwise, each atomic item in the 
                           atomized sequence is cast into a string.</p>
                        </item>
                        <item>
                           <p>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.</p>
                        </item>
                     </olist>
                  </item>
                  <item>
                     <p>The expansion of the empty variable part (one that contains no expression) is a zero-length string.</p>
                  </item>
               </ulist>
               <p>For example:</p>
               <eg role="parse-test" xml:space="preserve">let $greeting := "Hello", $planet := "Mars"
return `{ $greeting }, { $planet }!`</eg>
               <p>returns <code nobreak="false">"Hello, Mars!"</code>.</p>
               <p>The expression:</p>
               <eg role="parse-test" xml:space="preserve">let $long-months := (1, 3, 5, 7, 8, 10, 12)
return `The months with 31 days are: { $long-months }.`</eg>
               <p>returns <code nobreak="false">"The months with 31 days are: 1 3 5 7 8 10 12."</code>.</p>
               <note>
                  <p>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.</p>
               </note>
               <note>
                  <p>A string template containing no variable parts is effectively just another
                  way of writing a string literal: <code nobreak="false">"Goethe"</code>, <code nobreak="false">'Goethe'</code>, and <code nobreak="false">`Goethe`</code>
               are interchangeable. This means that back-ticks can sometimes be a useful way of delimiting a string
               that contains both single and double quotes: <code nobreak="false">`He said: "I didn't."`</code>.</p>
                  <p>It is sometimes useful to use string templates in conjunction with the <function>fn:char</function> function
                  to build strings containing special characters, for example <code nobreak="false">`Chapter{ fn:char("nbsp") }{ $chapNr }`</code>.</p>
               </note>
               <note>
                  <p>String literals containing an ampersand behave differently between XPath and XQuery: in XPath 
               (unless first expanded by an XML parser) the string literal <code nobreak="false">"Bacon &amp; Eggs"</code> 
               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 <code nobreak="false">`Bacon &amp; Eggs`</code>) 
                  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.</p>
               </note>
               <p>In XQuery, the token <code nobreak="false">``[</code> is recognized as the start of a 
               <code role="xpath" nobreak="false">StringConstructor</code>,
            under the “longest token” rule (see <specref ref="lexical-structure"/>). This means that the construct
               <code nobreak="false">``[1]</code> is not recognized as a <nt def="doc-xpath40-StringTemplate">StringTemplate<!--$spec = xpath40--></nt> followed by a predicate. 
               <phrase role="xpath">Although
               the token <code nobreak="false">``[</code> is not used in XPath, it is reserved for compatibility reasons, and <rfc2119>must</rfc2119>
               be rejected as syntactically invalid.</phrase> In the unlikely event that an empty <nt def="doc-xpath40-StringTemplate">StringTemplate<!--$spec = xpath40--></nt>
            followed by a predicate is wanted, whitespace or parentheses can be used to avoid the tokenization problem.</p>
            </div3>
         </div2>
         <div2 id="id-comparisons">
            <head>Comparison Expressions</head>
            <p>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.</p>
            <scrap headstyle="show">
               <prod id="doc-xpath40-ComparisonExpr">
                  <lhs>ComparisonExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-OtherwiseExpr">OtherwiseExpr<!--$idref_lang_part = xpath40- --></nt>  ((<nt def="prod-xpath40-ValueComp">ValueComp<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-GeneralComp">GeneralComp<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-NodeComp">NodeComp<!--$idref_lang_part = xpath40- --></nt>)  <nt def="prod-xpath40-OtherwiseExpr">OtherwiseExpr<!--$idref_lang_part = xpath40- --></nt>)?</rhs>
               </prod>

               <prod id="doc-xpath40-ComparisonExpr-OtherwiseExpr">
                  <lhs>OtherwiseExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-StringConcatExpr">StringConcatExpr<!--$idref_lang_part = xpath40- --></nt>  ("otherwise"  <nt def="prod-xpath40-StringConcatExpr">StringConcatExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
               </prod>

               <prod id="doc-xpath40-ComparisonExpr-ValueComp">
                  <lhs>ValueComp</lhs>
                  <rhs>"eq"  |  "ne"  |  "lt"  |  "le"  |  "gt"  |  "ge"</rhs>
               </prod>

               <prod id="doc-xpath40-ComparisonExpr-GeneralComp">
                  <lhs>GeneralComp</lhs>
                  <rhs>"="  |  "!="  |  "&lt;"  |  "&lt;="  |  "&gt;"  |  "&gt;="</rhs>
               </prod>

               <prod id="doc-xpath40-ComparisonExpr-NodeComp">
                  <lhs>NodeComp</lhs>
                  <rhs>"is"  |  "is-not"  |  <nt def="prod-xpath40-NodePrecedes">NodePrecedes<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-NodeFollows">NodeFollows<!--$idref_lang_part = xpath40- --></nt>  |  "precedes-or-is"  |  "follows-or-is"</rhs>
               </prod>

               <prod id="doc-xpath40-ComparisonExpr-NodePrecedes">
                  <lhs>NodePrecedes</lhs>
                  <rhs>"&lt;&lt;"  |  "precedes"</rhs>
               </prod>

               <prod id="doc-xpath40-ComparisonExpr-NodeFollows">
                  <lhs>NodeFollows</lhs>
                  <rhs>"&gt;&gt;"  |  "follows"</rhs>
               </prod>
            </scrap>
            <note role="xpath">
               <p role="xpath">When an XPath expression is written
within an XML document, the XML escaping rules for special characters
must be followed; thus <code nobreak="false">&lt;</code> must be written as
<code nobreak="false">&amp;lt;</code>.</p>
            </note>
            <p>For a summary of the differences between different ways of comparing atomic items
         in XPath 4.0, see <specref ref="id-atomic-comparisons"/>.</p>
            <div3 id="id-value-comparisons">
               <head>Value Comparisons</head>
               <changes>
                  <change issue="986" PR="2218" date="2025-09-29">
                  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.
               </change>
                  <change issue="2216" PR="2256" date="2025-12-01">
                  An ordering is now defined for all data types.
               </change>
               </changes>
               <p>The value comparison operators are <code nobreak="false">eq</code>, <code nobreak="false">ne</code>, <code nobreak="false">lt</code>, <code nobreak="false">le</code>, <code nobreak="false">gt</code>, and <code nobreak="false">ge</code>. 
               Value comparisons are used for comparing single <termref def="dt-atomic-item">atomic items</termref>.</p>
               <p>The first step in evaluating a value comparison is to evaluate its operands. The order in which the operands are evaluated is <termref def="dt-implementation-dependent">implementation-dependent</termref>. Each operand is evaluated by applying the following steps, in order:</p>
               <olist>
                  <item>
                     <p>
                        <termref def="dt-atomization">Atomization</termref> is applied to each  operand. The result of this
    operation is called the <term>atomized operand</term>.</p>
                  </item>
                  <item>
                     <p>If either or both of the atomized operands is the empty sequence, the result of
    the value comparison is the 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.</p>
                  </item>
                  <item>
                     <p> If an atomized operand is a sequence of
length greater than one, a <termref def="dt-type-error">type error</termref> is raised <errorref class="TY" code="0004"/>.</p>
                  </item>
                  <!--<item>
                  <p>If an  atomized operand is of type
  <code>xs:untypedAtomic</code> or <code>xs:anyURI</code>, then it is cast to
  <code>xs:string</code>.</p>
                  
               </item>-->
                  <item>
                     <p>If both operands are instances of <code nobreak="false">xs:numeric</code>, and
                     if either or both of the atomized operands is <code nobreak="false">NaN</code>, then the result is
               <code nobreak="false">false</code> if the operator is <code nobreak="false">eq</code>, <code nobreak="false">lt</code>, <code nobreak="false">gt</code>,
               <code nobreak="false">le</code>, or <code nobreak="false">ge</code>, but <code nobreak="false">true</code> if the operator
               is <code nobreak="false">ne</code>.</p>
                     <note>
                        <p>When an operand is <code nobreak="false">NaN</code>, the effect of a value comparison
               expression differs from the result of the <function>fn:compare</function>
               function.</p>
                     </note>
                  </item>
                  <item>
                     <p>The function <function>fn:compare</function> is then called, supplying
               the two atomized operands as the first two arguments. The collation used
               by <function>fn:compare</function> is the default collation from the static
               context, and the implicit timezone used by the function is the implicit
               timezone from the dynamic context.</p>
                     <note>
                        <p>The effect of this rule is that <code nobreak="false">xs:untypedAtomic</code>
               values (which typically result from atomizing a node) are treated as strings.</p>
                     </note>
                  </item>
                  <item>
                     <p>If <function>fn:compare</function> raises an error (typically because
               the two operands belong to different 
                  <xtermref spec="DM40" ref="dt-type-family">type families</xtermref>),
               then the value comparison fails with that error.</p>
                  </item>
                  <item>
                     <p>The result of the <function>fn:compare</function> function determines
               the result of the value comparison, according to the following table:</p>
                     <table>
                        <caption>Result of a Value Comparison</caption>
                        <thead>
                           <tr>
                              <th rowspan="1" colspan="1">Result of <function>fn:compare</function>
                              </th>
                              <th rowspan="1" colspan="1">
                                 <code nobreak="false">eq</code>
                              </th>
                              <th rowspan="1" colspan="1">
                                 <code nobreak="false">ne</code>
                              </th>
                              <th rowspan="1" colspan="1">
                                 <code nobreak="false">lt</code>
                              </th>
                              <th rowspan="1" colspan="1">
                                 <code nobreak="false">le</code>
                              </th>
                              <th rowspan="1" colspan="1">
                                 <code nobreak="false">gt</code>
                              </th>
                              <th rowspan="1" colspan="1">
                                 <code nobreak="false">ge</code>
                              </th>
                           </tr>
                        </thead>
                        <tbody>
                           <tr>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">-1</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">false</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">true</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">true</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">true</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">false</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">false</code>
                              </td>
                           </tr>
                           <tr>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">0</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">true</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">false</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">false</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">true</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">false</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">true</code>
                              </td>
                           </tr>
                           <tr>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">+1</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">false</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">true</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">false</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">false</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">true</code>
                              </td>
                              <td rowspan="1" colspan="1">
                                 <code nobreak="false">true</code>
                              </td>
                           </tr>
                        </tbody>
                     </table>
                  </item>
               </olist>
               <!--<item>
                  <p>Expressions using operators other than <code>eq</code> and <code>lt</code>
                  are rewritten as follows:</p>
                  <slist>
                     <sitem><code>A ne B</code> becomes <code>not(A eq B)</code></sitem>
                     <sitem><code>A le B</code> becomes <code>A lt B or A eq B</code></sitem>
                     <sitem><code>A gt B</code> becomes <code>B lt A</code></sitem>
                     <sitem><code>A ge B</code> becomes <code>B lt A or B eq A</code></sitem>
                  </slist>
               </item>-->
               <!--<item>
                  <p>If the types of the two operands correspond to an entry
                     in the table below, the operator is applied to the
                     operands by applying the appropriate function from the table.</p>
                  
                  <p>If the table contains no entry corresponding to the types of the operands, 
               then a <termref def="dt-type-error"
                  >type error</termref>
is raised <errorref class="TY" code="0004"/>.</p>
               </item>

            </olist>
            
            
           <table border="1" role="small">
<caption>Value Comparison Operators</caption>
<tbody>

<tr>
<th>Expression</th>
<th>Type(A)</th>
<th>Type(B)</th>
<th>Function</th>
</tr>



<tr><td>A eq B</td><td>xs:numeric</td><td>xs:numeric</td>
   <td><function>op:numeric-equal</function><code>(A, B)</code></td></tr>

<tr><td>A eq B</td><td>xs:boolean</td><td>xs:boolean</td><td><function>op:boolean-equal</function><code>(A, B)</code></td></tr>

<tr><td>A eq B</td><td>xs:string</td><td>xs:string</td><td>
   <code>fn:atomic-equal(fn:compare(A, B), 0)</code></td></tr>

<tr><td>A eq B</td><td>xs:date</td><td>xs:date</td><td><function>op:date-equal</function><code>(A, B)</code></td></tr>

<tr><td>A eq B</td><td>xs:time</td><td>xs:time</td><td><function>op:time-equal</function><code>(A, B)</code></td></tr>

<tr><td>A eq B</td><td>xs:dateTime</td><td>xs:dateTime</td><td><function>op:dateTime-equal</function><code>(A, B)</code></td></tr>

<tr><td>A eq B</td><td>xs:duration</td><td>xs:duration</td><td><function>op:duration-equal</function><code>(A, B)</code></td></tr>

<tr><td>A eq B</td><td>xs:gYear</td><td>xs:gYear</td><td><function>op:gYear-equal</function><code>(A, B)</code></td></tr>
<tr><td>A eq B</td><td>xs:gYearMonth</td><td>xs:gYearMonth</td><td><function>op:gYearMonth-equal</function><code>(A, B)</code></td></tr>
<tr><td>A eq B</td><td>xs:gMonth</td><td>xs:gMonth</td><td><function>op:gMonth-equal</function><code>(A, B)</code></td></tr>
<tr><td>A eq B</td><td>xs:gMonthDay</td><td>xs:gMonthDay</td><td><function>op:gMonthDay-equal</function><code>(A, B)</code></td></tr>
<tr><td>A eq B</td><td>xs:gDay</td><td>xs:gDay</td><td><function>op:gDay-equal</function><code>(A, B)</code></td></tr>

<tr><td>A eq B</td><td>(xs:hexBinary | xs:base64Binary)</td><td>(xs:hexBinary | xs:base64Binary)</td><td><function>op:binary-equal</function><code>(A, B)</code></td></tr>


<tr><td>A eq B</td><td>xs:QName</td><td>xs:QName</td><td><function>op:QName-equal</function><code>(A, B)</code></td></tr>

<tr><td>A eq B</td><td>xs:NOTATION</td><td>xs:NOTATION</td><td><function>op:NOTATION-equal</function><code>(A, B)</code></td></tr>




<tr><td>A lt B</td><td>xs:numeric</td><td>xs:numeric</td>
   <td><function>op:numeric-less-than</function><code>(A, B)</code></td></tr>

<tr><td>A lt B</td><td>xs:boolean</td><td>xs:boolean</td><td><function>op:boolean-less-than</function><code>(A, B)</code></td></tr>

<tr><td>A lt B</td><td>xs:string</td><td>xs:string</td><td>
   <code>fn:atomic-equal(fn:compare(A, B), -1)</code></td></tr>

<tr><td>A lt B</td><td>xs:date</td><td>xs:date</td><td><function>op:date-less-than</function><code>(A, B)</code></td></tr>

<tr><td>A lt B</td><td>xs:time</td><td>xs:time</td><td><function>op:time-less-than</function><code>(A, B)</code></td></tr>

<tr><td>A lt B</td><td>xs:dateTime</td><td>xs:dateTime</td><td><function>op:dateTime-less-than</function><code>(A, B)</code></td></tr>

<tr><td>A lt B</td><td>xs:yearMonthDuration</td><td>xs:yearMonthDuration</td><td><function>op:yearMonthDuration-less-than</function><code>(A, B)</code></td></tr>
<tr><td>A lt B</td><td>xs:dayTimeDuration</td><td>xs:dayTimeDuration</td><td><function>op:dayTimeDuration-less-than</function><code>(A, B)</code></td></tr>
<tr><td>A lt B</td><td>(xs:hexBinary | xs:base64Binary)</td><td>(xs:hexBinary | xs:base64Binary)</td><td><function>op:binary-less-than</function><code>(A, B)</code></td></tr>




</tbody>
</table>


            <p>The definitions of the operator functions are found in <bibref
                  ref="xpath-functions-40"/>.</p>

 
            <note>
               <p>Comparison of strings is defined
               by reference to the specification of the <function>fn:compare</function>
                  function with two arguments; this implies that the comparison is performed
                  using the <termref def="dt-def-collation"/> from the
                  <termref def="dt-static-context"/>.</p>
            </note>-->
               <p>Here are some examples of value comparisons:</p>
               <ulist>
                  <item>
                     <p>The following comparison atomizes the node(s) that are returned 
                     by the expression <code nobreak="false">$book/author</code>. The comparison is true 
                     only if the result of atomization is the value "Kennedy" as an 
                     instance of <code nobreak="false">xs:string</code> or <code nobreak="false">xs:untypedAtomic</code>. 
                     If the result of atomization is the empty sequence, the result of 
                     the comparison is the empty sequence. If the result of atomization 
                     is a sequence containing more than one value, a <termref def="dt-type-error">type error</termref> is raised <errorref class="TY" code="0004"/>.</p>
                     <eg role="parse-test" xml:space="preserve">$book1/author eq "Kennedy"</eg>
                  </item>
                  <item>
                     <p>The following comparison is <code nobreak="false">true</code> because atomization 
                     converts an array to its member sequence:</p>
                     <eg role="parse-test" xml:space="preserve">[ "Kennedy" ] eq "Kennedy"</eg>
                  </item>
                  <item>
                     <p>The following <termref def="dt-path-expression">path expression</termref> contains a predicate that selects 
                     products whose weight is greater than 100. For any product that 
                     does not have a <code nobreak="false">weight</code> subelement, the value of the 
                     predicate is the empty sequence, and the product is not selected. 
                     This example assumes that <code nobreak="false">weight</code> is a validated element 
                     with a numeric type.</p>
                     <eg role="parse-test" xml:space="preserve">//product[weight gt 100]</eg>
                  </item>
                  <item>
                     <p>The following comparison is true if <code nobreak="false">my:hatsize</code> and 
                     <code nobreak="false">my:shoesize</code> are both user-defined types that are derived 
                     by restriction from a primitive <termref def="dt-numeric">numeric</termref> type:</p>
                     <eg role="parse-test" xml:space="preserve">my:hatsize(5) eq my:shoesize(5)</eg>
                  </item>
                  <item>
                     <p>The following comparison is true. The <code nobreak="false">eq</code> operator compares 
                     two QNames by performing codepoint-comparisons of their namespace URIs 
                     and their local names, ignoring their namespace prefixes.</p>
                     <eg role="parse-test" xml:space="preserve">QName("http://example.com/ns1", "this:color") eq
QName("http://example.com/ns1", "that:color")</eg>
                  </item>
                  <item>
                     <p>The following comparison is false. The <code nobreak="false">xs:double</code> value
                  <code nobreak="false">1.1e0</code> is converted to type <code nobreak="false">xs:decimal</code>, giving
                  the result <code nobreak="false">1.100000000000000088817841970012523233890533447265625</code>, 
                  which is not equal to the <code nobreak="false">xs:decimal</code> value <code nobreak="false">1.1</code>.</p>
                     <eg role="parse-test" xml:space="preserve">1.1 eq 1.1e0</eg>
                     <note>
                        <p>This is incompatible with previous versions, which converted
                  both operands to <code nobreak="false">xs:double</code> 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.</p>
                     </note>
                  </item>
               </ulist>
            </div3>
            <div3 id="id-general-comparisons">
               <head>General Comparisons</head>
               <changes>
                  <change issue="986" PR="2218" date="2025-09-29">The rules for comparing untyped atomic items with numeric values have changed. 
                  Rather than converting an untyped atomic item unconditionally to <code nobreak="false">xs:double</code>,
                  it is now converted to the type of the numeric operand. This is designed to ensure that
                  comparisons such as <code nobreak="false">&lt;a&gt;1.1&lt;/a&gt; = 1.1</code> succeed, given that the values
                  will now be compared as decimals rather than as doubles.</change>
               </changes>
               <p>The general comparison operators are <code nobreak="false">=</code>, <code nobreak="false">!=</code>, <code nobreak="false">&lt;</code>, <code nobreak="false">&lt;=</code>, <code nobreak="false">&gt;</code>, and <code nobreak="false">&gt;=</code>. General comparisons are existentially quantified comparisons that may be applied to operand sequences of any length. The result of a general comparison that does not raise an error is
always <code nobreak="false">true</code> or <code nobreak="false">false</code>.</p>
               <p role="xpath">If <termref def="dt-xpath-compat-mode">XPath 1.0 compatibility mode</termref> is <code nobreak="false">true</code>, a general 
               comparison is evaluated by applying the following rules, in order:</p>
               <olist role="xpath">
                  <item>
                     <p>If either operand is a single atomic item that is an instance of
<code nobreak="false">xs:boolean</code>, then the other operand is converted to <code nobreak="false">xs:boolean</code> by taking its
<termref def="dt-ebv">effective boolean value</termref>.</p>
                  </item>
                  <item>
                     <p>
                        <termref def="dt-atomization">Atomization</termref> is applied to each operand. After atomization, 
                     each operand is a sequence of atomic items.</p>
                  </item>
                  <item>
                     <p>If the comparison operator is <code nobreak="false">&lt;</code>, <code nobreak="false">&lt;=</code>, <code nobreak="false">&gt;</code>, or <code nobreak="false">&gt;=</code>, then each item in both of the
operand sequences is converted to the type  <code nobreak="false">xs:double</code> by applying the
<function>fn:number</function> function. (Note that <function>fn:number</function> returns the value <code nobreak="false">NaN</code> if its operand cannot be converted to a number.)</p>
                  </item>
                  <item>
                     <p>The result of the comparison is <code nobreak="false">true</code> if and only if there is a pair of
atomic items, one in the first operand sequence and the other in the second operand sequence, that have the required
<term>magnitude relationship</term>. Otherwise the result of the  comparison is
<code nobreak="false">false</code> or an error. The <term>magnitude relationship</term> between two atomic items is determined by
applying the following rules. If a <code nobreak="false">cast</code> operation called for by these rules is not successful, a <termref def="dt-dynamic-error">dynamic error</termref>  is raised. <xerrorref spec="FO40" class="RG" code="0001"/>
                     </p>
                     <olist>
                        <item>
                           <p>If at least one of the two atomic items is an instance of a <termref def="dt-numeric">numeric</termref> type, then both atomic items are converted to the type <code nobreak="false">xs:double</code> by
applying the <function>fn:number</function> function.</p>
                        </item>
                        <item>
                           <p>If at least one of the two atomic items is an instance of <code nobreak="false">xs:string</code>,
or if both atomic items are instances of <code nobreak="false">xs:untypedAtomic</code>, then both
atomic items are cast to the type <code nobreak="false">xs:string</code>.</p>
                        </item>
                        <item>
                           <p>If one of the atomic items is an instance of <code nobreak="false">xs:untypedAtomic</code> and the other is not an instance of <code nobreak="false">xs:string</code>, <code nobreak="false">xs:untypedAtomic</code>, or any <termref def="dt-numeric">numeric</termref> type, then the <code nobreak="false">xs:untypedAtomic</code> item is
                            cast to the base primitive type (<code nobreak="false">xs:decimal</code>, <code nobreak="false">xs:double</code>, 
                           or <code nobreak="false">xs:float</code>) of the <termref def="dt-dynamic-type">dynamic type</termref> of the other value.</p>
                        </item>
                        <item>
                           <p>After performing the conversions described above, the atomic items are
compared using one of the value comparison operators <code nobreak="false">eq</code>, <code nobreak="false">ne</code>, <code nobreak="false">lt</code>, <code nobreak="false">le</code>, <code nobreak="false">gt</code>, or
<code nobreak="false">ge</code>, depending on whether the general comparison operator was <code nobreak="false">=</code>, <code nobreak="false">!=</code>, <code nobreak="false">&lt;</code>, <code nobreak="false">&lt;=</code>,
<code nobreak="false">&gt;</code>, or <code nobreak="false">&gt;=</code>. The values have the required <term>magnitude relationship</term> if and only if the result
of this value comparison is <code nobreak="false">true</code>.</p>
                        </item>
                     </olist>
                  </item>
               </olist>
               <p>
                  <phrase role="xpath">If <termref def="dt-xpath-compat-mode">XPath 1.0 compatibility mode</termref> is <code nobreak="false">false</code>, a</phrase>
                general comparison is evaluated by applying the following rules, in order:</p>
               <olist>
                  <item>
                     <p>
                        <termref def="dt-atomization">Atomization</termref> is applied to each operand. After atomization, each 
                     operand is a sequence of atomic items.</p>
                  </item>
                  <item>
                     <p>The result of the comparison is <code nobreak="false">true</code> if and only if there is a pair of
atomic items, one in the first operand sequence and the other in the second operand sequence, that have the required
<term>magnitude relationship</term>. Otherwise the result of the  comparison is
<code nobreak="false">false</code> or an error. The <term>magnitude relationship</term> between two atomic items is determined by
applying the following rules. If a <code nobreak="false">cast</code> operation called for by these rules is not successful, a <termref def="dt-dynamic-error">dynamic error</termref>  is raised. <xerrorref spec="FO40" class="RG" code="0001"/>
                     </p>
                     <olist>
                        <item>
                           <p>If both atomic items are instances of <code nobreak="false">xs:untypedAtomic</code>,
                then the values are cast to the type <code nobreak="false">xs:string</code>.
             </p>
                        </item>
                        <item>
                           <p>If exactly one of the atomic items is an instance of
                <code nobreak="false">xs:untypedAtomic</code>, it is cast to a type depending on
                the other value’s dynamic type <var>T</var> according to the following rules,
                in which <var>V</var> denotes the value to be cast:
             </p>
                           <olist>
                              <item>
                                 <p>If <var>T</var> is a numeric type or is derived from a numeric type,
                      then <var>V</var> is cast first to the primitive base type of <var>T</var>
                                 (one of <code nobreak="false">xs:decimal</code>, <code nobreak="false">xs:double</code>,
                                 or <code nobreak="false">xs:float</code>); or if that fails, to <code nobreak="false">xs:double</code>.</p>
                                 <note>
                                    <p>Casting to <code nobreak="false">xs:decimal</code> might fail if <var>V</var>
                              uses exponential notation or is positive or negative infinity. Casting to
                              <code nobreak="false">xs:float</code> might fail because of numeric overflow.</p>
                                 </note>
                              </item>
                              <!--<item>
                              <p>If <var>T</var> is <code>xs:dayTimeDuration</code> or is derived from
                      <code>xs:dayTimeDuration</code>,
                      then <var>V</var> is cast to <code>xs:dayTimeDuration</code>.</p>
                           </item>
                           <item>
                              <p>If <var>T</var> is <code>xs:yearMonthDuration</code> or is derived from
                      <code>xs:yearMonthDuration</code>,
                      then <var>V</var> is cast to <code>xs:yearMonthDuration</code>.</p>
                           </item>-->
                              <item>
                                 <p>In all other cases, <var>V</var> is cast to the primitive base type of <var>T</var>.</p>
                              </item>
                           </olist>
                           <!--<note>
                           <p>
                The special treatment of the duration types is required to avoid
                errors that may arise when comparing the primitive type
                <code>xs:duration</code> with any duration type.
             </p>
                        </note>-->
                        </item>
                        <item>
                           <p>After performing the conversions described above, the atomic items are
compared using one of the value comparison operators <code nobreak="false">eq</code>, <code nobreak="false">ne</code>, <code nobreak="false">lt</code>, <code nobreak="false">le</code>, <code nobreak="false">gt</code>, or
<code nobreak="false">ge</code>, depending on whether the general comparison operator was <code nobreak="false">=</code>, <code nobreak="false">!=</code>, <code nobreak="false">&lt;</code>, <code nobreak="false">&lt;=</code>,
<code nobreak="false">&gt;</code>, or <code nobreak="false">&gt;=</code>. The values have the required <term>magnitude relationship</term> if and only if the result
of this value comparison is <code nobreak="false">true</code>.</p>
                        </item>
                     </olist>
                  </item>
               </olist>
               <p>When evaluating a general comparison in which either operand is a sequence of items, 
               an implementation may return <code nobreak="false">true</code> as soon as it finds an item in the 
               first operand and an item in the second operand that have the required 
               <term>magnitude relationship</term>. Similarly, a general comparison may raise a <termref def="dt-dynamic-error">dynamic error</termref> as soon as it encounters an error in evaluating 
               either operand, or in comparing a pair of items from the two operands. 
               As a result of these rules, the result of a general comparison is not 
               deterministic in the presence of errors.</p>
               <p>Here are some examples of general comparisons:</p>
               <ulist>
                  <item>
                     <p>The following comparison is true if the <termref def="dt-typed-value">typed value</termref> of any
<code nobreak="false">author</code> child element of <code nobreak="false">$book1</code> is "Kennedy" as an instance of <code nobreak="false">xs:string</code> or <code nobreak="false">xs:untypedAtomic</code>:</p>
                     <eg role="parse-test" xml:space="preserve">$book1/author = "Kennedy"</eg>
                  </item>
                  <item>
                     <p>The following comparison is true if the <termref def="dt-typed-value">typed value</termref> of any
<code nobreak="false">price</code> child element of <code nobreak="false">$book1</code> is (say) <code nobreak="false">"8.95"</code> as an instance of 
                     <code nobreak="false">xs:untypedAtomic</code>:</p>
                     <eg role="parse-test" xml:space="preserve">$book1/price &gt; 8.50</eg>
                     <p>Because the operand <code nobreak="false">8.50</code> is expressed as an <code nobreak="false">xs:decimal</code>,
                  the <code nobreak="false">xs:untypedAtomic</code> value of the element node is converted
                  to type <code nobreak="false">xs:decimal</code>, and the two <code nobreak="false">xs:decimal</code>
                  values are compared.</p>
                  </item>
                  <item>
                     <p>Given the input <code nobreak="false">&lt;item price="10.30"/&gt;</code>, the expression 
                  <code nobreak="false">@discount != "25%"</code> returns false, because there is no 
                  <code nobreak="false">discount</code> attribute that meets the specified criteria. By contrast,
                  the expression <code nobreak="false">not(@discount = "25%")</code> returns true.</p>
                  </item>
                  <item>
                     <p>The following comparison is <code nobreak="false">true</code> because atomization converts an array to its member sequence:</p>
                     <eg role="parse-test" xml:space="preserve">[ "Obama", "Nixon", "Kennedy" ] = "Kennedy"</eg>
                  </item>
                  <item>
                     <p>The following example contains three general comparisons. The value of the first two 
                     comparisons is <code nobreak="false">true</code>, and the value of the third comparison is 
                     <code nobreak="false">false</code>. This example illustrates the fact that general comparisons are not transitive.</p>
                     <eg xml:space="preserve">(1, 2) = (2, 3)
(2, 3) = (3, 4)
(1, 2) = (3, 4)</eg>
                  </item>
                  <item>
                     <p>The following example contains two general comparisons, both of which are <code nobreak="false">true</code>. 
                     This example illustrates the fact that the <code nobreak="false">=</code> and <code nobreak="false">!=</code> operators 
                     are not inverses of each other.</p>
                     <eg xml:space="preserve">(1, 2) = (2, 3)
(1, 2) != (2, 3)</eg>
                  </item>
                  <item>
                     <p>Suppose that <code nobreak="false">$a</code>, <code nobreak="false">$b</code>, and <code nobreak="false">$c</code> are bound to 
                     element nodes with type annotation <code nobreak="false">xs:untypedAtomic</code>, with <termref def="dt-string-value">string values</termref>
                        <code nobreak="false">"1"</code>, <code nobreak="false">"2"</code>, and <code nobreak="false">"2.0"</code> respectively. 
                     Then <code role="parse-test" nobreak="false">($a, $b) = ($c, 3.0)</code> returns <code nobreak="false">false</code>, because 
                     <code nobreak="false">$b</code> and <code nobreak="false">$c</code> are compared as strings. However, <code role="parse-test" nobreak="false">($a, $b) = ($c, 2.0)</code> returns <code nobreak="false">true</code>, 
                     because <code nobreak="false">$b</code> and <code nobreak="false">2.0</code> are compared as <code nobreak="false">xs:decimal</code> numbers.</p>
                  </item>
               </ulist>
            </div3>
            <div3 id="id-node-comparisons">
               <head>GNode Comparisons</head>
               <changes>
                  <change date="2025-07-28" PR="2130">
                  Operator <code nobreak="false">is-not</code> is introduced, as a complement to the operator <code nobreak="false">is</code>.
               </change>
                  <change date="2025-07-28" PR="2130">
                  Operators <code nobreak="false">precedes</code> and <code nobreak="false">follows</code> are introduced as synonyms
                  for operators <code nobreak="false">&lt;&lt;</code> and <code nobreak="false">&gt;&gt;</code>.
               </change>
                  <change date="2025-08-22" PR="2176">
                  Operators <code nobreak="false">precedes-or-is</code> and <code nobreak="false">follows-or-is</code> are introduced as synonyms
                  for the union of operators <code nobreak="false">&lt;&lt;</code> and <code nobreak="false">is</code> and for the union of 
                  operators <code nobreak="false">&gt;&gt;</code> and <code nobreak="false">is</code>, respectively.
               </change>
               </changes>
               <p>GNode comparisons are used to compare two <termref def="dt-GNode">GNodes</termref>

               (that is, <termref def="dt-XNode">XNodes</termref> or
               <xtermref spec="DM40" ref="dt-JNode">JNodes</xtermref>), by their identity or by their <termref def="dt-document-order">document order</termref>. The result of a GNode comparison is defined by the following rules:</p>
               <olist>
                  <item>
                     <p>The operands of a <termref def="dt-GNode"/> comparison are evaluated in <termref def="dt-implementation-dependent">implementation-dependent</termref> order.</p>
                  </item>
                  <item>
                     <p>If either operand is the empty sequence, the result of the
    comparison is the 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.</p>
                  </item>
                  <item>
                     <p> Each operand must be either a single <termref def="dt-GNode"/> or the empty sequence; otherwise
a <termref def="dt-type-error">type error</termref> is raised <errorref class="TY" code="0004"/>.</p>
                  </item>
                  <item>
                     <p>A comparison with the <code nobreak="false">is</code> operator is <code nobreak="false">true</code> if 
                     the values of two operands are the same GNode; otherwise it
is <code nobreak="false">false</code>. See <bibref ref="xpath-datamodel-40"/> for  the definition of GNode identity.</p>
                  </item>
                  <item>
                     <p>A comparison with the <code nobreak="false">is-not</code> operator is <code nobreak="false">false</code> if 
                     the values of two operands are the same GNode; otherwise it
is <code nobreak="false">true</code>. See <bibref ref="xpath-datamodel-40"/> for  the definition of GNode identity.</p>
                  </item>
                  <item>
                     <p>A comparison with the <code nobreak="false">&lt;&lt;</code> or <code nobreak="false">precedes</code> operator returns <code nobreak="false">true</code> 
                     if the left operand <termref def="dt-GNode"/> precedes the right operand GNode in

<termref def="dt-document-order">document order</termref>; otherwise it returns <code nobreak="false">false</code>.</p>
                  </item>
                  <item>
                     <p>A comparison with the <code nobreak="false">&gt;&gt;</code> or <code nobreak="false">follows</code> operator returns 
                     <code nobreak="false">true</code> if the left operand GNode follows the right operand GNode in
<termref def="dt-document-order">document order</termref>; otherwise it returns <code nobreak="false">false</code>.</p>
                  </item>
                  <item>
                     <p>A comparison with the <code nobreak="false">precedes-or-is</code> operator returns <code nobreak="false">true</code> 
                     if the left operand <termref def="dt-GNode"/> precedes the right operand GNode in
                     
                     <termref def="dt-document-order">document order</termref> or if the values of two operands 
                     are the same GNode; otherwise it returns <code nobreak="false">false</code>.</p>
                  </item>
                  <item>
                     <p>A comparison with the <code nobreak="false">follows-or-is</code> operator returns <code nobreak="false">true</code> 
                     if the left operand <termref def="dt-GNode"/> follows the right operand GNode in
                     
                     <termref def="dt-document-order">document order</termref> or if the values of two operands 
                     are the same GNode; otherwise it returns <code nobreak="false">false</code>.</p>
                  </item>
               </olist>
               <p>Here are some examples of GNode comparisons:</p>
               <ulist>
                  <item>
                     <p>The following comparison is true only if the left and right sides each
evaluate to exactly the same single node:</p>
                     <eg role="parse-test" xml:space="preserve">/books/book[isbn = "1558604820"] is /books/book[call = "QA76.9 C3845"]</eg>
                  </item>
                  <item>
                     <p>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:</p>
                     <eg role="parse-test" xml:space="preserve">/transactions/purchase[parcel = "28-451"] &lt;&lt; /transactions/sale[parcel = "33-870"]</eg>
                  </item>
                  <item>
                     <p>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:</p>
                     <eg role="parse-test" xml:space="preserve">let $A := ["Q", 3, "E", "R", "T", 5, "Y"]
return $A ? child::type(xs:integer)[1] precedes $A ? child::type(xs:string)[1]</eg>
                  </item>
               </ulist>
            </div3>
         </div2>
         <div2 id="id-logical-expressions">
            <head>Logical Expressions</head>
            <changes>
               <change issue="71 2132" PR="230" date="2022-11-15">
                  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 <code nobreak="false">and</code> and <code nobreak="false">or</code>,
                  and of predicates in filter expressions, in a way that might allow the processor to raise dynamic
                  errors that the author intended to prevent.
               </change>
            </changes>
            <p>
               <termdef id="dt-logical-expression" term="logical expression">
            A <term>logical expression</term> is either an <termref def="dt-and-expression"/>
            or an <termref def="dt-or-expression"/>. If a logical expression does not raise an error, 
            its value is always one of the boolean values <code nobreak="false">true</code> or <code nobreak="false">false</code>.</termdef>
            </p>
            <scrap headstyle="show">
               <prod id="doc-xpath40-OrExpr">
                  <lhs>OrExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-AndExpr">AndExpr<!--$idref_lang_part = xpath40- --></nt>  ("or"  <nt def="prod-xpath40-AndExpr">AndExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
               </prod>

               <prod id="doc-xpath40-OrExpr-AndExpr">
                  <lhs>AndExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-ComparisonExpr">ComparisonExpr<!--$idref_lang_part = xpath40- --></nt>  ("and"  <nt def="prod-xpath40-ComparisonExpr">ComparisonExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
               </prod>

               <prod id="doc-xpath40-OrExpr-ComparisonExpr">
                  <lhs>ComparisonExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-OtherwiseExpr">OtherwiseExpr<!--$idref_lang_part = xpath40- --></nt>  ((<nt def="prod-xpath40-ValueComp">ValueComp<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-GeneralComp">GeneralComp<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-NodeComp">NodeComp<!--$idref_lang_part = xpath40- --></nt>)  <nt def="prod-xpath40-OtherwiseExpr">OtherwiseExpr<!--$idref_lang_part = xpath40- --></nt>)?</rhs>
               </prod>
            </scrap>
            <p>
               <termdef id="dt-and-expression" term="and expression">An <term>and expression</term>
         is a <termref def="dt-non-trivial"/> instance of the production <nt def="prod-xpath40-AndExpr">AndExpr<!--$spec = xpath40--></nt>.</termdef>
            </p>
            <p>
               <termdef id="dt-or-expression" term="or expression">An <term>or expression</term>
         is a <termref def="dt-non-trivial"/> instance of the production <nt def="doc-xpath40-OrExpr">OrExpr<!--$spec = xpath40--></nt>.</termdef>
            </p>
            <p>In the absence of errors, an <termref def="dt-and-expression"/> returns <code nobreak="false">true</code>
            when both of its operands have an <termref def="dt-ebv"/> of <code nobreak="false">true</code>, while an
            <termref def="dt-or-expression"/> returns <code nobreak="false">true</code> when either or both of its operands have
            an <termref def="dt-ebv"/> of <code nobreak="false">true</code>.</p>
            <p>The rules for error handling follow the principles defined in <specref ref="id-guarded-expressions"/>.
         Specifically, an <termref def="dt-and-expression"/> returns false if the first operand has an 
         <termref def="dt-ebv"/> of <code nobreak="false">false</code>, whether or not evaluation of the second
         operand raises an error; while an <termref def="dt-or-expression"/> returns true if the first operand has an 
         <termref def="dt-ebv"/> of <code nobreak="false">true</code>, whether or not evaluation of the second
         operand raises an error.</p>
            <note>
               <p>This rule is consistent with the so-called “short-circuit” evaluation of
         logical operators defined in some procedural programming languages. However, unlike many
         such languages, the rule is concerned only with error behavior, and not with side-effects.
         A processor may evaluate the operands of a logical expression in any order, or in parallel,
         provided that the error semantics are respected. For example, an optimizer may choose to
         evaluate the second operand before evaluating the first, provided that any error in doing so
         is masked when the result can be determined from the value of the first operand.</p>
            </note>
            <p>The value of an <termref def="dt-and-expression"/> is determined by the effective
          boolean values (EBVs) of its operands, as shown in the following table:</p>
            <table role="medium" width="80%" border="1">
               <tbody>
                  <tr>
                     <th rowspan="1" colspan="1">AND:</th>
                     <th rowspan="1" colspan="1">EBV<sub>2</sub> =
<code nobreak="false">true</code>
                     </th>
                     <th rowspan="1" colspan="1">EBV<sub>2</sub> = <code nobreak="false">false</code>
                     </th>
                     <th rowspan="1" colspan="1">error in EBV<sub>2</sub>
                     </th>
                  </tr>
                  <tr>
                     <th rowspan="1" colspan="1">EBV<sub>1</sub> =
<code nobreak="false">true</code>
                     </th>
                     <td rowspan="1" colspan="1">
                        <code nobreak="false">true</code>
                     </td>
                     <td rowspan="1" colspan="1">
                        <code nobreak="false">false</code>
                     </td>
                     <td rowspan="1" colspan="1">error</td>
                  </tr>
                  <tr>
                     <th rowspan="1" colspan="1">EBV<sub>1</sub>
= <code nobreak="false">false</code>
                     </th>
                     <td rowspan="1" colspan="1">
                        <code nobreak="false">false</code>
                     </td>
                     <td rowspan="1" colspan="1">
                        <code nobreak="false">false</code>
                     </td>
                     <td rowspan="1" colspan="1">
                        <code nobreak="false">false</code>
                     </td>
                  </tr>
                  <tr>
                     <th rowspan="1" colspan="1">error in EBV<sub>1</sub>
                     </th>
                     <td rowspan="1" colspan="1">error</td>
                     <td rowspan="1" colspan="1">error</td>
                     <td rowspan="1" colspan="1">error</td>
                  </tr>
               </tbody>
            </table>
            <p>The value of an
<termref def="dt-or-expression"/> is determined by the effective boolean values (EBVs) of
its operands, as shown in
the following table:</p>
            <table role="medium" width="80%" border="1">
               <tbody>
                  <tr>
                     <th rowspan="1" colspan="1">OR:</th>
                     <th rowspan="1" colspan="1">EBV<sub>2</sub> =
<code nobreak="false">true</code>
                     </th>
                     <th rowspan="1" colspan="1">EBV<sub>2</sub> = <code nobreak="false">false</code>
                     </th>
                     <th rowspan="1" colspan="1">error in
EBV<sub>2</sub>
                     </th>
                  </tr>
                  <tr>
                     <th rowspan="1" colspan="1">EBV<sub>1</sub> =
<code nobreak="false">true</code>
                     </th>
                     <td rowspan="1" colspan="1">
                        <code nobreak="false">true</code>
                     </td>
                     <td rowspan="1" colspan="1">
                        <code nobreak="false">true</code>
                     </td>
                     <td rowspan="1" colspan="1">
                        <code nobreak="false">true</code>
                     </td>
                  </tr>
                  <tr>
                     <th rowspan="1" colspan="1">EBV<sub>1</sub> =
<code nobreak="false">false</code>
                     </th>
                     <td rowspan="1" colspan="1">
                        <code nobreak="false">true</code>
                     </td>
                     <td rowspan="1" colspan="1">
                        <code nobreak="false">false</code>
                     </td>
                     <td rowspan="1" colspan="1">error</td>
                  </tr>
                  <tr>
                     <th rowspan="1" colspan="1">error
in EBV<sub>1</sub>
                     </th>
                     <td rowspan="1" colspan="1">error</td>
                     <td rowspan="1" colspan="1">error</td>
                     <td rowspan="1" colspan="1">error</td>
                  </tr>
               </tbody>
            </table>
            <note>
               <p>XPath 1.0 defined the order of evaluation for 
               <termref def="dt-and-expression">and-expressions</termref> and 
               <termref def="dt-or-expression">or-expressions</termref>, thus ensuring
               “short-circuit” semantics. XPath 2.0 and XQuery 1.0 changed the rules
               to allow operands to be evaluated in either order, in the interests
               of optimization, while retaining “short-circuit” semantics when
               running XPath in 1.0 compatibility mode. The same rules were retained in
               the 3.0 and 3.1 versions of the specifications.</p>
               <p>The disadvantage
               of that formulation was that it was not possible to use the first operand
               of a logical expression to guard against dynamic errors in the second;
               for example the expression <code nobreak="false">$n instance of node() and exists($n/*)</code>
               might legitimately fail in the case where <code nobreak="false">$n</code> is not a node.</p>
               <p>The 4.0 specification therefore guarantees that this expression will not fail;
               but it does so without mandating an order of evaluation for the operands. Instead
               it mandates only that any error in evaluating the second operand (<code nobreak="false">exists($n/*)</code>)
               is masked if the first operand (<code nobreak="false">$n instance of node()</code>) is false.
            </p>
            </note>
            <p>Here are some examples of logical expressions:</p>
            <ulist>
               <item>
                  <p>The following expressions return
<code nobreak="false">true</code>:</p>
                  <eg role="parse-test" xml:space="preserve">1 eq 1 and 2 eq 2</eg>
                  <eg role="parse-test" xml:space="preserve">1 eq 1 or 2 eq 3</eg>
               </item>
               <item>
                  <p>The following returns <code nobreak="false">false</code>: it is not allowed to
               raise an error.</p>
                  <eg role="parse-test" xml:space="preserve">1 eq 2 and 3 idiv 0 = 1</eg>
               </item>
               <item>
                  <p>The following expression returns <code nobreak="false">true</code>: it is not allowed to
               raise an error.</p>
                  <eg role="parse-test" xml:space="preserve">1 eq 1 or 3 idiv 0 = 1</eg>
               </item>
               <item>
                  <p>The
following expression must raise a <termref def="dt-dynamic-error">dynamic error</termref>:</p>
                  <eg role="parse-test" xml:space="preserve">1 eq 1 and 3 idiv 0 = 1</eg>
               </item>
            </ulist>
            <p>In addition to and- and or-expressions, XPath 4.0 provides a
function named <function>fn:not</function> that takes a general sequence as
parameter and returns a boolean value.  The <function>fn:not</function> function
is defined in <bibref ref="xpath-functions-40"/>. The
<function>fn:not</function> function reduces its parameter to an <termref def="dt-ebv">effective boolean value</termref>. It then returns
<code nobreak="false">true</code> if the effective boolean value of its parameter is
<code nobreak="false">false</code>, and <code nobreak="false">false</code> if the effective boolean
value of its parameter is <code nobreak="false">true</code>. If an error is
encountered in finding the effective boolean value of its operand,
<function>fn:not</function> raises the same error.</p>
         </div2>
         <div2 id="id-constructors">
            <head>Node Constructors</head>
            <changes>
               <change issue="2427" PR="2446" date="2026-02-07">
               Computed node constructors are now available in XPath as well as XQuery.
            </change>
            </changes>
            <p>XPath 4.0 provides node constructors that can create XML nodes within a query.</p>
            <scrap headstyle="show">
               <prod id="doc-xpath40-NodeConstructor">
                  <lhs>NodeConstructor</lhs>
                  <rhs>
                     <nt def="prod-xpath40-ComputedConstructor">ComputedConstructor<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-NodeConstructor-ComputedConstructor">
                  <lhs>ComputedConstructor</lhs>
                  <rhs>
                     <nt def="prod-xpath40-CompDocConstructor">CompDocConstructor<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-CompElemConstructor">CompElemConstructor<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-CompAttrConstructor">CompAttrConstructor<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-CompNamespaceConstructor">CompNamespaceConstructor<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-CompTextConstructor">CompTextConstructor<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-CompCommentConstructor">CompCommentConstructor<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-CompPIConstructor">CompPIConstructor<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>
            </scrap>
            <p>Constructors are provided for element, attribute, document, text, comment, 
            processing instruction, and namespace nodes. 
             </p>
            <p>The rest of this section defines the semantics of various kinds of 
            constructor expressions.</p>
            <div3 id="id-constructing-complex-content" role="xpath">
               <head>Constructing Complex Content</head>
               <p>The rules in this section are invoked when constructing document and element nodes.</p>
               <p>The result of evaluating the content expression of a computed document or 
               element constructor (called the <term>content sequence</term>) is processed by applying the following
               steps, in order: </p>
               <olist>
                  <item>
                     <p>Each array in the content sequence is flattened by calling the 
                     function <code nobreak="false">array:flatten()</code> before the steps that follow.</p>
                  </item>
                  <item>
                     <p>If the content sequence contains a <termref def="dt-function-item"/>
                     (including a <termref def="dt-map"/>), a type error is raised <errorref class="TY" code="0105"/>.</p>
                  </item>
                  <item>
                     <p>For each sequence of one or more adjacent <termref def="dt-atomic-item">atomic items</termref> 
                     in the content sequence, 
                     a new text node is constructed, containing the result of casting each atomic item to a 
                     string, with a single <char>U+0020</char> character inserted between adjacent values.</p>
                     <note>
                        <p>The insertion of space characters between adjacent values applies even if one 
                        or both of the values is a zero-length string.</p>
                     </note>
                  </item>
                  <item>
                     <p>For each node in the content sequence, a new copy is made of the 
                     given node and all nodes that have the given node as an ancestor,  
                     collectively referred to as <term>copied nodes</term>. The properties 
                     of the copied nodes are as follows:</p>
                     <olist>
                        <item>
                           <p>Each copied node receives a new node identity.</p>
                        </item>
                        <item>
                           <p>The <code nobreak="false">parent</code>, <code nobreak="false">children</code>, and <code nobreak="false">attributes</code> 
                           properties of the copied nodes are set so as to preserve their inter-node 
                           relationships. For the topmost node (the node directly present in the content sequence), 
                           the <code nobreak="false">parent</code> property is set to 
                           the node being constructed by this constructor.</p>
                        </item>
                        <item>
                           <p>The <code nobreak="false">type-name</code>, <code nobreak="false">nilled</code>, <code nobreak="false">string-value</code>, <code nobreak="false">typed-value</code>, 
                           <code nobreak="false">is-id</code>, and <code nobreak="false">is-idrefs</code> properties of the copied nodes are preserved.</p>
                        </item>
                        <item>
                           <p>The <termref def="dt-in-scope-namespaces"/> of a copied element node consist of:</p>
                           <olist>
                              <item>
                                 <p>The <termref def="dt-in-scope-namespaces"/> of the element node being copied, plus</p>
                              </item>
                              <item>
                                 <p>Inherited copies of the <termref def="dt-in-scope-namespaces"/> of the element node being constructed,
                           as defined in <specref ref="id-ns-nodes-on-elements"/>, except where a namespace binding
                           has been overridden in the element being copied or in one of its ancestors.</p>
                              </item>
                           </olist>
                        </item>
                        <item>
                           <p>When an attribute node is copied but its parent element node is not
                                 copied, type error <errorref class="TY" code="0086"/>
                           is raised if the <termref def="dt-typed-value">typed value</termref>
                                 of the copied attribute node is
                                 <termref def="dt-namespace-sensitive">namespace-sensitive</termref>.</p>
                           <note>
                              <p>This is because it is not possible to preserve the type of a QName without also preserving
                              the <termref def="dt-namespace-binding"/> that defines the prefix of the QName.</p>
                           </note>
                        </item>
                        <item>
                           <p>When an element or processing instruction node is copied, its
                           <code nobreak="false">base-uri</code> property is set to be the same as that of its new parent,
                           with the following exception: if a copied element node has an 
                           <code nobreak="false">xml:base</code> attribute, its <code nobreak="false">base-uri</code> property is set to
                           the value of that attribute, <termref def="dt-resolve-relative-uri">resolved (if it is relative)</termref> against
                           the <code nobreak="false">base-uri</code> property of the new parent node.</p>
                        </item>
                     </olist>
                  </item>
               </olist>
               <note>
                  <p>These rules are the same as for XQuery computed document and element constructors, with 
               <term>construction mode</term> set to <code nobreak="false">preserve</code>, and 
               <term>copy-namespaces</term> mode set to <code nobreak="false">preserve, inherit</code>.</p>
               </note>
               <note>
                  <p>These rules are the same as for XSLT construction of document and element nodes,
               with <term>inherit-namespaces</term> set to <code nobreak="false">true</code>; except that duplicate
               attribute names cause an error (XSLT takes the last of the duplicates), and different
               error codes are used for other error conditions.</p>
               </note>
            </div3>
            <div3 id="id-computedConstructors">
               <head>Computed Constructors</head>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-ComputedConstructor">
                     <lhs>ComputedConstructor</lhs>
                     <rhs>
                        <nt def="prod-xpath40-CompDocConstructor">CompDocConstructor<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-CompElemConstructor">CompElemConstructor<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-CompAttrConstructor">CompAttrConstructor<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-CompNamespaceConstructor">CompNamespaceConstructor<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-CompTextConstructor">CompTextConstructor<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-CompCommentConstructor">CompCommentConstructor<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-CompPIConstructor">CompPIConstructor<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-ComputedConstructor-CompDocConstructor">
                     <lhs>CompDocConstructor</lhs>
                     <rhs>"document"  <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-ComputedConstructor-CompElemConstructor">
                     <lhs>CompElemConstructor</lhs>
                     <rhs>"element"  <nt def="prod-xpath40-CompNodeName">CompNodeName<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-EnclosedContentExpr">EnclosedContentExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-ComputedConstructor-CompAttrConstructor">
                     <lhs>CompAttrConstructor</lhs>
                     <rhs>"attribute"  <nt def="prod-xpath40-CompNodeName">CompNodeName<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-ComputedConstructor-CompNamespaceConstructor">
                     <lhs>CompNamespaceConstructor</lhs>
                     <rhs>"namespace"  <nt def="prod-xpath40-CompNodeNCName">CompNodeNCName<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-ComputedConstructor-CompTextConstructor">
                     <lhs>CompTextConstructor</lhs>
                     <rhs>"text"  <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-ComputedConstructor-CompCommentConstructor">
                     <lhs>CompCommentConstructor</lhs>
                     <rhs>"comment"  <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-ComputedConstructor-CompPIConstructor">
                     <lhs>CompPIConstructor</lhs>
                     <rhs>"processing-instruction"  <nt def="prod-xpath40-CompNodeNCName">CompNodeNCName<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>
               </scrap>
               <p> A computed
constructor begins with a keyword that identifies the type of node to
be created: <code nobreak="false">element</code>, <code nobreak="false">attribute</code>,
<code nobreak="false">document</code>, <code nobreak="false">text</code>,
<code nobreak="false">processing-instruction</code>, <code nobreak="false">comment</code>, or
<code nobreak="false">namespace</code>.</p>
               <p>For those kinds of nodes that have names (element, attribute, 
processing instruction, and namespace nodes), the keyword that specifies the node
kind is followed by the name of the node to be created. This name may

be specified either as a literal or as an expression enclosed in
braces. <termdef term="name expression" id="dt-name-expression">When

an expression is used to specify the name of a constructed node, that
expression is called the <term>name expression</term> of the
constructor.</termdef>
               </p>
               <p>The following example illustrates the use of computed element and
attribute constructors in a simple case where the names of the
constructed nodes are constants:</p>
               <eg role="parse-test" xml:space="preserve">element #book {
  attribute #isbn { "isbn-0060229357" },
  element #title { "Harold and the Purple Crayon" },
  element #author {
    element #first { "Crockett" },
    element #last { "Johnson" }
  }
}</eg>
               <note>
                  <p>In the above example, the element names <code nobreak="false">#book</code>,<code nobreak="false">#title</code>, and so on
            are <nt def="doc-xpath40-QNameLiteral">QNameLiteral<!--$spec = xpath40--></nt>s, which are expanded using the
                  <termref def="dt-constructed-element-namespace-rule"/>.
            The attribute name <code nobreak="false">#isbn</code>, by contrast, is expanded using the
            <termref def="dt-no-namespace-rule"/>.</p>
               </note>
               <note role="xpath">
                  <p>The syntax for computed constructors is a subset of the
            syntax in XQuery 4.0. However, it differs from the syntax that was defined in earlier
            XQuery releases: specifically, the node name must be written either as a QName literal
            (for example <code nobreak="false">#name</code> or <code nobreak="false">#xml:space</code>) or as an expression
            within curly braces. Earlier XQuery releases allowed a bare NCName (for example
            <code nobreak="false">element div {}</code> to create an empty <code nobreak="false">div</code> element) but this option
            has not been carried forward to XPath 4.0 because of complications with reserved words.</p>
               </note>
               <div4 id="id-computedElements">
                  <head>Computed Element Constructors</head>
                  <scrap headstyle="show">
                     <prod id="doc-xpath40-CompElemConstructor">
                        <lhs>CompElemConstructor</lhs>
                        <rhs>"element"  <nt def="prod-xpath40-CompNodeName">CompNodeName<!--$idref_lang_part = xpath40- --></nt>
                           <nt def="prod-xpath40-EnclosedContentExpr">EnclosedContentExpr<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-CompElemConstructor-CompNodeName">
                        <lhs>CompNodeName</lhs>
                        <rhs>
                           <nt def="prod-xpath40-QNameLiteral">QNameLiteral<!--$idref_lang_part = xpath40- --></nt>  |  ("{"  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>  "}")</rhs>
                     </prod>

                     <prod id="doc-xpath40-CompElemConstructor-QNameLiteral">
                        <lhs>QNameLiteral</lhs>
                        <rhs>"#"  <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-CompElemConstructor-Expr">
                        <lhs>Expr</lhs>
                        <rhs>(<nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt> ++ ",")</rhs>
                     </prod>

                     <prod id="doc-xpath40-CompElemConstructor-EnclosedContentExpr">
                        <lhs>EnclosedContentExpr</lhs>
                        <rhs>
                           <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-CompElemConstructor-EnclosedExpr">
                        <lhs>EnclosedExpr</lhs>
                        <rhs>"{"  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>?  "}"</rhs>
                     </prod>
                  </scrap>
                  <p>
                     <termdef term="computed element constructor" id="dt-computed-elem-const">A <term>computed element constructor</term> creates an element node, allowing both the name 
                     and the content of the node to be dynamically computed.</termdef>
                  </p>
                  <p>The element name is determined by the <nt def="prod-xpath40-CompNodeName">CompNodeName<!--$spec = xpath40--></nt>, which 
                  may be provided in a number of ways:</p>
                  <olist>
                     <item>
                        <p>As a QName literal, for example:</p>
                        <slist>
                           <sitem>
                              <code nobreak="false">element #table {}</code>
                           </sitem>
                           <sitem>
                              <code nobreak="false">element #html:table {}</code>
                           </sitem>
                           <sitem>
                              <code nobreak="false">element #Q{}table {}</code>
                           </sitem>
                           <sitem>
                              <code nobreak="false">element #Q{http://http://www.w3.org/1999/xhtml}table {}</code>
                           </sitem>
                           <sitem>
                              <code nobreak="false">element #Q{http://http://www.w3.org/1999/xhtml}html:table {}</code>
                           </sitem>
                        </slist>
                        <p>A QName literal written as an unprefixed <termref def="dt-qname">lexical QName</termref>
                     (the first form above) is resolved using the 
                     <termref def="dt-constructed-element-namespace-rule"/>. This differs from the normal rules for evaluating
                     a QName literal as an atomic item of type <code nobreak="false">xs:QName</code>.</p>
                        <p>Note that the third and fourth examples (<code nobreak="false">#Q{}table</code> and 
                        <code nobreak="false">#Q{http://http://www.w3.org/1999/xhtml}table</code>) will result in the name of the
                     constructed element having no prefix, which may in turn trigger the generation of a default
                     namespace declaration.</p>
                     </item>
                     <item>
                        <p>As an expression in curly brackets. This is processed as follows:</p>
                        <olist>
                           <item>
                              <p>
                                 <termref def="dt-atomization">Atomization</termref> is applied to the value of the <termref def="dt-name-expression">name expression</termref>. If the result of atomization is not a single atomic item of type <code nobreak="false">xs:QName</code>, <code nobreak="false">xs:string</code>, or <code nobreak="false">xs:untypedAtomic</code>, a <termref def="dt-type-error">type
   error</termref> is raised <errorref class="TY" code="0004"/>.</p>
                           </item>
                           <item>
                              <p>If the atomized value of the <termref def="dt-name-expression">name expression</termref> is of type
   <code nobreak="false">xs:QName</code>, that <termref def="dt-expanded-qname">expanded QName</termref> is used as the <code nobreak="false">node-name</code> property of the constructed
   element, retaining the prefix part of the QName.</p>
                           </item>
                           <item>
                              <p>If the atomized value of the <termref def="dt-name-expression">name expression</termref> is of type <code nobreak="false">xs:string</code> or <code nobreak="false">xs:untypedAtomic</code>, 
                        that value is converted to an <termref def="dt-expanded-qname">expanded QName</termref>
                                 <phrase diff="add" at="A">as follows:</phrase>
                              </p>
                              <olist>
                                 <item>
                                    <p>Leading and trailing whitespace is removed.</p>
                                 </item>
                                 <item>
                                    <p>If the value is a lexical QName, it is expanded
                           using the <termref def="dt-constructed-element-namespace-rule"/>.</p>
                                 </item>
                                 <item>
                                    <p>If the value is in the form of a <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$spec = xpath40--></nt>
                           (<code nobreak="false">Q{uri}local</code> or <code nobreak="false">Q{uri}prefix:local</code>), it
                           is converted to an <termref def="dt-expanded-qname"/> with the supplied namespace URI and
                           local name, and with the specified prefix if present.</p>
                                 </item>
                              </olist>
                           </item>
                           <item>
                              <p>If conversion of the atomized <termref def="dt-name-expression">name expression</termref> to an <termref def="dt-expanded-qname">expanded QName</termref> is not successful, a <termref def="dt-dynamic-error">dynamic error</termref> is raised <errorref class="DY" code="0074"/>.</p>
                           </item>
                        </olist>
                     </item>
                  </olist>
                  <p>The resulting <termref def="dt-expanded-qname">expanded QName</termref> is used as the
                        <code nobreak="false">node-name</code> property of the constructed element, retaining the prefix part of the QName
                        <phrase diff="add" at="A">(or its absence)</phrase>.</p>
                  <!--	<change diff="add" at="XQ.E19"> -->
                  <p>An error is raised
             <errorref class="DY" code="0096"/> if the node-name of the constructed
             element node has any of the following properties:
          </p>
                  <ulist>
                     <item>
                        <p>Its namespace prefix is <code nobreak="false">xmlns</code>.
             </p>
                     </item>
                     <item>
                        <p>Its namespace URI is <code nobreak="false">http://www.w3.org/2000/xmlns/</code>.
             </p>
                     </item>
                     <item>
                        <p>Its namespace prefix is <code nobreak="false">xml</code> and its namespace
                URI is not <code nobreak="false">http://www.w3.org/XML/1998/namespace</code>.
             </p>
                     </item>
                     <item>
                        <p>Its namespace prefix is other than <code nobreak="false">xml</code> and its
                namespace URI is <code nobreak="false">http://www.w3.org/XML/1998/namespace</code>.
             </p>
                     </item>
                  </ulist>
                  <p>The above error <rfc2119>may</rfc2119> be raised as a <termref def="dt-static-error"/> if
               the element name is computed statically; in other cases it <rfc2119>must</rfc2119> 
                  be raised as a <termref def="dt-dynamic-error"/>.</p>
                  <p role="xpath">The <termref def="dt-content-expression">content expression</termref> of a computed element constructor (if present) is processed 
                  as described in <specref ref="id-constructing-complex-content"/>. 
                  The result of processing the content expression is a sequence of nodes called the 
                  <term>content sequence</term>. If the <termref def="dt-content-expression">content expression</termref> is absent, the content sequence is the empty sequence.</p>
                  <p>Processing of the computed element constructor proceeds as follows:</p>
                  <olist>
                     <item>
                        <p>If the content sequence contains a document node, the document node is replaced in the 
                        content sequence by its children.</p>
                     </item>
                     <item>
                        <p>Adjacent text nodes in the content sequence are merged into a single text 
                        node by concatenating their contents, with no intervening blanks. After concatenation, 
                        any text node whose content is a zero-length string is deleted from the content sequence.</p>
                     </item>
                     <item>
                        <p> If the content
   sequence contains an attribute node or a namespace node following a node that is not an
   attribute node or a namespace node, a <termref def="dt-type-error">type error</termref>
   is raised <errorref class="TY" code="0024"/>.</p>
                     </item>
                     <item>
                        <p>The properties of the newly constructed element node are determined as follows:</p>
                        <olist>
                           <item>
                              <p>
                                 <code nobreak="false">node-name</code> is the <termref def="dt-expanded-qname">expanded QName</termref> resulting from processing the specified 
                              <nt def="prod-xpath40-CompNodeName">CompNodeName<!--$spec = xpath40--></nt>, as described above.</p>
                           </item>
                           <item>
                              <p>
                                 <code nobreak="false">parent</code> is empty.</p>
                           </item>
                           <item>
                              <p>
                                 <code nobreak="false">attributes</code> consist of all the attribute nodes in the content sequence, in <termref def="dt-implementation-dependent">implementation-dependent</termref> order. Note that the <code nobreak="false">parent</code> property of each of these attribute nodes has been set to the newly constructed element node. If two or more  attributes have the same <code nobreak="false">node-name</code>,  a <termref def="dt-dynamic-error">dynamic error</termref> is raised <errorref class="DY" code="0025"/>. If an attribute named <code nobreak="false">xml:space</code> has a value other than <code nobreak="false">preserve</code> or <code nobreak="false">default</code>, a <termref def="dt-dynamic-error">dynamic error</termref>  may be raised <errorref code="0092" class="DY"/>.</p>
                           </item>
                           <item>
                              <p>
                                 <code nobreak="false">children</code> consist of all the element, text, comment, and processing
                               instruction nodes in the content sequence. Note that the <code nobreak="false">parent</code> property 
                              of each of these nodes has been set to the newly constructed element node.</p>
                           </item>
                           <item>
                              <p>
                                 <code nobreak="false">base-uri</code> is set to the following value:

                              <olist>
                                    <item>
                                       <p>If the constructed node has an attribute named <code nobreak="false">xml:base</code>, 
                                       then the value of this attribute, <termref def="dt-resolve-relative-uri">resolved (if it is relative)</termref> against the 
                                       <phrase diff="chg" at="2023-05-19">
                                             <termref def="dt-executable-base-uri"/>
                                          </phrase>, as described
                                       in <specref ref="id-resolve-relative-uri"/>.</p>
                                    </item>
                                    <item>
                                       <p>Otherwise, the <phrase diff="chg" at="2023-05-19">
                                             <termref def="dt-executable-base-uri"/>
                                          </phrase>.</p>
                                    </item>
                                 </olist>
                              </p>
                           </item>
                           <item>
                              <p>
                              The <termref def="dt-in-scope-namespaces"/> are computed as described in <specref ref="id-ns-nodes-on-elements"/>.</p>
                           </item>
                           <item>
                              <p>The <code nobreak="false">nilled</code> property is <code nobreak="false">false</code>.</p>
                           </item>
                           <item>
                              <p>The <code nobreak="false">string-value</code> property is equal to the concatenated contents 
                              of the text-node descendants in document order.</p>
                           </item>
                           <item>
                              <p>The <code nobreak="false">typed-value</code> property is equal to the <code nobreak="false">string-value</code> 
                              property, as an instance of <code nobreak="false">xs:untypedAtomic</code>.</p>
                           </item>
                           <item role="xpath">
                              <p>The <code nobreak="false">type-name</code> property is <code nobreak="false">xs:untyped</code>. </p>
                           </item>
                           <item>
                              <p>The <code nobreak="false">is-id</code> and <code nobreak="false">is-idrefs</code> properties are set to <code nobreak="false">false</code>.</p>
                           </item>
                        </olist>
                     </item>
                  </olist>
                  <p>A computed element constructor might be
                  used to make a modified copy of an existing element. For example,
                  if the variable <code nobreak="false">$e</code> is bound to an element with <termref def="dt-numeric">numeric</termref>
                  content, the following constructor might be used to create a new
                  element with the same name and attributes as <code nobreak="false">$e</code> and
                  with numeric content equal to twice the value of
                  <code nobreak="false">$e</code>:</p>
                  <eg role="parse-test" xml:space="preserve">element { node-name($e) } { $e/@*, 2 * data($e) }</eg>
                  <p>In this example, if <code nobreak="false">$e</code> is
                  bound by the expression <code nobreak="false">let $e := &lt;length
                  units="inches"&gt;{ 5 }&lt;/length&gt;</code>, then the result of the
                  example expression is the element <code nobreak="false">&lt;length
                  units="inches"&gt;10&lt;/length&gt;</code>.</p>
                  <!--<note>
                  <p>The <termref def="dt-static-type">static type</termref> of the expression <code
                        role="parse-test"
                        >fn:node-name($e)</code> is <code>xs:QName?</code>, denoting zero or one QName. 
                     The example can be successfully evaluated as written provided that 
                     <code>$e</code> is bound to exactly one element node with numeric content.</p>
               </note>-->
                  <p>One important
                  purpose of computed constructors is to allow the name of a node to
                  be computed. We will illustrate this feature by an expression that
                  translates the name of an element from one language to
                  another. Suppose that the variable <code nobreak="false">$dict</code> is bound to a
                  <code nobreak="false">dictionary</code> element containing a sequence of <code nobreak="false">entry</code> elements, 
                  each of which encodes translations for a specific word.  Here is an example
                  entry that encodes the German and Italian variants of the word “address”:</p>
                  <eg role="parse-test" xml:space="preserve">
&lt;entry word="address"&gt;
  &lt;variant xml:lang="de"&gt;Adresse&lt;/variant&gt;
  &lt;variant xml:lang="it"&gt;indirizzo&lt;/variant&gt;
&lt;/entry&gt;
</eg>
                  <p>Suppose further that the variable <code nobreak="false">$e</code> is bound to the following element:</p>
                  <eg role="parse-test" xml:space="preserve">&lt;address&gt;123 Roosevelt Ave. Flushing, NY 11368&lt;/address&gt;</eg>
                  <p>Then the following expression generates a new element in which the name of <code nobreak="false">$e</code> has been translated into Italian and the content of <code nobreak="false">$e</code> (including its attributes, if any) has been preserved. The first enclosed expression after the <code nobreak="false">element</code> keyword generates the name of the element, and the second enclosed
expression generates the content and attributes:</p>
                  <eg role="parse-test" xml:space="preserve">
element {
  $dict/entry[@word = name($e)]/variant[@xml:lang = "it"]
} {
  $e/@*, $e/node()
}</eg>
                  <p>The result of this expression is as follows:</p>
                  <eg role="parse-test" xml:space="preserve">&lt;indirizzo&gt;123 Roosevelt Ave. Flushing, NY 11368&lt;/indirizzo&gt;</eg>
               </div4>
               <div4 id="id-computedAttributes">
                  <head>Computed Attribute Constructors</head>
                  <scrap headstyle="show">
                     <prod id="doc-xpath40-CompAttrConstructor">
                        <lhs>CompAttrConstructor</lhs>
                        <rhs>"attribute"  <nt def="prod-xpath40-CompNodeName">CompNodeName<!--$idref_lang_part = xpath40- --></nt>
                           <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-CompAttrConstructor-CompNodeName">
                        <lhs>CompNodeName</lhs>
                        <rhs>
                           <nt def="prod-xpath40-QNameLiteral">QNameLiteral<!--$idref_lang_part = xpath40- --></nt>  |  ("{"  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>  "}")</rhs>
                     </prod>

                     <prod id="doc-xpath40-CompAttrConstructor-QNameLiteral">
                        <lhs>QNameLiteral</lhs>
                        <rhs>"#"  <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-CompAttrConstructor-Expr">
                        <lhs>Expr</lhs>
                        <rhs>(<nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt> ++ ",")</rhs>
                     </prod>

                     <prod id="doc-xpath40-CompAttrConstructor-EnclosedExpr">
                        <lhs>EnclosedExpr</lhs>
                        <rhs>"{"  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>?  "}"</rhs>
                     </prod>
                  </scrap>
                  <p>A computed attribute constructor creates a new attribute node,
                with its own node identity.</p>
                  <p>Attributes have no default namespace. The rules that expand attribute names create an  <termref def="dt-implementation-dependent">implementation-dependent</termref> prefix if an attribute name has a namespace URI but no prefix is provided.</p>
                  <p>The attribute name may be provided in a number of ways:</p>
                  <olist>
                     <item>
                        <p>As a QName literal, for example:</p>
                        <slist>
                           <sitem>
                              <code nobreak="false">attribute #width {}</code>
                           </sitem>
                           <sitem>
                              <code nobreak="false">attribute #xsi:type {}</code>
                           </sitem>
                           <sitem>
                              <code nobreak="false">attribute #Q{}width {}</code>
                           </sitem>
                           <sitem>
                              <code nobreak="false">attribute #Q{http://www.w3.org/2001/XMLSchema-instance}xsi:type {}</code>
                           </sitem>
                           <sitem>
                              <code nobreak="false">attribute #Q{http://www.w3.org/2001/XMLSchema-instance}type {}</code>
                           </sitem>
                        </slist>
                        <p>A QName literal written as an unprefixed <termref def="dt-qname">lexical QName</termref>
                     (the first form above) is resolved using the 
                     <termref def="dt-no-namespace-rule"/>.</p>
                        <p>Note that the last example (<code nobreak="false">#Q{http://www.w3.org/2001/XMLSchema-instance}type</code>) 
                        will result in the name of the
                     constructed attribute having a system-generated prefix.</p>
                     </item>
                     <item>
                        <p>As an expression in curly brackets. This is processed as follows:</p>
                        <olist>
                           <item>
                              <p>
                                 <termref def="dt-atomization">Atomization</termref> is applied to the result of the <termref def="dt-name-expression">name expression</termref>. If the result of <termref def="dt-atomization">atomization</termref> is not a
                            single atomic item of type <code nobreak="false">xs:QName</code>,
                            <code nobreak="false">xs:string</code>, or <code nobreak="false">xs:untypedAtomic</code>, a <termref def="dt-type-error">type error</termref> is raised <errorref class="TY" code="0004"/>.</p>
                           </item>
                           <item>
                              <p>If the atomized value of the <termref def="dt-name-expression">name expression</termref> is of type <code nobreak="false">xs:QName</code>:</p>
                              <olist>
                                 <item>
                                    <p>If the <termref def="dt-expanded-qname">expanded QName</termref> returned by the atomized name expression has a namespace URI 
                                 but has no prefix, it is given an <termref def="dt-implementation-dependent">implementation-dependent</termref> prefix.</p>
                                 </item>
                                 <item>
                                    <p>The resulting <termref def="dt-expanded-qname">expanded QName</termref> (including its prefix) is used as the <code nobreak="false">node-name</code> property of the constructed
                                 attribute node.</p>
                                 </item>
                              </olist>
                           </item>
                           <item>
                              <p>If the atomized value of the <termref def="dt-name-expression">name expression</termref> is of type <code nobreak="false">xs:string</code> or <code nobreak="false">xs:untypedAtomic</code>, 
                        that value is converted to an <termref def="dt-expanded-qname">expanded QName</termref>
                                 <phrase diff="add" at="A">as follows:</phrase>
                              </p>
                              <olist>
                                 <item>
                                    <p>Leading and trailing whitespace is removed.</p>
                                 </item>
                                 <item>
                                    <p>If the value is a lexical QName, it is expanded
                           using the <termref def="dt-no-namespace-rule"/>.</p>
                                 </item>
                                 <item>
                                    <p>If the value is in the form of a <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$spec = xpath40--></nt> 
                           (<code nobreak="false">Q{uri}local</code> or <code nobreak="false">Q{uri}prefix:local</code>), it
                           is converted to an <termref def="dt-expanded-qname"/> with the supplied namespace URI,
                           local name, and prefix, or with an <termref def="dt-implementation-dependent"/> prefix
                           if none is supplied.</p>
                                 </item>
                                 <item>
                                    <p>If conversion of the atomized name expression to an <termref def="dt-expanded-qname"/> is not successful, 
                           a dynamic error is raised <errorref class="DY" code="0074"/>.</p>
                                 </item>
                              </olist>
                           </item>
                        </olist>
                     </item>
                  </olist>
                  <p>The resulting <termref def="dt-expanded-qname">expanded QName</termref> (including its
   prefix) is used as the <code nobreak="false">node-name</code> property of the
   constructed attribute node. If expansion of the QName is not
   successful, a <termref def="dt-static-error">static error</termref>
   is raised <errorref code="0081" class="ST"/>.</p>
                  <p>If the keyword <code nobreak="false">attribute</code> is followed by a <termref def="dt-name-expression">name expression</termref>, the name
   expression is processed as follows:</p>
                  <!--	<change diff="chg" at="XQ.E19"> -->
                  <p>A <termref def="dt-dynamic-error">dynamic error</termref> is raised
             <errorref class="DY" code="0044"/> if the node-name of the constructed
             attribute node has any of the following properties:
          </p>
                  <ulist>
                     <item>
                        <p>Its namespace prefix is <code nobreak="false">xmlns</code>.
             </p>
                     </item>
                     <item>
                        <p>It has no namespace prefix and its local name is
                <code nobreak="false">xmlns</code>.
             </p>
                     </item>
                     <item>
                        <p>Its namespace URI is <code nobreak="false">http://www.w3.org/2000/xmlns/</code>.
             </p>
                     </item>
                     <item>
                        <p>Its namespace prefix is <code nobreak="false">xml</code> and its namespace
                URI is not <code nobreak="false">http://www.w3.org/XML/1998/namespace</code>.
             </p>
                     </item>
                     <item>
                        <p>Its namespace prefix is other than <code nobreak="false">xml</code> and its
                namespace URI is <code nobreak="false">http://www.w3.org/XML/1998/namespace</code>.
             </p>
                     </item>
                  </ulist>
                  <!--	</change> -->
                  <p>The <termref def="dt-content-expression">content
   expression</termref> of a computed attribute constructor is
   processed as follows:</p>
                  <olist>
                     <item>
                        <p>
                           <termref def="dt-atomization">Atomization</termref> is
     applied to the result of the <termref def="dt-content-expression">content expression</termref>,
     converting it to a sequence of atomic items. (If the <termref def="dt-content-expression">content expression</termref> is
     absent, the result of this step is the empty
     sequence.)</p>
                     </item>
                     <item>
                        <p>If the result of atomization is the empty sequence, the
     value of the attribute is the zero-length string. Otherwise, each
     atomic item in the atomized sequence is cast into a
     string.</p>
                     </item>
                     <item>
                        <p>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 resulting string
     becomes the <code nobreak="false">string-value</code> property of the new
     attribute node. The <termref def="dt-type-annotation">type
     annotation</termref> (<code nobreak="false">type-name</code> property) of the new
     attribute node is <code nobreak="false">xs:untypedAtomic</code>. The
     <code nobreak="false">typed-value</code> property of the attribute node is the
     same as its <code nobreak="false">string-value</code>, as an instance of
     <code nobreak="false">xs:untypedAtomic</code>.</p>
                     </item>
                     <item>
                        <p>The <code nobreak="false">parent</code> property of the attribute node
     is set to empty.</p>
                     </item>
                     <item>
                        <p>If the attribute name is <code nobreak="false">xml:id</code>, then
     <code nobreak="false">xml:id</code> processing is performed as defined in <bibref ref="XMLID"/>. This ensures that the attribute node has the type
     <code nobreak="false">xs:ID</code> and that its value is properly normalized. If
     an error is encountered during <code nobreak="false">xml:id</code> processing, an
     implementation may raise a <termref def="dt-dynamic-error">dynamic error</termref>
                           <errorref class="DY" code="0091"/>.</p>
                     </item>
                     <item>
                        <p>If the attribute name is <code nobreak="false">xml:id</code>, the
     <code nobreak="false">is-id</code> property of the resulting attribute node is
     set to <code nobreak="false">true</code>; otherwise the <code nobreak="false">is-id</code>
     property is set to <code nobreak="false">false</code>. The <code nobreak="false">is-idrefs</code>
     property of the attribute node is unconditionally set to
     <code nobreak="false">false</code>.</p>
                     </item>
                     <item>
                        <p>If the attribute name is <code nobreak="false">xml:space</code> and the
     attribute value is other than <code nobreak="false">preserve</code> or
     <code nobreak="false">default</code>, a <termref def="dt-dynamic-error">dynamic error</termref>  may be raised <errorref code="0092" class="DY"/>.</p>
                     </item>
                  </olist>
                  <ulist>
                     <item>
                        <p>Example:</p>
                        <eg role="parse-test" xml:space="preserve">attribute #size { 4 + 3 }</eg>
                        <p>The <termref def="dt-string-value">string
     value</termref> of the <code nobreak="false">size</code> attribute is
     <code nobreak="false">"7"</code> and its type is
     <code nobreak="false">xs:untypedAtomic</code>.</p>
                     </item>
                     <item>
                        <p>Example:</p>
                        <eg role="parse-test" xml:space="preserve">
attribute {
  if ($sex = "M") then #husband else #wife
} {
  &lt;a&gt;Hello&lt;/a&gt;, 1 to 3, &lt;b&gt;Goodbye&lt;/b&gt;
}
</eg>
                        <p>The name of the constructed attribute is
     either <code nobreak="false">husband</code> or
     <code nobreak="false">wife</code> (in no namespace). Its <termref def="dt-string-value">string
     value</termref> is "<code nobreak="false">Hello 1 2 3
     Goodbye</code>".</p>
                     </item>
                  </ulist>
               </div4>
               <div4 id="id-documentConstructors">
                  <head>Document Node Constructors</head>
                  <scrap headstyle="show">
                     <prod id="doc-xpath40-CompDocConstructor">
                        <lhs>CompDocConstructor</lhs>
                        <rhs>"document"  <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-CompDocConstructor-EnclosedExpr">
                        <lhs>EnclosedExpr</lhs>
                        <rhs>"{"  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>?  "}"</rhs>
                     </prod>
                  </scrap>
                  <p>
                  The result of a document node constructor is a new document node, with its own node identity.</p>
                  <p>A document node constructor is useful when the result of a query is to be a document 
                  in its own right. The following example illustrates a query that returns an XML document 
                  containing a root element named <code nobreak="false">author-list</code>:</p>
                  <eg role="parse-test" xml:space="preserve">document {
  &lt;author-list&gt;{
    doc("bib.xml")/bib/book/author
  }&lt;/author-list&gt;
}</eg>
                  <p>The <termref def="dt-content-expression">content expression</termref> of a document node constructor is processed 
                  in exactly the same way as the content expression of a computed element constructor,
                  as described in <specref ref="id-computedElements"/>.</p>
                  <!--an enclosed expression in the content of a <termref
                     def="dt-direct-elem-const"
                     >direct element constructor</termref>, as described in Step 1e of <specref
                     ref="id-content"
                     />. 
               -->
                  <p>The result of processing the content expression is a sequence of nodes 
                  called the <term>content sequence</term>. Processing of the document node 
                  constructor then proceeds as follows:</p>
                  <olist>
                     <item>
                        <p>If the content sequence contains a document node, the document node 
                        is replaced in the content sequence by its children.</p>
                     </item>
                     <item>
                        <p>Adjacent text nodes in the content sequence are merged into a single 
                        text node by concatenating their contents, with no intervening blanks. 
                        After concatenation, any text node whose content is a zero-length string 
                        is deleted from the content sequence.</p>
                     </item>
                     <item>
                        <p> If the content sequence contains an attribute node, a
<termref def="dt-type-error">type error</termref> is raised <errorref class="TY" code="0004"/>.</p>
                     </item>
                     <item>
                        <p> If the content sequence contains a namespace node, a
<termref def="dt-type-error">type error</termref> is raised <errorref class="TY" code="0004"/>.</p>
                     </item>
                     <item>
                        <p>The properties of the newly constructed document node are determined as follows:</p>
                        <olist>
                           <item>
                              <p>
                                 <code nobreak="false">base-uri</code> is
    set to the <phrase diff="chg" at="2023-05-19">
                                    <termref def="dt-executable-base-uri"/>
                                 </phrase>.</p>
                           </item>
                           <item>
                              <p>
                                 <code nobreak="false">children</code> consist of all the element, text, comment, and processing
   instruction nodes in the content sequence. Note that the <code nobreak="false">parent</code> property of each of these nodes has been set to the newly constructed document node.</p>
                           </item>
                           <item>
                              <p>The <code nobreak="false">unparsed-entities</code> and <code nobreak="false">document-uri</code> properties are empty.</p>
                           </item>
                           <item>
                              <p>The <code nobreak="false">string-value</code> property is equal to the concatenated contents of the text-node descendants in document order.</p>
                           </item>
                           <item>
                              <p>The <code nobreak="false">typed-value</code> property is equal to the <code nobreak="false">string-value</code> property, as an instance of <code nobreak="false">xs:untypedAtomic</code>.</p>
                           </item>
                        </olist>
                     </item>
                  </olist>
                  <p>No validation is performed on the constructed document node. The <bibref ref="XML"/> rules that govern the structure of an XML document (for example, the 
                  document node must have exactly one child that is an element node)  
                  are not enforced by the XPath 4.0 document node constructor.</p>
               </div4>
               <div4 id="id-textConstructors">
                  <head>Text Node Constructors</head>
                  <scrap headstyle="show">
                     <prod id="doc-xpath40-CompTextConstructor">
                        <lhs>CompTextConstructor</lhs>
                        <rhs>"text"  <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-CompTextConstructor-EnclosedExpr">
                        <lhs>EnclosedExpr</lhs>
                        <rhs>"{"  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>?  "}"</rhs>
                     </prod>
                  </scrap>
                  <p>
                  The result of a text node constructor is a new text node, with its own node identity.</p>
                  <p>The <termref def="dt-content-expression">content expression</termref> of a text node constructor is processed as follows:</p>
                  <olist>
                     <item>
                        <p>
                           <termref def="dt-atomization">Atomization</termref> is applied to the value of the <termref def="dt-content-expression">content expression</termref>, converting it to a sequence of atomic items.</p>
                     </item>
                     <item>
                        <p>If the result of atomization is the empty sequence, no text node is constructed. 
                        Otherwise, each atomic item in the atomized sequence is cast into a string.</p>
                     </item>
                     <item>
                        <p>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 resulting string becomes the <code nobreak="false">content</code> property of 
                        the constructed text node.</p>
                     </item>
                  </olist>
                  <p>The <code nobreak="false">parent</code> property of the constructed text node is set to empty.</p>
                  <note>
                     <p>It is possible for a text node constructor to construct a text node containing 
                     a zero-length string. However, if used in the content of a constructed element 
                     or document node, such a text node will be deleted or merged with another text node.</p>
                  </note>
                  <p>The following example illustrates a text node constructor:</p>
                  <eg role="parse-test" xml:space="preserve">text { "Hello" }</eg>
                  <note>
                     <p>It is possible to construct a text node whose string value is zero-length. The rules 
                     for constructing element nodes, however, ensure that a zero-length text node will be discarded
                     if used while forming the content of an element.</p>
                  </note>
               </div4>
               <div4 id="id-computed-pis">
                  <head>Computed Processing Instruction Constructors</head>
                  <scrap headstyle="show">
                     <prod id="doc-xpath40-CompPIConstructor">
                        <lhs>CompPIConstructor</lhs>
                        <rhs>"processing-instruction"  <nt def="prod-xpath40-CompNodeNCName">CompNodeNCName<!--$idref_lang_part = xpath40- --></nt>
                           <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-CompPIConstructor-CompNodeNCName">
                        <lhs>CompNodeNCName</lhs>
                        <rhs>
                           <nt def="prod-xpath40-MarkedNCName">MarkedNCName<!--$idref_lang_part = xpath40- --></nt>  |  ("{"  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>  "}")</rhs>
                     </prod>

                     <prod id="doc-xpath40-CompPIConstructor-MarkedNCName">
                        <lhs>MarkedNCName</lhs>
                        <rhs>"#"  <nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-CompPIConstructor-Expr">
                        <lhs>Expr</lhs>
                        <rhs>(<nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt> ++ ",")</rhs>
                     </prod>

                     <prod id="doc-xpath40-CompPIConstructor-EnclosedExpr">
                        <lhs>EnclosedExpr</lhs>
                        <rhs>"{"  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>?  "}"</rhs>
                     </prod>
                  </scrap>
                  <p>A computed processing instruction constructor (<nt def="doc-xpath40-CompPIConstructor">CompPIConstructor<!--$spec = xpath40--></nt>) constructs a new processing instruction node with its own node identity.
   </p>
                  <p>The name of a processing instruction node is always an NCName, and may be provided in a number of ways:</p>
                  <olist>
                     <item>
                        <p>As an <code nobreak="false">NCName</code> with a preceding <code nobreak="false">#</code> sign, 
                     for example <code nobreak="false">processing-instruction #xref {}</code>.
                  </p>
                     </item>
                     <item>
                        <p>As an expression in curly braces. This is processed as follows:</p>
                        <olist>
                           <item>
                              <p>
                                 <termref def="dt-atomization">Atomization</termref> is applied to the value of the <termref def="dt-name-expression">name expression</termref>. If the result of <termref def="dt-atomization">atomization</termref> is not a single atomic item of type <code nobreak="false">xs:NCName</code>, 
                              <code nobreak="false">xs:string</code>, or <code nobreak="false">xs:untypedAtomic</code>, a <termref def="dt-type-error">type error</termref> is raised <errorref class="TY" code="0004"/>.</p>
                           </item>
                           <item>
                              <p>If the atomized value of the <termref def="dt-name-expression">name expression</termref> is of type <code nobreak="false">xs:string</code> or <code nobreak="false">xs:untypedAtomic</code>, 
                              that value is cast to the type <code nobreak="false">xs:NCName</code>. If the value cannot be cast to <code nobreak="false">xs:NCName</code>, a <termref def="dt-dynamic-error">dynamic error</termref> is raised <errorref class="DY" code="0041"/>.</p>
                           </item>
                           <item>
                              <p>The resulting NCName is then used as the <code nobreak="false">target</code> property of the newly constructed 
                              processing instruction node. However, a <termref def="dt-dynamic-error">dynamic error</termref> is raised if the  NCName is equal to <code nobreak="false">"XML"</code> (in any combination of upper and lower case) <errorref class="DY" code="0064"/>.</p>
                           </item>
                        </olist>
                     </item>
                  </olist>
                  <p>The
   <termref def="dt-content-expression">content expression</termref> of a computed processing instruction constructor
   is processed as follows:</p>
                  <olist>
                     <item>
                        <p>
                           <termref def="dt-atomization">Atomization</termref> is applied to the value of the <termref def="dt-content-expression">content expression</termref>, converting it to a sequence of atomic items. (If the <termref def="dt-content-expression">content expression</termref> is absent, the result of this step is the empty sequence.)</p>
                     </item>
                     <item>
                        <p>If the result of atomization is the empty sequence, it is replaced by a zero-length string.
                        Otherwise, each atomic item in the atomized sequence is cast into a string.
                        If any of the resulting strings contains the string <code nobreak="false">"?&gt;"</code>, a <termref def="dt-dynamic-error">dynamic error</termref>
                           <errorref class="DY" code="0026"/> is raised.</p>
                     </item>
                     <item>
                        <p>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.
                        Leading whitespace is removed from the resulting string. The resulting string then
                        becomes the <code nobreak="false">content</code> property of the constructed processing instruction node.</p>
                     </item>
                  </olist>
                  <p>The remaining properties of the new processing instruction node are determined as follows:</p>
                  <olist>
                     <item>
                        <p>The <code nobreak="false">parent</code> property is empty.</p>
                     </item>
                     <item>
                        <p>The <code nobreak="false">base-uri</code> property is empty.</p>
                     </item>
                  </olist>
                  <p>The following example illustrates a computed processing instruction constructor:</p>
                  <eg role="parse-test" xml:space="preserve">let $target := "audio-output",
return processing-instruction { $target } { "beep" }</eg>
                  <p>The processing instruction node constructed by this example might be serialized as follows:</p>
                  <eg xml:space="preserve">&lt;?audio-output beep?&gt;</eg>
               </div4>
               <div4 id="id-computed-comments">
                  <head>Computed Comment Constructors</head>
                  <scrap headstyle="show">
                     <head/>
                     <prod id="doc-xpath40-CompCommentConstructor">
                        <lhs>CompCommentConstructor</lhs>
                        <rhs>"comment"  <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-CompCommentConstructor-EnclosedExpr">
                        <lhs>EnclosedExpr</lhs>
                        <rhs>"{"  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>?  "}"</rhs>
                     </prod>
                  </scrap>
                  <p>A computed comment constructor (<nt def="doc-xpath40-CompCommentConstructor">CompCommentConstructor<!--$spec = xpath40--></nt>) constructs a new comment node with its own node identity.
   The <termref def="dt-content-expression">content expression</termref> of a computed comment constructor is processed as follows:</p>
                  <olist>
                     <item>
                        <p>
                           <termref def="dt-atomization">Atomization</termref> is applied to the value of the <termref def="dt-content-expression">content expression</termref>, converting it to a sequence of atomic items.</p>
                     </item>
                     <item>
                        <p>If the result of atomization is the empty sequence, it is replaced by a zero-length string. Otherwise, each atomic item in the atomized sequence is cast into a string.</p>
                     </item>
                     <item>
                        <p>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 resulting string becomes the <code nobreak="false">content</code> property of the constructed comment node.</p>
                     </item>
                     <item>
                        <p>It is a <termref def="dt-dynamic-error">dynamic
 error</termref>
                           <errorref class="DY" code="0072"/> if the result of the <termref def="dt-content-expression">content expression</termref> of a computed comment constructor contains two adjacent hyphens or ends with a hyphen.</p>
                     </item>
                  </olist>
                  <p>The <code nobreak="false">parent</code> property of the constructed comment node is set to empty.</p>
                  <p>The following example illustrates a computed comment constructor:</p>
                  <eg role="parse-test" xml:space="preserve">let $homebase := "Houston"
return comment { concat($homebase, ", we have a problem.") }</eg>
                  <p>The comment node constructed by this example might be serialized as follows:</p>
                  <eg xml:space="preserve">&lt;!--Houston, we have a problem.--&gt;</eg>
               </div4>
               <div4 id="id-computed-namespaces">
                  <head>Computed Namespace Constructors</head>
                  <scrap headstyle="show">
                     <prod id="doc-xpath40-CompNamespaceConstructor">
                        <lhs>CompNamespaceConstructor</lhs>
                        <rhs>"namespace"  <nt def="prod-xpath40-CompNodeNCName">CompNodeNCName<!--$idref_lang_part = xpath40- --></nt>
                           <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-CompNamespaceConstructor-CompNodeNCName">
                        <lhs>CompNodeNCName</lhs>
                        <rhs>
                           <nt def="prod-xpath40-MarkedNCName">MarkedNCName<!--$idref_lang_part = xpath40- --></nt>  |  ("{"  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>  "}")</rhs>
                     </prod>

                     <prod id="doc-xpath40-CompNamespaceConstructor-MarkedNCName">
                        <lhs>MarkedNCName</lhs>
                        <rhs>"#"  <nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-CompNamespaceConstructor-Expr">
                        <lhs>Expr</lhs>
                        <rhs>(<nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt> ++ ",")</rhs>
                     </prod>

                     <prod id="doc-xpath40-CompNamespaceConstructor-EnclosedExpr">
                        <lhs>EnclosedExpr</lhs>
                        <rhs>"{"  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>?  "}"</rhs>
                     </prod>
                  </scrap>
                  <p>A computed namespace constructor creates a new namespace node,
   with its own node identity. The parent of the newly created
   namespace node is absent.</p>
                  <p>The name of a namespace node is always an <code nobreak="false">NCName</code>, and represents
               the namespace prefix.</p>
                  <p>The string value of a namespace node should be a <code nobreak="false">URI</code>, and represents
               the namespace URI.</p>
                  <p>The namespace prefix may be provided in a number of ways:</p>
                  <olist>
                     <item>
                        <p>As an <code nobreak="false">NCName</code> with a preceding <code nobreak="false">#</code> sign, 
                     for example <code nobreak="false">namespace #xlink { "http://www.w3.org/1999/xlink" }</code>.
                  </p>
                     </item>
                     <item>
                        <p>As a simple <code nobreak="false">NCName</code> with no preceding <code nobreak="false">#</code> sign, 
                     for example <code nobreak="false">namespace xlink { "http://www.w3.org/1999/xlink" }</code>. This
                  form is allowed only if the namespace prefix is not a reserved keyword: see
                  <loc xmlns:xlink="http://www.w3.org/1999/xlink"
                                href="#parse-note-unreserved-name"
                                xlink:type="simple"
                                xlink:show="replace"
                                xlink:actuate="onRequest">unreserved-name</loc>.</p>
                     </item>
                     <item>
                        <p>As an expression in curly braces. This is processed as follows:</p>
                        <olist>
                           <item>
                              <p>
                                 <termref def="dt-atomization">Atomization</termref> is
      applied to the result of the enclosed expression.</p>
                           </item>
                           <item>
                              <p>
      If the result of <termref def="dt-atomization">atomization</termref>
        is the empty sequence
        or a single atomic item of type <code nobreak="false">xs:string</code> or <code nobreak="false">xs:untypedAtomic</code>,
      then the following rules are applied in order:</p>
                              <olist>
                                 <item>
                                    <p>If the result is castable to <code nobreak="false">xs:NCName</code>, then it is used as the local name
         of the newly constructed namespace node. (The local name of a namespace node
         represents the prefix part of the <termref def="dt-namespace-binding"/>.)</p>
                                 </item>
                                 <item>
                                    <p>If the result is the empty sequence
                      or a zero-length <code nobreak="false">xs:string</code>
                      or <code nobreak="false">xs:untypedAtomic</code> item,
               the new namespace node has no name (such a namespace node represents a binding for the default namespace).</p>
                                 </item>
                                 <item>
                                    <p>Otherwise, a <termref def="dt-dynamic-error">dynamic error</termref>  is raised  <errorref class="DY" code="0074"/>.</p>
                                 </item>
                              </olist>
                           </item>
                           <item>
                              <p>If the result of atomization is not the empty sequence
                               or a single atomic item of type <code nobreak="false">xs:string</code> or <code nobreak="false">xs:untypedAtomic</code>,
      a type error is raised <errorref class="TY" code="0004"/>.</p>
                           </item>
                        </olist>
                     </item>
                  </olist>
                  <p>The <termref def="dt-content-expression">content expression</termref> is evaluated, and the result is cast
    to <code nobreak="false">xs:anyURI</code> to create the <code nobreak="false">URI</code> property
    for the newly created node.  
    An implementation may raise a <termref def="dt-dynamic-error">dynamic error</termref>
                     <errorref class="DY" code="0074"/> if the <code nobreak="false">URIExpr</code> of a computed namespace constructor is not a valid instance of <code nobreak="false">xs:anyURI</code>.</p>
                  <p>An error <errorref class="DY" code="0101"/> is raised if a
    computed namespace constructor attempts to do any of the
    following:</p>
                  <ulist>
                     <item>
                        <p>Bind the prefix <code nobreak="false">xml</code> to some namespace URI
      other than <code nobreak="false">http://www.w3.org/XML/1998/namespace</code>.
      </p>
                     </item>
                     <item>
                        <p>Bind a prefix other than <code nobreak="false">xml</code> to the namespace
      URI <code nobreak="false">http://www.w3.org/XML/1998/namespace</code>.
      </p>
                     </item>
                     <item>
                        <p>Bind the prefix <code nobreak="false">xmlns</code> to any namespace URI.
      </p>
                     </item>
                     <item>
                        <p>Bind a prefix to the namespace
      URI <code nobreak="false">http://www.w3.org/2000/xmlns/</code>.
      </p>
                     </item>
                     <item>
                        <p>Bind any prefix (including the empty prefix) to a zero-length namespace URI.</p>
                     </item>
                  </ulist>
                  <p>By itself, a computed namespace constructor has no effect on
                  the <termref def="dt-in-scope-namespaces"/> of any element,
                  but if an element constructor’s content
                  sequence contains a namespace node, the <termref def="dt-namespace-binding"/> it
                  represents is added to that element’s <termref def="dt-in-scope-namespaces"/>.</p>
                  <p>A computed namespace constructor has no effect on the <termref def="dt-static-namespaces"/>
                  in the <termref def="dt-static-context"/>.</p>
                  <note>
                     <p>The newly created namespace node has all properties defined
      for a namespace node in the data model, but its parent is always absent.  As defined in the
      data model, the name of the node is the prefix, the string value
      of the node is the URI. Since the nodes are parentless, their relative order is implementation
      dependent.</p>
                  </note>
                  <p>Examples:</p>
                  <ulist>
                     <item>
                        <p>A computed namespace constructor with a prefix:</p>
                        <eg role="parse-test" xml:space="preserve">namespace #a { "http://a.example.com" }</eg>
                     </item>
                     <item>
                        <p>A computed namespace constructor with a prefix expression:</p>
                        <eg role="parse-test" xml:space="preserve">namespace { "a" || $i } { "http://example.ns/a" || $i }</eg>
                     </item>
                     <item>
                        <p>A computed namespace constructor with the empty prefix:</p>
                        <eg role="parse-test" xml:space="preserve">namespace {""} { "http://example.ns/a0" }</eg>
                     </item>
                  </ulist>
                  <p>Computed namespace constructors are generally used to add to the
<termref def="dt-in-scope-namespaces"/> of elements created using computed element constructors:</p>
                  <eg role="parse-test" xml:space="preserve">
element #age {
  namespace #xmlns:xsi { "http://www.w3.org/2001/XMLSchema-instance" },
  namespace #xs { "http://www.w3.org/2001/XMLSchema" },
  attribute #xsi:type { "xs:integer" },
  23
}
</eg>
                  <p>In this example, the explicit construction of 
                  the <code nobreak="false">xsi</code>
                     <termref def="dt-namespace-binding"/> 
                  is unnecessary; it would be created automatically, because the <code nobreak="false">xsi</code> 
                  prefix is used in an attribute name. By contrast, the declaration of
                  the <code nobreak="false">xs</code>
                     <termref def="dt-namespace-binding"/> is needed; the attribute’s 
                  content is simply character data, and would not trigger automatic creation
                  of a namespace binding. This would be true even if the attribute is subsequently
                  validated against a schema that interprets <code nobreak="false">"xs:integer"</code> as a QName,
                  because such validation relies on the namespace binding already being present.</p>
                  <note>
                     <p>It is not possible to use a computed namespace constructor to
                    generate a namespace undeclaration such as <code nobreak="false">xmlns=""</code>
                 or (with XML Namespaces 1.1) <code nobreak="false">xmlns:p=""</code>. A namespace undeclaration in lexical XML
                 is represented in the XDM model by the absence of a <termref def="dt-namespace-binding"/> that
                 would otherwise be present.</p>
                  </note>
               </div4>
            </div3>
            <div3 id="id-ns-nodes-on-elements">
               <head>In-scope Namespaces of a Constructed Element</head>
               <p>An element node constructed by a  computed element
constructor has an <termref def="dt-in-scope-namespaces"/> property that consists of a set of 
               <termref def="dt-namespace-binding">namespace bindings</termref>.  The
in-scope namespaces of an element node may affect the way the node is
serialized (see <specref ref="id-serialization"/>), and may also
affect the behavior of certain functions that operate on nodes, such
as <function>fn:name</function>. Note the difference between <termref def="dt-in-scope-namespaces">in-scope namespaces</termref>, which is a
dynamic property of an element node, and <termref def="dt-static-namespaces">statically known namespaces</termref>,
which is a static property of an expression.  One of
the namespace bindings in the in-scope namespaces may have an empty prefix:
this is referred to as the <termref def="dt-default-in-scope-namespace"/> of the element. The in-scope
namespaces of a constructed element node consist of the following
<termref def="dt-namespace-binding">namespace bindings</termref>:</p>
               <ulist>
                  <item>
                     <p>A <termref def="dt-namespace-binding"/> is created for each namespace node in
                  the content sequence of the current element constructor.</p>
                  </item>
                  <item>
                     <p>A <termref def="dt-namespace-binding"/> is always created to bind the prefix
  <code nobreak="false">xml</code> to the namespace URI
  <code nobreak="false">http://www.w3.org/XML/1998/namespace</code>.</p>
                  </item>
                  <item>
                     <p>For each prefix used in the name of the
  constructed element or in the names of its attributes, a <termref def="dt-namespace-binding"/> must exist.</p>
                     <p>If a <termref def="dt-namespace-binding"/> does not already exist for one of these
  prefixes, a new namespace binding is created for it.</p>
                     <p>If this would result in a conflict, because it would require two
  different bindings of the same prefix, then the prefix used in the
  node name is changed to an arbitrary <termref def="dt-implementation-dependent">implementation-dependent</termref>
  prefix that does not cause such a conflict, and a <termref def="dt-namespace-binding"/>
  is created for this new prefix.</p>
                     <p>If there is a <termref def="dt-default-in-scope-namespace"/>, then 
                     a binding is created between the empty prefix and that URI.</p>
                  </item>
               </ulist>
               <p>In an element constructor, if two or more <termref def="dt-namespace-binding">namespace bindings</termref> in the
<termref def="dt-in-scope-namespaces"/> would have the same prefix, then an error is raised
if they have different URIs <errorref class="DY" code="0102"/>; if they
would have the same prefix and URI, duplicate bindings are
ignored. 
If the name of an element in an element constructor is in no namespace,
creating a default namespace for that element using a computed namespace constructor is an error <errorref class="DY" code="0102"/>. 
For instance, the following computed constructor raises an error because the element’s name is not in a namespace, 
but a default namespace is defined.</p>
               <eg role="parse-test" xml:space="preserve">element #Q{}e { namespace { '' } { 'u' } }</eg>
               <p>The following example illustrates the <termref def="dt-in-scope-namespaces"/> of a constructed element:</p>
               <eg xml:space="preserve">declare namespace p = "http://example.com/ns/p";
declare namespace q = "http://example.com/ns/q";
declare namespace f = "http://example.com/ns/f";
element #p:a {
  attribute #q:b { f:func(2) }
  namespace #r {"http://example.com/ns/r"}
}  
</eg>
               <p>The <termref def="dt-in-scope-namespaces"/> of the resulting <code nobreak="false">p:a</code> element comprise 
               the following <termref def="dt-namespace-binding">namespace bindings</termref>:</p>
               <slist>
                  <sitem>
                     <code nobreak="false">p = "http://example.com/ns/p"</code>
                  </sitem>
                  <sitem>
                     <code nobreak="false">q = "http://example.com/ns/q"</code>
                  </sitem>
                  <sitem>
                     <code nobreak="false">r = "http://example.com/ns/r"</code>
                  </sitem>
                  <sitem>
                     <code nobreak="false">xml = "http://www.w3.org/XML/1998/namespace"</code>
                  </sitem>
               </slist>
               <p>The <termref def="dt-namespace-binding">namespace bindings</termref> for <code nobreak="false">p</code> and <code nobreak="false">q</code> 
               are added to the result element because their respective namespaces
               are used in the names of the element and its attributes. The namespace binding <code nobreak="false">r="http://example.com/ns/r"</code> 
               is added to the in-scope namespaces of the constructed
               element because it is explicitly created, even though it is not used in a name.</p>
               <p>No <termref def="dt-namespace-binding"/> corresponding to <code nobreak="false">f="http://example.com/ns/f"</code> is created, 
               because the namespace prefix <code nobreak="false">f</code> appears only in the query prolog and is not used in an element 
               or attribute name of the constructed node. This namespace binding does not appear in the query result, 
               even though it is present in the <termref def="dt-static-namespaces"/> and is available for use 
               during processing of the query.</p>
            </div3>
         </div2>
         <div2 id="id-flwor-expressions">
            <head>
               <phrase role="xpath">For and Let Expressions</phrase>
            </head>
            <p role="xpath">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.</p>
            <div3 role="xpath" id="id-for-expressions">
               <head>For Expressions</head>
               <changes>
                  <change issue="49" PR="344" date="2023-02-10">A <code nobreak="false">for member</code> clause is added to FLWOR expressions to allow iteration over
               an array.</change>
                  <change issue="22" PR="28" date="2020-12-18">
               Multiple <code nobreak="false">for</code> and <code nobreak="false">let</code> clauses can be combined
               in an expression without an intervening <code nobreak="false">return</code> keyword.
            </change>
                  <change issue="31" PR="1249" date="2024-06-01">
               A <code nobreak="false">for key/value</code> clause is added to FLWOR expressions to allow iteration over
               maps.</change>
                  <change issue="231" PR="1131" date="2024-04-01">
               A positional variable can be defined in a <code nobreak="false">for</code> expression.
            </change>
                  <change issue="796" PR="1131" date="2024-04-01">
               The type of a variable used in a <code nobreak="false">for</code> expression can be declared.
               </change>
               </changes>
               <p>XPath provides an iteration facility called a <term>for expression</term>. 
         It can be used to iterate over the items of a sequence, the
            members of an array, or the entries in a map.</p>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-ForExpr">
                     <lhs>ForExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-ForClause">ForClause<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-ForLetReturn">ForLetReturn<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-ForExpr-ForClause">
                     <lhs>ForClause</lhs>
                     <rhs>"for"  (<nt def="prod-xpath40-ForBinding">ForBinding<!--$idref_lang_part = xpath40- --></nt> ++ ",")</rhs>
                  </prod>

                  <prod id="doc-xpath40-ForExpr-ForBinding">
                     <lhs>ForBinding</lhs>
                     <rhs>
                        <nt def="prod-xpath40-ForItemBinding">ForItemBinding<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ForMemberBinding">ForMemberBinding<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ForEntryBinding">ForEntryBinding<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-ForExpr-ForItemBinding">
                     <lhs>ForItemBinding</lhs>
                     <rhs>
                        <nt def="prod-xpath40-VarNameAndType">VarNameAndType<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-PositionalVar">PositionalVar<!--$idref_lang_part = xpath40- --></nt>?  "in"  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-ForExpr-VarNameAndType">
                     <lhs>VarNameAndType</lhs>
                     <rhs>"$"  <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-TypeDeclaration">TypeDeclaration<!--$idref_lang_part = xpath40- --></nt>?</rhs>
                  </prod>

                  <prod id="doc-xpath40-ForExpr-EQName">
                     <lhs>EQName</lhs>
                     <rhs>
                        <nt def="prod-xpath40-QName">QName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-ForExpr-TypeDeclaration">
                     <lhs>TypeDeclaration</lhs>
                     <rhs>"as"  <nt def="prod-xpath40-SequenceType">SequenceType<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-ForExpr-PositionalVar">
                     <lhs>PositionalVar</lhs>
                     <rhs>"at"  <nt def="prod-xpath40-VarName">VarName<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-ForExpr-VarName">
                     <lhs>VarName</lhs>
                     <rhs>"$"  <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-ForExpr-ExprSingle">
                     <lhs>ExprSingle</lhs>
                     <rhs>
                        <nt def="prod-xpath40-ForExpr">ForExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-LetExpr">LetExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-QuantifiedExpr">QuantifiedExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-IfExpr">IfExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-OrExpr">OrExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-ForExpr-ForMemberBinding">
                     <lhs>ForMemberBinding</lhs>
                     <rhs>"member"  <nt def="prod-xpath40-VarNameAndType">VarNameAndType<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-PositionalVar">PositionalVar<!--$idref_lang_part = xpath40- --></nt>?  "in"  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-ForExpr-ForEntryBinding">
                     <lhs>ForEntryBinding</lhs>
                     <rhs>((<nt def="prod-xpath40-ForEntryKeyBinding">ForEntryKeyBinding<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-ForEntryValueBinding">ForEntryValueBinding<!--$idref_lang_part = xpath40- --></nt>?)  |  <nt def="prod-xpath40-ForEntryValueBinding">ForEntryValueBinding<!--$idref_lang_part = xpath40- --></nt>)  <nt def="prod-xpath40-PositionalVar">PositionalVar<!--$idref_lang_part = xpath40- --></nt>?  "in"  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-ForExpr-ForEntryKeyBinding">
                     <lhs>ForEntryKeyBinding</lhs>
                     <rhs>"key"  <nt def="prod-xpath40-VarNameAndType">VarNameAndType<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-ForExpr-ForEntryValueBinding">
                     <lhs>ForEntryValueBinding</lhs>
                     <rhs>"value"  <nt def="prod-xpath40-VarNameAndType">VarNameAndType<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-ForExpr-ForLetReturn">
                     <lhs>ForLetReturn</lhs>
                     <rhs>
                        <nt def="prod-xpath40-ForExpr">ForExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-LetExpr">LetExpr<!--$idref_lang_part = xpath40- --></nt>  |  ("return"  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>)</rhs>
                  </prod>

                  <prod id="doc-xpath40-ForExpr-LetExpr">
                     <lhs>LetExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-LetClause">LetClause<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-ForLetReturn">ForLetReturn<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>
               </scrap>
               <p>A <code nobreak="false">for</code> expression is evaluated as follows:</p>
               <olist>
                  <item>
                     <p>If the <nt def="prod-xpath40-ForClause">ForClause<!--$spec = xpath40--></nt> includes multiple 
                  <nt def="prod-xpath40-ForBinding">ForBinding<!--$spec = xpath40--></nt>s with a comma separator, 
                  the <code nobreak="false">for</code>expression is first expanded to a set of nested <code nobreak="false">for</code> 
                  expressions, each of which contains a single <nt def="prod-xpath40-ForBinding">ForBinding<!--$spec = xpath40--></nt>.
               More specifically, every separating comma is replaced by <code nobreak="false">for</code>.</p>
                     <example>
                        <head>Example:</head>
                        <p>The expression:</p>
                        <eg xml:space="preserve">for $x in X, $y in Y return $x + $y</eg>
                        <p>is expanded to:</p>
                        <eg xml:space="preserve">for $x in X for $y in Y return $x + $y</eg>
                     </example>
                  </item>
                  <item>
                     <p>Having performed this expansion, 
                  variables bound in the <nt def="prod-xpath40-ForClause">ForClause<!--$spec = xpath40--></nt>
                  are called the <term>range variables</term>,
                  the variable named in the <nt def="prod-xpath40-PositionalVar">PositionalVar<!--$spec = xpath40--></nt> (if present)
                  is called the <term>position variable</term>,
                  the expression that follows the <code nobreak="false">in</code> keyword is called the <term>binding expression</term>, 
                  and the expression in the <nt def="prod-xpath40-ForLetReturn">ForLetReturn<!--$spec = xpath40--></nt> part 
                  (that is, the following <nt def="doc-xpath40-LetExpr">LetExpr<!--$spec = xpath40--></nt> or
                  <nt def="doc-xpath40-ForExpr">ForExpr<!--$spec = xpath40--></nt>, or the <nt def="doc-xpath40-ExprSingle">ExprSingle<!--$spec = xpath40--></nt> 
                  that follows the <code nobreak="false">return</code> keyword) is called the <term>return expression</term>. 
               </p>
                     <p>
                        <termdef id="dt-binding-collection-xp" term="binding collection">The 
                  result of evaluating the <term>binding expression</term> in a 
                  <code nobreak="false">for</code> expression is called the 
                  <term>binding collection</term>
                        </termdef>.</p>
                  </item>
                  <item>
                     <p>If a <term>position variable</term> is declared, its type is implicitly
                  <code nobreak="false">xs:integer</code>. Its name (as an <termref def="dt-expanded-qname"/>) must be
               different from the name of a <term>range variable</term> declared in the same
                <nt def="prod-xpath40-ForBinding">ForBinding<!--$spec = xpath40--></nt>.  
                  <errorref spec="XQ" class="ST" code="0089"/>.
               </p>
                  </item>
                  <item>
                     <p>When a <nt def="prod-xpath40-ForItemBinding">ForItemBinding<!--$spec = xpath40--></nt> is used (that is, when none
                  of the keywords <code nobreak="false">member</code>, <code nobreak="false">key</code>, or <code nobreak="false">value</code>
                  is used), the expression iterates over the items in a sequence:
                  <olist>
                           <item>
                              <p>If a <nt def="prod-xpath40-TypeDeclaration">TypeDeclaration<!--$spec = xpath40--></nt>
                        is present then each item in the <termref def="dt-binding-collection-xp"/>
                        is converted to the specified type by applying the <termref def="dt-coercion-rules"/>.</p>
                           </item>
                           <item>
                              <p>The <term>return expression</term> is evaluated once 
                        for each item in the <termref def="dt-binding-collection-xp"/>, with a dynamic context in which
                        the <term>range variable</term> is bound to that item, and the <term>position variable</term> 
                        (if present) is bound to the one-based position of that item in the 
                        <termref def="dt-binding-collection-xp"/>, as an instance of type 
                        <code nobreak="false">xs:integer</code>.</p>
                           </item>
                           <item>
                              <p>The result of the <code nobreak="false">for</code> expression is the <termref def="dt-sequence-concatenation"/>
                        of the results of the successive evaluations of the <term>return expression</term>.</p>
                           </item>
                        </olist>
                     </p>
                  </item>
                  <item>
                     <p>When the <code nobreak="false">member</code> keyword is present:
                  <olist>
                           <item>
                              <p>The value of the <termref def="dt-binding-collection-xp"/> must be a single array.
                        Otherwise, a <termref def="dt-type-error">type error</termref> is raised: <errorref class="TY" code="0141"/>.
                        However, the coercion rules also allow a JNode whose <term>·jvalue·</term> is an array to be supplied.
                     </p>
                           </item>
                           <item>
                              <p>If a <nt def="prod-xpath40-TypeDeclaration">TypeDeclaration<!--$spec = xpath40--></nt>
                        is present then each member of the <termref def="dt-binding-collection-xp"/> array
                        is converted to the specified type by applying the <termref def="dt-coercion-rules"/>.
                        (Recall that this can be any sequence, not necessarily a single item). </p>
                           </item>
                           <item>
                              <p>The result of the single-variable <code nobreak="false">for member</code> expression is obtained
                        by evaluating the <term>return expression</term> once 
                        for each member of that array, with the range variable bound to that member </p>
                           </item>
                           <item>
                              <p>The <term>return expression</term> is evaluated once 
                        for each member of the <termref def="dt-binding-collection-xp"/> array, 
                        with a dynamic context in which
                        the <term>range variable</term> is bound to that member, and the <term>position variable</term> 
                        (if present) is bound to the one-based position of that member in the <termref def="dt-binding-collection-xp"/>.</p>
                           </item>
                           <item>
                              <p>The result of the <code nobreak="false">for</code> expression is the <termref def="dt-sequence-concatenation"/>
                        of the results of the successive evaluations of the <term>return expression</term>.</p>
                              <p>Note that the result is a sequence, not an array.</p>
                           </item>
                        </olist>
                     </p>
                  </item>
                  <item>
                     <p>When the <code nobreak="false">key</code> and/or <code nobreak="false">value</code> keywords are present:
                  <olist>
                           <item>
                              <p>The value of the <termref def="dt-binding-collection-xp"/> must be a single map.
                        Otherwise, a <termref def="dt-type-error">type error</termref> is raised: 
                        <errorref class="TY" code="0141"/>. However, the coercion rules also allow a JNode
                        whose <term>·jvalue·</term> is a map to be supplied.
                        The map is treated as a sequence of key/value
                        pairs, in <termref def="dt-implementation-dependent"/> order.
                     </p>
                           </item>
                           <item>
                              <p>If the <code nobreak="false">key</code> keyword is present, then the corresponding
                     variable is bound to the key part of the key/value pair.</p>
                           </item>
                           <item>
                              <p>If the <code nobreak="false">value</code> keyword is present, then the corresponding
                     variable is bound to the value part of the key/value pair.</p>
                           </item>
                           <item>
                              <p>If both the <code nobreak="false">key</code> and <code nobreak="false">value</code> keywords are present, 
                        then the corresponding variables must have distinct names.
                        <errorref spec="XQ" class="ST" code="0089"/>.</p>
                           </item>
                           <item>
                              <p>If a <nt def="prod-xpath40-TypeDeclaration">TypeDeclaration<!--$spec = xpath40--></nt>
                        is present for the key, then each key is converted to the specified type by 
                        applying the <termref def="dt-coercion-rules"/>.</p>
                           </item>
                           <item>
                              <p>If a <nt def="prod-xpath40-TypeDeclaration">TypeDeclaration<!--$spec = xpath40--></nt>
                        is present for the value, then each value is converted to the specified type by 
                        applying the <termref def="dt-coercion-rules"/>.</p>
                           </item>
                           <item>
                              <p>The result of the single-variable <code nobreak="false">for key/value</code> expression is obtained
                        by evaluating the <term>return expression</term> once 
                        for each entry in the map, with the range variables bound to that entry as described.</p>
                           </item>
                           <item>
                              <p>The <term>return expression</term> is evaluated once 
                        for each entry of the <termref def="dt-binding-collection-xp"/> map, 
                        with a dynamic context in which
                        the <code nobreak="false">key</code>
                                 <term>range variable</term> (if present)
                        is bound to the key part of that entry, 
                        the <code nobreak="false">value</code>
                                 <term>range variable</term> (if present)
                        is bound to the value part of that entry, and the <term>position variable</term> 
                        (if present) is bound to the one-based position of that entry in the 
                        <termref def="dt-implementation-dependent"/> ordering of the 
                        <termref def="dt-binding-collection-xp"/>.</p>
                           </item>
                           <item>
                              <p>The result of the <code nobreak="false">for</code> expression is the <termref def="dt-sequence-concatenation"/>
                        of the results of the successive evaluations of the <term>return expression</term>.</p>
                              <p>Note that the result is a sequence, not a map.</p>
                           </item>
                        </olist>
                     </p>
                  </item>
               </olist>
               <p role="xpath">The following example illustrates the use of a <code nobreak="false">for</code> expression in restructuring an input document. The example is based on the following
input:</p>
               <eg xml:space="preserve">&lt;bib&gt;
  &lt;book&gt;
    &lt;title&gt;TCP/IP Illustrated&lt;/title&gt;
    &lt;author&gt;Stevens&lt;/author&gt;
    &lt;publisher&gt;Addison-Wesley&lt;/publisher&gt;
  &lt;/book&gt;
  &lt;book&gt;
    &lt;title&gt;Advanced Programming in the Unix Environment&lt;/title&gt;
    &lt;author&gt;Stevens&lt;/author&gt;
    &lt;publisher&gt;Addison-Wesley&lt;/publisher&gt;
  &lt;/book&gt;
  &lt;book&gt;
    &lt;title&gt;Data on the Web&lt;/title&gt;
    &lt;author&gt;Abiteboul&lt;/author&gt;
    &lt;author&gt;Buneman&lt;/author&gt;
    &lt;author&gt;Suciu&lt;/author&gt;
  &lt;/book&gt;
&lt;/bib&gt;</eg>
               <p>The following example transforms the input document into a list in
which each author’s name appears only once, followed by a list of
titles of books written by that author. This example assumes that the
context value is the <code nobreak="false">bib</code> element in the input
document.</p>
               <eg role="parse-test" xml:space="preserve"><phrase role="parse-test">for $a in distinct-values(book/author)
return ((book/author[. = $a])[1], book[author = $a]/title)</phrase>
         </eg>
               <p>The result of the above expression consists of the following
sequence of elements. The titles of books written by a given author
are listed after the name of the author.

The ordering of <code nobreak="false">author</code> elements in the result is <termref def="dt-implementation-dependent">implementation-dependent</termref> due to the semantics of the <function>fn:distinct-values</function> function.</p>
               <eg xml:space="preserve">&lt;author&gt;Stevens&lt;/author&gt;
&lt;title&gt;TCP/IP Illustrated&lt;/title&gt;
&lt;title&gt;Advanced Programming in the Unix environment&lt;/title&gt;
&lt;author&gt;Abiteboul&lt;/author&gt;
&lt;title&gt;Data on the Web&lt;/title&gt;
&lt;author&gt;Buneman&lt;/author&gt;
&lt;title&gt;Data on the Web&lt;/title&gt;
&lt;author&gt;Suciu&lt;/author&gt;
&lt;title&gt;Data on the Web&lt;/title&gt;</eg>
               <p>The following example illustrates a <code nobreak="false">for</code> expression containing more than one variable:</p>
               <eg role="parse-test" xml:space="preserve"><phrase role="parse-test">for $i in (10, 20),
    $j in (1, 2)
return ($i + $j)</phrase>
         </eg>
               <p>The result of the above expression, expressed as a sequence of numbers, is as follows: <code nobreak="false">11, 12, 21, 22</code>
               </p>
               <p>The scope of a variable bound in a <code nobreak="false">for</code> expression is the <term>return expression</term>. 
            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  <code nobreak="false">for</code> expression:</p>
               <eg role="parse-test" xml:space="preserve"><phrase role="parse-test">for $x in $z, $y in f($x)
return g($x, $y)</phrase>
         </eg>
               <p>The following example illustrates processing of an array.</p>
               <eg xml:space="preserve">for member $map in parse-json('[{ "x": 1, "y": 2 }, { "x": 10, "y": 20 }]') 
return $map ! (?x + ?y)</eg>
               <p>The result is the sequence <code nobreak="false">(3, 30)</code>.</p>
               <p>The following example illustrates processing of a map.</p>
               <eg xml:space="preserve">for key $key value $value in { "x": 1, "y": 2, "z: 3 }
return `{$key}={$value}`</eg>
               <p>The result is the sequence <code nobreak="false">("x=1", "y=2", "z=3")</code> (but
         not necessarily in that order).</p>
               <note>
                  <p>The focus for evaluation of the <code nobreak="false">return</code> clause of a <code nobreak="false">for</code> expression
is the same as the focus for evaluation of the <code nobreak="false">for</code> expression itself. The
following example, which attempts to find the total value of a set of
order-items, is therefore incorrect:

</p>
                  <eg role="error" xml:space="preserve">sum(for $i in order-item return @price * @qty)</eg>
                  <p>

Instead, the expression must be written to use the variable bound in the <code nobreak="false">for</code> clause:</p>
                  <eg role="parse-test" xml:space="preserve">sum(for $i in order-item return $i!(@price * @qty))</eg>
               </note>
               <note diff="add" at="2023-02-16">
                  <p>XPath 4.0 allows the format:</p>
                  <eg role="parse-test" xml:space="preserve">for $order in //orders
for $line in $order/order-line
return $line/value</eg>
                  <p>primarily because it is familiar to XQuery users, some of whom may regard it as more
            readable than the XPath 3.1 alternative which uses a comma in place of the second <code nobreak="false">for</code>.</p>
               </note>
            </div3>
            <div3 id="id-let-expressions" role="xpath">
               <head>Let Expressions</head>
               <changes>
                  <change issue="22" PR="28" date="2020-12-18">
               Multiple <code nobreak="false">for</code> and <code nobreak="false">let</code> clauses can be combined
               in an expression without an intervening <code nobreak="false">return</code> keyword.
            </change>
                  <change issue="796" PR="1131" date="2024-04-01">
               The type of a variable used in a <code nobreak="false">let</code> expression can be declared.
            </change>
                  <change issue="37" PR="2055" date="2025-06-17">
               Sequences, arrays, and maps can be destructured in a <code nobreak="false">let</code> 
               expression to extract their components into multiple variables. 
            </change>
               </changes>
               <p>XPath allows a variable to be declared and bound to a value using a <term>let expression</term>.</p>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-LetExpr">
                     <lhs>LetExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-LetClause">LetClause<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-ForLetReturn">ForLetReturn<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-LetExpr-LetClause">
                     <lhs>LetClause</lhs>
                     <rhs>"let"  (<nt def="prod-xpath40-LetBinding">LetBinding<!--$idref_lang_part = xpath40- --></nt> ++ ",")</rhs>
                  </prod>

                  <prod id="doc-xpath40-LetExpr-LetBinding">
                     <lhs>LetBinding</lhs>
                     <rhs>
                        <nt def="prod-xpath40-LetValueBinding">LetValueBinding<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-LetSequenceBinding">LetSequenceBinding<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-LetArrayBinding">LetArrayBinding<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-LetMapBinding">LetMapBinding<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-LetExpr-LetValueBinding">
                     <lhs>LetValueBinding</lhs>
                     <rhs>
                        <nt def="prod-xpath40-VarNameAndType">VarNameAndType<!--$idref_lang_part = xpath40- --></nt>  ":="  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-LetExpr-VarNameAndType">
                     <lhs>VarNameAndType</lhs>
                     <rhs>"$"  <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-TypeDeclaration">TypeDeclaration<!--$idref_lang_part = xpath40- --></nt>?</rhs>
                  </prod>

                  <prod id="doc-xpath40-LetExpr-EQName">
                     <lhs>EQName</lhs>
                     <rhs>
                        <nt def="prod-xpath40-QName">QName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-LetExpr-TypeDeclaration">
                     <lhs>TypeDeclaration</lhs>
                     <rhs>"as"  <nt def="prod-xpath40-SequenceType">SequenceType<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-LetExpr-ExprSingle">
                     <lhs>ExprSingle</lhs>
                     <rhs>
                        <nt def="prod-xpath40-ForExpr">ForExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-LetExpr">LetExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-QuantifiedExpr">QuantifiedExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-IfExpr">IfExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-OrExpr">OrExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-LetExpr-LetSequenceBinding">
                     <lhs>LetSequenceBinding</lhs>
                     <rhs>"$"  "("  (<nt def="prod-xpath40-VarNameAndType">VarNameAndType<!--$idref_lang_part = xpath40- --></nt> ++ ",")  ")"  <nt def="prod-xpath40-TypeDeclaration">TypeDeclaration<!--$idref_lang_part = xpath40- --></nt>?  ":="  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-LetExpr-SequenceType">
                     <lhs>SequenceType</lhs>
                     <rhs>("empty-sequence"  "("  ")")<br/>|  (<nt def="prod-xpath40-ItemType">ItemType<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-OccurrenceIndicator">OccurrenceIndicator<!--$idref_lang_part = xpath40- --></nt>?)</rhs>
                  </prod>

                  <prod id="doc-xpath40-LetExpr-LetArrayBinding">
                     <lhs>LetArrayBinding</lhs>
                     <rhs>"$"  "["  (<nt def="prod-xpath40-VarNameAndType">VarNameAndType<!--$idref_lang_part = xpath40- --></nt> ++ ",")  "]"  <nt def="prod-xpath40-TypeDeclaration">TypeDeclaration<!--$idref_lang_part = xpath40- --></nt>?  ":="  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-LetExpr-LetMapBinding">
                     <lhs>LetMapBinding</lhs>
                     <rhs>"$"  "{"  (<nt def="prod-xpath40-VarNameAndType">VarNameAndType<!--$idref_lang_part = xpath40- --></nt> ++ ",")  "}"  <nt def="prod-xpath40-TypeDeclaration">TypeDeclaration<!--$idref_lang_part = xpath40- --></nt>?  ":="  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-LetExpr-ForLetReturn">
                     <lhs>ForLetReturn</lhs>
                     <rhs>
                        <nt def="prod-xpath40-ForExpr">ForExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-LetExpr">LetExpr<!--$idref_lang_part = xpath40- --></nt>  |  ("return"  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>)</rhs>
                  </prod>

                  <prod id="doc-xpath40-LetExpr-ForExpr">
                     <lhs>ForExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-ForClause">ForClause<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-ForLetReturn">ForLetReturn<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>
               </scrap>
               <p>A let expression is evaluated as follows:</p>
               <olist>
                  <item>
                     <p>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 <code nobreak="false">let</code>.</p>
                     <example>
                        <head>Example:</head>
                        <p>The expression:</p>
                        <eg xml:space="preserve">let $x := 4, $y := 3 return $x + $y</eg>
                        <p>is expanded to:</p>
                        <eg xml:space="preserve">let $x := 4 let $y := 3 return $x + $y</eg>
                     </example>
                  </item>
                  <item>
                     <p>In a <nt def="prod-xpath40-LetValueBinding">LetValueBinding<!--$spec = xpath40--></nt>
                  such as <code nobreak="false">let $<var>V</var> as <var>T</var> := <var>EXPR</var>
                        </code>:</p>
                     <olist>
                        <item>
                           <p>The variable <var>V</var> is called the <term>range variable</term>.</p>
                        </item>
                        <item>
                           <p>The sequence type <var>T</var> is called the <term>declared type</term>.
                     If there is no declared type, then <code nobreak="false">item()*</code> is assumed.</p>
                        </item>
                        <item>
                           <p>The expression <var>EXPR</var> is evaluated, and its value is converted
                     to the declared type by applying the <termref def="dt-coercion-rules"/>.
                     The resulting value is called the <term>binding sequence</term>.</p>
                        </item>
                     </olist>
                  </item>
                  <item>
                     <p>In a <nt def="prod-xpath40-LetSequenceBinding">LetSequenceBinding<!--$spec = xpath40--></nt>
                  such as <code nobreak="false">let $( $<var>A1</var> as <var>T1</var>, $<var>A2</var> as <var>T2</var>, ...
                     , $<var>A/n</var> as <var>T/n</var> ) as <var>ST</var> := <var>EXPR</var>
                        </code>:</p>
                     <olist>
                        <item>
                           <p>The sequence type <var>ST</var> is called the <term>declared sequence type</term>.
                     If there is no declared sequence type, then <code nobreak="false">item()*</code> is assumed.</p>
                        </item>
                        <item>
                           <p>The expression <var>EXPR</var> is evaluated, and its value is converted
                     to the declared sequence type <var>ST</var> by applying the <termref def="dt-coercion-rules"/>.
                     Call the resulting (coerced) value <var>V</var>.</p>
                        </item>
                        <item>
                           <p>Each variable <var>A/i</var> (for <var>i</var> in 1 to <var>n</var>-1)
                     is effectively replaced by a <nt def="prod-xpath40-LetValueBinding">LetValueBinding<!--$spec = xpath40--></nt>
                        of the form <code nobreak="false">let <var>A/i</var> as <var>T/i</var> := items-at(<var>V</var>, <var>i</var>)</code>.
                     That is, a <term>range variable</term> named <var>A/i</var> is declared, whose <term>binding sequence</term>
                     is the item <var>V[ i ]</var>, after coercion to the type <var>T/i</var> if specified.
                     If <var>T/i</var> is absent, no further coercion takes place (the default is effectively
                     <code nobreak="false">item()?</code>).</p>
                        </item>
                        <item>
                           <p>The last variable <var>A/n</var> 
                     is effectively replaced by a <nt def="prod-xpath40-LetValueBinding">LetValueBinding<!--$spec = xpath40--></nt>
                        of the form <code nobreak="false">let <var>A/n</var> as <var>T/n</var> := subsequence(<var>V</var>, <var>n</var>)</code>.
                        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).
                     </p>
                        </item>
                     </olist>
                     <note>
                        <p>If <var>i</var> exceeds the length of the sequence <var>V</var>, then
                        <var>A/i</var> is bound to the empty sequence. This will cause a type error if
                        type <var>T/i</var> does not permit the empty sequence.</p>
                     </note>
                     <note>
                        <p>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 <code nobreak="false">$_</code>:
                        for example <code nobreak="false">let $( $_, $_, $x ) := <var>EXPR</var>
                           </code> effectively
                        binds <code nobreak="false">$x</code> to the third item in the sequence and causes the first two
                        items to be ignored.</p>
                     </note>
                     <example>
                        <head>Example:</head>
                        <p>The expression:</p>
                        <eg xml:space="preserve">let $( $a, $b as xs:integer, $local:c ) := (2, 4, 6)
return $a + $b + $local:c</eg>
                        <p>is expanded to:</p>
                        <eg xml:space="preserve">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</eg>
                        <p>where <code nobreak="false">$temp</code> is some variable name that is otherwise unused.</p>
                     </example>
                     <example>
                        <head>Example:</head>
                        <p>Consider the element <var>$E</var> := <code nobreak="false">&lt;e A="p q r" B="x y z"/&gt;</code>.</p>
                        <p>Then consider the expression:</p>
                        <eg xml:space="preserve">let $( $a, $b ) := $E!(@A, @B)</eg>
                        <p>Here the binding sequence is a sequence of two attribute nodes, so
                        <code nobreak="false">$a</code> is bound to the attribute <code nobreak="false">@A</code>, and <code nobreak="false">$b</code>
                        is bound to the attribute node <code nobreak="false">@B</code>.</p>
                        <p>If the operator <code nobreak="false">"!"</code> were replaced by <code nobreak="false">"/"</code>, or if
                        <code nobreak="false">","</code> were replaced by <code nobreak="false">"|"</code>, 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.</p>
                        <p>Now consider what happens when a declared sequence type is added:</p>
                        <eg xml:space="preserve">let $( $a, $b ) as xs:string* := $E!(@A, @B)</eg>
                        <p>The sequence of two attribute nodes is now atomized to form a sequence of strings.
                        The first string in this sequence is bound to <code nobreak="false">$a</code>, and the remainder
                        of the sequence is bound to <code nobreak="false">$b</code>. If the element <code nobreak="false">$E</code> is untyped,
                        this will result in <code nobreak="false">$a</code> being bound to the <code nobreak="false">xs:untypedAtomic</code>
                        value <code nobreak="false">"p q r"</code>, while <code nobreak="false">$b</code> is bound to the <code nobreak="false">xs:untypedAtomic</code>
                        value <code nobreak="false">"x y z"</code>.</p>
                        <p>However, suppose that the element <code nobreak="false">$E</code> has been validated against a schema
                        that defines both attributes <code nobreak="false">@A</code> and <code nobreak="false">@B</code> as list types with
                        item type <code nobreak="false">xs:string</code>. In this case, the atomized value of <code nobreak="false">$E</code>
                        will be a sequence of six strings. The variable <code nobreak="false">$a</code> is bound to the first
                        of these strings (that is, <code nobreak="false">"p"</code>), while <code nobreak="false">$b</code> is bound to a
                        sequence containing the remaining five strings (that is, <code nobreak="false">("q", "r", "x", "y", "z")</code>).</p>
                        <p>By contrast, if the expression is written as:</p>
                        <eg xml:space="preserve">let $( $a as xs:string*, $b as xs:string* ) := $E!(@A, @B)</eg>
                        <p>then <code nobreak="false">$a</code> is bound to the result of atomizing the first attribute
                     (the <code nobreak="false">untypedAtomic</code> value <code nobreak="false">"p q r"</code> in the untyped case, or
                     the sequence of three strings <code nobreak="false">("p", "q", "r")</code> in the schema-validated case),
                     while <code nobreak="false">$b</code> is similarly bound to the result of atomizing the second attribute.</p>
                     </example>
                  </item>
                  <item>
                     <p>In a <nt def="prod-xpath40-LetArrayBinding">LetArrayBinding<!--$spec = xpath40--></nt>
                  such as <code nobreak="false">let $[ $<var>A1</var> as <var>T1</var>, $<var>A2</var> as <var>T2</var>, ...
                     , $<var>A/n</var> as <var>T/n</var> ] as <var>AT</var> := <var>EXPR</var>
                        </code>:</p>
                     <olist>
                        <item>
                           <p>The sequence type <var>AT</var> is called the <term>declared array type</term>.
                     If there is no declared array type, then <code nobreak="false">array(*)</code> is assumed.</p>
                        </item>
                        <item>
                           <p>The expression <var>EXPR</var> is evaluated, and its value is converted
                     to the declared array type <var>AT</var> by applying the <termref def="dt-coercion-rules"/>.
                     A type error <errorref class="TY" code="0004"/> is raised if the result is not
                        a <termref def="dt-singleton"/> array.
                     Call the resulting (coerced) value <var>V</var>.</p>
                        </item>
                        <item>
                           <p>Each variable <var>A/i</var> (for <var>i</var> in 1 to <var>n</var>)
                     is effectively replaced by a <nt def="prod-xpath40-LetValueBinding">LetValueBinding<!--$spec = xpath40--></nt>
                        of the form <code nobreak="false">let <var>A/i</var> as <var>T/i</var> := array:get(<var>V</var>, <var>i</var>)</code>.
                     That is, a <term>range variable</term> named <var>A/i</var> is declared, whose <term>binding sequence</term>
                     is the array member <var>V ? i</var>, after coercion to the type <var>T/i</var> if specified.
                     If <var>T/i</var> is absent, no further coercion takes place (the default is effectively
                     <code nobreak="false">item()*</code>).</p>
                           <note>
                              <p>If <var>i</var> exceeds the length of the array <var>V</var>, then
                        a dynamic error <xerrorref spec="FO" class="AR" code="0001"/> is raised.</p>
                           </note>
                           <note>
                              <p>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 <code nobreak="false">$_</code>:
                        for example <code nobreak="false">let $( $_, $_, $x ) := <var>EXPR</var>
                                 </code> effectively
                        binds <code nobreak="false">$x</code> to the third item in the sequence and causes the first two
                        items to be ignored.</p>
                           </note>
                           <example>
                              <head>Example:</head>
                              <p>The expression:</p>
                              <eg xml:space="preserve">let $[ $a, $b as xs:integer, $local:c ] := [ 2, 4, 6 ]
return $a + $b + $local:c</eg>
                              <p>is expanded to:</p>
                              <eg xml:space="preserve">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</eg>
                              <p>where <code nobreak="false">$temp</code> is some variable name that is otherwise unused.</p>
                           </example>
                        </item>
                     </olist>
                  </item>
                  <item>
                     <p>In a <nt def="prod-xpath40-LetMapBinding">LetMapBinding<!--$spec = xpath40--></nt>
                  such as <code nobreak="false">let ${ $<var>A1</var> as <var>T1</var>, $<var>A2</var> as <var>T2</var>, ...
                     , $<var>A/n</var> as <var>T/n</var> } as <var>MT</var> := <var>EXPR</var>
                        </code>:</p>
                     <olist>
                        <item>
                           <p>The sequence type <var>MT</var> is called the <term>declared map type</term>.
                     If there is no declared map type, then <code nobreak="false">map(*)</code> is assumed.</p>
                        </item>
                        <item>
                           <p>The expression <var>EXPR</var> is evaluated, and its value is converted
                     to the declared map type <var>MT</var> by applying the <termref def="dt-coercion-rules"/>.
                     A type error <errorref class="TY" code="0004"/> is raised if the result is not
                        a <termref def="dt-singleton"/> map.
                     Call the resulting (coerced) value <var>V</var>.</p>
                        </item>
                        <item>
                           <p>Each variable <var>A/i</var> (for <var>i</var> in 1 to <var>n</var>)
                     is effectively replaced by a <nt def="prod-xpath40-LetValueBinding">LetValueBinding<!--$spec = xpath40--></nt>
                        of the form <code nobreak="false">let <var>A/i</var> as <var>T/i</var> := map:get(<var>V</var>, "<var>N/i</var>", ())</code>,
                        where <var>N/i</var> is the local part of the name of the variable <var>A/i</var>.
                     That is, a <term>range variable</term> named <var>A/i</var> is declared, whose <term>binding sequence</term>
                     is the value of the map entry in <var>V</var> whose key is an <code nobreak="false">xs:string</code> (or <code nobreak="false">xs:anyURI</code> or <code nobreak="false">xs:untypedAtomic</code>)
                        equal to the local part of the variable name, after coercion to the type <var>T/i</var> if specified.
                     If <var>T/i</var> is absent, no further coercion takes place (the default is effectively
                     <code nobreak="false">item()*</code>).</p>
                           <note>
                              <p>If there is no entry in the map with a key corresponding to the variable
                           name, then the variable
                        <var>A/i</var> is bound to the empty sequence. This will cause a type error if
                        type <var>T/i</var> does not permit the empty sequence.</p>
                           </note>
                           <note>
                              <p>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 <code nobreak="false">NCNames</code>.</p>
                           </note>
                           <example>
                              <head>Example:</head>
                              <p>The expression:</p>
                              <eg xml:space="preserve">let ${ $a, $b as xs:integer, $local:c } := { "a": 2, "b": 4, "c": 6, "d": 8 }
return $a + $b + $local:c</eg>
                              <p>is expanded to:</p>
                              <eg xml:space="preserve">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</eg>
                              <p>where <code nobreak="false">$temp</code> is some variable name that is otherwise unused.</p>
                           </example>
                        </item>
                     </olist>
                  </item>
                  <item>
                     <p>The expression in the <nt def="prod-xpath40-ForLetReturn">ForLetReturn<!--$spec = xpath40--></nt> part 
                  (that is, the following <nt def="doc-xpath40-LetExpr">LetExpr<!--$spec = xpath40--></nt> or
                  <nt def="doc-xpath40-ForExpr">ForExpr<!--$spec = xpath40--></nt>, or the <nt def="doc-xpath40-ExprSingle">ExprSingle<!--$spec = xpath40--></nt> 
                  that follows the <code nobreak="false">return</code> keyword) is
called the <term>return expression</term>. The result of the let expression is obtained
by evaluating the <term>return expression</term> with a dynamic context in which each range variable is bound to the
corresponding binding sequence. </p>
                  </item>
               </olist>
               <p>The scope of a variable bound in a let expression is the
            <term>return expression</term>.
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:</p>
               <eg role="parse-test" xml:space="preserve">
let $x := doc('a.xml')/*, $y := $x//*
return $y[@value gt $x/@min]
</eg>
               <note diff="add" at="2023-02-09">
                  <p>It is not required that the variables should have distinct names. It is permitted, 
               for example, to write:</p>
                  <eg role="parse-test" xml:space="preserve">
let $x := "[A fine romance]"
let $x := substring-after($x, "[")
let $x := substring-before($x, "]")
return upper-case($x)
</eg>
                  <p>which returns the result <code nobreak="false">"A FINE ROMANCE"</code>. 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.</p>
               </note>
            </div3>
         </div2>
         <div2 id="id-maps-and-arrays">
            <head>Maps and Arrays</head>
            <p>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.</p>
            <p diff="del" at="B">In previous versions of the language, element structures and
sequences were the only complex data structures.  We are adding maps
and arrays to XPath 4.0 in order to provide lightweight data
structures that are easier to optimize and less complex to use for
intermediate processing and to allow programs to easily combine XML
processing with JSON processing.</p>
            <note>
               <p>The XPath 4.0 specification focuses on syntax provided for maps
  and arrays, especially constructors and lookup.</p>
               <p>Some of the functionality typically needed for maps and
  arrays is provided by functions defined in <xspecref spec="FO40" ref="maps"/>
               and <xspecref spec="FO40" ref="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.</p>
            </note>
            <div3 id="id-maps">
               <head>Maps</head>
               <changes>
                  <change issue="1651" PR="1703" date="2025-01-14">Ordered maps are introduced.</change>
               </changes>
               <p>
                  <termdef term="map" id="dt-map">A <term>map</term> is a function
  that associates a set of keys with values, resulting in a collection
  of key / value pairs.</termdef>
                  <termdef term="entry" id="dt-entry">Each key / value pair in a map
  is called an <term>entry</term>.</termdef>
                  <termdef term="associated value" id="dt-associated-value">The value
  associated with a given key is called the <term>associated
  value</term> of the key.</termdef>
               </p>
               <p>Maps and their properties are defined in the data model:
               see <xspecref spec="DM40" ref="map-items"/>. For an overview
            of the functions available for processing maps,
            see <xspecref spec="FO40" ref="maps"/>.</p>
               <note>
                  <p>Maps in XPath 4.0 are ordered.
                  The effect of this property is explained 
                  in <xspecref spec="DM40" ref="map-items"/>. 
                  In an ordered map, the order of entries is predictable
                  and depends on the order in which they were added to the map.</p>
               </note>
               <div4 id="id-map-constructors">
                  <head>Map Constructors</head>
                  <changes>
                     <change issue="1070" PR="1071" date="2024-03-26">
                     In map constructors, the keyword <code nobreak="false">map</code> is now optional, so 
                     <code nobreak="false">map { 0: false(), 1: true() }</code> can now be written <code nobreak="false">{ 0: false(), 1: true() }</code>,
                     provided it is used in a context where this creates no ambiguity.
                  </change>
                     <change issue="1651" PR="1703" date="2025-01-14">The order of key-value
                     pairs in the map constructor is now retained in the constructed map.</change>
                     <change issue="2003" PR="2094" date="2025-07-13">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.</change>
                  </changes>
                  <p>A map can be created using a <nt def="doc-xpath40-MapConstructor">MapConstructor<!--$spec = xpath40--></nt>.</p>
                  <p>Examples are:</p>
                  <eg xml:space="preserve">{ "a": 1, "b": 2 }</eg>
                  <p>which constructs a map with two entries, and</p>
                  <eg xml:space="preserve">{ "a": 1, if ($condition) { map{ "b": 2 } } }</eg>
                  <p>which constructs a map having either one or two entries depending on the
               value of <code nobreak="false">$condition</code>.</p>
                  <p>Both the keys and the values in a map constructor can be supplied as expressions
               rather than as constants.</p>
                  <scrap headstyle="show">
                     <prod id="doc-xpath40-MapConstructor">
                        <lhs>MapConstructor</lhs>
                        <rhs>"map"?  "{"  (<nt def="prod-xpath40-MapConstructorEntry">MapConstructorEntry<!--$idref_lang_part = xpath40- --></nt> ** ",")  "}"</rhs>
                     </prod>

                     <prod id="doc-xpath40-MapConstructor-MapConstructorEntry">
                        <lhs>MapConstructorEntry</lhs>
                        <rhs>
                           <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>  (":"  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>)?</rhs>
                     </prod>

                     <prod id="doc-xpath40-MapConstructor-ExprSingle">
                        <lhs>ExprSingle</lhs>
                        <rhs>
                           <nt def="prod-xpath40-ForExpr">ForExpr<!--$idref_lang_part = xpath40- --></nt>
                           <br/>|  <nt def="prod-xpath40-LetExpr">LetExpr<!--$idref_lang_part = xpath40- --></nt>
                           <br/>|  <nt def="prod-xpath40-QuantifiedExpr">QuantifiedExpr<!--$idref_lang_part = xpath40- --></nt>
                           <br/>|  <nt def="prod-xpath40-IfExpr">IfExpr<!--$idref_lang_part = xpath40- --></nt>
                           <br/>|  <nt def="prod-xpath40-OrExpr">OrExpr<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>
                  </scrap>
                  <note>
                     <p>The keyword <code nobreak="false">map</code> was required in earlier versions
                  of the language; in XPath 4.0 it becomes optional. There may be cases
                  where using the keyword improves readability.</p>
                     <p>In order to allow the <code nobreak="false">map</code> keyword to be omitted,
                  an incompatible change has been made to XQuery computed element
                  and attribute constructors: if the name of the constructed element
                  or attribute is a language keyword, it must now be written using the
                  <code nobreak="false">QNameLiteral</code> syntax, for example <code nobreak="false">element #div {}</code>.</p>
                     <p>Although the grammar allows a <nt def="doc-xpath40-MapConstructor">MapConstructor<!--$spec = xpath40--></nt>
                  to appear within an <nt def="doc-xpath40-EnclosedExpr">EnclosedExpr<!--$spec = xpath40--></nt> (that is, between
                  curly brackets), this may be confusing to readers, and using the <code nobreak="false">map</code>
                  keyword in such cases may improve clarity. The keyword <code nobreak="false">map</code> is used in the
                  second example above to avoid any confusion between the braces required for the
                  <code nobreak="false">then</code> part of the conditional expression, and the braces
                  required for the inner map constructor.</p>
                     <p>If the <nt def="doc-xpath40-EnclosedExpr">EnclosedExpr<!--$spec = xpath40--></nt>
                  appears in a context such as a <nt def="doc-xpath40-StringTemplate">StringTemplate<!--$spec = xpath40--></nt>,
                  the two adjacent left opening braces must at least be separated by whitespace.</p>
                  </note>
                  <p>When a <nt def="prod-xpath40-MapConstructorEntry">MapConstructorEntry<!--$spec = xpath40--></nt> is written as two instances of
               <nt def="doc-xpath40-ExprSingle">ExprSingle<!--$spec = xpath40--></nt> separated by a colon, the first expression
               is evaluated and atomized to form a key, and the second expression is evaluated to form the
               corresponding value. The result is a <xtermref spec="DM40" ref="dt-single-entry-map"/>
               which will be merged into the constructed map, as described below.
               A <termref def="dt-type-error">type error</termref>
                     <errorref class="TY" code="0004"/> occurs if the result of the first
                  expression (after atomization) is not a single atomic item. The result
               of the second expression is used <emph>as is</emph>.</p>
                  <p>When the <nt def="prod-xpath40-MapConstructorEntry">MapConstructorEntry<!--$spec = xpath40--></nt> is written as a
               single instance of <nt def="doc-xpath40-ExprSingle">ExprSingle<!--$spec = xpath40--></nt> with no colon, it must evaluate
               to a sequence of zero or more map items (<errorref class="TY" code="0004"/>).
                  However, the coercion rules also allow a JNode
                  whose <term>·jvalue·</term> is a map (or a sequence of maps) to be supplied.
                  These map items will be merged into the constructed map, as described below.</p>
                  <p>Each contained <nt def="prod-xpath40-MapConstructorEntry">MapConstructorEntry<!--$spec = xpath40--></nt> thus
                  delivers zero or more maps, and the result of the map constructor is a new map
                  obtained by merging these component maps, in order, as if by the <function>map:merge</function>
                  function.</p>
                  <p>
                     <termdef id="dt-same-key" term="same key">Two atomic items <var>K1</var> and
    <var>K2</var> have the <term>same key value</term> if
    
    
      <code nobreak="false">fn:atomic-equal(<var>K1</var>, <var>K2</var>)</code> returns <code nobreak="false">true</code>, as specified in <xspecref spec="FO40" ref="func-atomic-equal" diff="chg" at="2023-01-25"/>
                     </termdef>

    If two or more entries have the <termref def="dt-same-key">same key value</termref> then a dynamic
    error is raised <errorref class="DY" code="0137"/>.
                  
                  The error <rfc2119>may</rfc2119> be raised statically if two or more entries can be determined statically
                  to have the <termref def="dt-same-key">same key value</termref>.

    
    </p>
                  <p>The <xtermref spec="DM40" ref="dt-entry-order"/>
                  of the entries in the constructed map retains the order of the 
                  <nt def="prod-xpath40-MapConstructorEntry">MapConstructorEntry<!--$spec = xpath40--></nt> entries
                  in the input.</p>
                  <example>
                     <head>Constructing a fixed map</head>
                     <p>The following expression constructs a map with seven entries:</p>
                     <eg id="map-weekdays" xml:space="preserve">
{
  "Su" : "Sunday",
  "Mo" : "Monday",
  "Tu" : "Tuesday",
  "We" : "Wednesday",
  "Th" : "Thursday",
  "Fr" : "Friday",
  "Sa" : "Saturday"
}</eg>
                  </example>
                  <example>
                     <head>Constructing a map with conditional entries</head>
                     <p>The following expression constructs a map with either five or seven entries,
                  depending on a supplied condition:</p>
                     <eg xml:space="preserve">
{
  "Mo" : "Monday",
  "Tu" : "Tuesday",
  "We" : "Wednesday",
  "Th" : "Thursday",
  "Fr" : "Friday",
  if ($include-weekends) {
    { "Sa" : "Saturday",
      "Su" : "Sunday"
    }
  }
}</eg>
                     <p>This could also be written:</p>
                     <eg xml:space="preserve">
{
  "Mo" : "Monday",
  "Tu" : "Tuesday",
  "We" : "Wednesday",
  "Th" : "Thursday",
  "Fr" : "Friday",
  { "Sa" : "Saturday",
    "Su" : "Sunday"
  } [$include-weekends]
}</eg>
                  </example>
                  <example>
                     <head>Constructing a map to index nodes</head>
                     <p>The following expression (which uses two nested map constructors)
                  constructs a map that indexes employees by the value 
                  of their <code nobreak="false">@id</code> attribute:</p>
                     <eg xml:space="preserve">{ //employee ! {@id : .} }</eg>
                  </example>
                  <example>
                     <head>Constructing nested maps</head>
                     <p>Maps can nest, and can contain any XDM value. Here is an example of a nested map with values that can be string values, numeric values, or arrays:</p>
                     <eg id="map-book" xml:space="preserve">

{
  "book": {
    "title": "Data on the Web",
    "year": 2000,
    "author": [
      {
        "last": "Abiteboul",
        "first": "Serge"
      },
      {
        "last": "Buneman",
        "first": "Peter"
      },
      {
        "last": "Suciu",
        "first": "Dan"
      }
    ],
    "publisher": "Morgan Kaufmann Publishers",
    "price": 39.95
  }
}
    </eg>
                     <note>
                        <p>The syntax deliberately mimics JSON, but there are a few differences.
               JSON constructs that are not accepted in XPath 4.0 map
               constructors include the keywords <code nobreak="false">true</code>, <code nobreak="false">false</code>,
               and <code nobreak="false">null</code>, and backslash-escaped characters such as <code nobreak="false">"\n"</code>
               in string literals. In an XPath 4.0 map constructor, of course, any literal 
               value can be replaced with an expression.</p>
                     </note>
                  </example>
                  <note>
                     <p>
    In some circumstances, it is necessary to include whitespace before or after the colon
    of a <nt def="prod-xpath40-MapConstructorEntry">MapConstructorEntry<!--$spec = xpath40--></nt> to ensure that it is parsed as intended.
    </p>
                     <p>
    For instance, consider the expression <code nobreak="false">{a:b}</code>.
    Although it matches the EBNF for <nt def="doc-xpath40-MapConstructor">MapConstructor<!--$spec = xpath40--></nt>,
    the “longest terminal” rule (see <specref ref="lexical-structure"/>)
     requires that <code nobreak="false">a:b</code> be parsed as a QName,
    which is likely to result in an error indicating that the prefix <code nobreak="false">a</code>
    has not been declared.
    Changing the expression to <code nobreak="false">{a :b}</code> or <code nobreak="false">{a: b}</code>
    will prevent this, resulting in the intended parse.
    </p>
                     <p>Similarly, consider these three expressions:</p>
                     <eg xml:space="preserve">
{a:b:c}
{a:*:c}
{*:b:c}</eg>
                     <p>
    In each case, the expression matches the EBNF in two different ways,
    but the “longest possible match” rule forces the parse in which
    the first subexpression is <code nobreak="false">a:b</code>, <code nobreak="false">a:*</code>, or <code nobreak="false">*:b</code> (respectively)
    and the second subexpression is <code nobreak="false">c</code>.
    To achieve the alternative parse
    (in which the first expression is merely <code nobreak="false">a</code> or <code nobreak="false">*</code>),
    insert whitespace before and/or after the first colon.
    </p>
                     <p>See <specref ref="lexical-structure"/>.</p>
                  </note>
                  <note>
                     <p>There are also several functions that can be used to construct maps with a variable
               number of entries:</p>
                     <ulist>
                        <item>
                           <p>
                              <function>map:build</function> takes any sequence as input, and for each
                  item in the sequence, it computes a key and a value, by calling user-supplied functions.</p>
                        </item>
                        <item>
                           <p>
                              <function>map:merge</function> takes a sequence of maps (often but not necessarily
                  <xtermref spec="DM40" ref="dt-single-entry-map"/>) and merges them into a single map.</p>
                        </item>
                        <!--<item><p><function>map:of-pairs</function> takes a sequence of 
                     <xtermref spec="FO40" ref="dt-key-value-pair-map">key-value pair maps</xtermref>
                     and merges them into a single map.</p></item>-->
                     </ulist>
                     <p>Either of these functions can be used to build an index of employee
                  elements using the value of the <code nobreak="false">@id</code> attribute as a key:</p>
                     <ulist>
                        <item>
                           <p>
                              <code nobreak="false">map:build(//employee, fn { @id })</code>
                           </p>
                        </item>
                        <item>
                           <p>
                              <code nobreak="false">map:merge(//employee ! { @id, . })</code>
                           </p>
                        </item>
                        <!--<item><p><code>map:of-pairs(//employee ! { 'key': @id, 'value': . })</code></p></item>-->
                     </ulist>
                     <p>Both functions also provide control over:</p>
                     <ulist>
                        <item>
                           <p>The way in which duplicate keys are handled, and </p>
                        </item>
                        <item>
                           <p>The ordering of entries in the resulting map.</p>
                        </item>
                     </ulist>
                  </note>
               </div4>
               <div4 id="id-map-lookup">
                  <head>Maps as Functions</head>
                  <p>Maps are <termref def="dt-function-item">function items</termref>, and 
                  a <termref def="dt-dynamic-function-call"/> can be used to look up
    the value associated with a key in a map.

    
    If <code nobreak="false">$map</code> is a map and <code nobreak="false">$key</code> is a key,
    then <code nobreak="false">$map($key)</code> is equivalent to <code nobreak="false">map:get($map, $key)</code>.
    The semantics of such a function call are formally defined in
    <xspecref spec="FO40" ref="func-map-get"/>.
    
    </p>
                  <p>Examples:</p>
                  <ulist>
                     <item>
                        <p>
                           <code nobreak="false">$weekdays("Su")</code> returns the <termref def="dt-associated-value">associated value</termref> of the key <code nobreak="false">Su</code>.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">$books("Green Eggs and Ham")</code> returns  <termref def="dt-associated-value">associated value</termref>  of the key <code nobreak="false">Green Eggs and Ham</code>.</p>
                     </item>
                  </ulist>
                  <note>
                     <p>XPath 4.0 also provides an alternate syntax for map and
      array lookup that is more terse, supports wildcards, and allows lookup to
      iterate over a sequence of maps or arrays. See <specref ref="id-lookup"/> for details.</p>
                  </note>
                  <p>Map lookups can be chained.</p>
                  <p>Examples: (These examples assume that <code nobreak="false">$b</code> is bound to the books map from the previous section)</p>
                  <ulist>
                     <item>
                        <p>The expression <code nobreak="false">$b("book")("title")</code> returns the string <code nobreak="false">Data on the Web</code>.</p>
                     </item>
                     <item>
                        <p>The expression <code nobreak="false">$b("book")("author")</code> returns the array of authors.</p>
                     </item>
                     <item>
                        <p>The expression <code nobreak="false">$b("book")("author")(1)("last")</code> returns the string <code nobreak="false">Abiteboul</code>.</p>
                        <p>(This example combines <specref ref="id-array-lookup"/> with map lookups.)</p>
                     </item>
                  </ulist>
               </div4>
            </div3>
            <div3 id="id-arrays">
               <head>Arrays</head>
               <p/>
               <div4 id="id-array-constructors">
                  <head>Array Constructors</head>
                  <p>
                     <termdef id="dt-array" term="array">An <term>array</term> is
      a <termref def="dt-function-item"/> that associates a set of positions, represented as
      positive integer keys, with values.</termdef> The first position
      in an array is associated with the integer 1.
      <termdef id="dt-member" term="member">The values of an array are called
      its <term>members</term>.</termdef>

      In the type hierarchy, array has a distinct type, which is
      derived from function.
      Atomization converts arrays to sequences (see <termref def="dt-atomization">Atomization</termref>).  
      </p>
                  <p>An array is created using an <nt def="doc-xpath40-ArrayConstructor">ArrayConstructor<!--$spec = xpath40--></nt>.</p>
                  <scrap headstyle="show">
                     <prod id="doc-xpath40-ArrayConstructor">
                        <lhs>ArrayConstructor</lhs>
                        <rhs>
                           <nt def="prod-xpath40-SquareArrayConstructor">SquareArrayConstructor<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-CurlyArrayConstructor">CurlyArrayConstructor<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-ArrayConstructor-SquareArrayConstructor">
                        <lhs>SquareArrayConstructor</lhs>
                        <rhs>"["  (<nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt> ** ",")  "]"</rhs>
                     </prod>

                     <prod id="doc-xpath40-ArrayConstructor-ExprSingle">
                        <lhs>ExprSingle</lhs>
                        <rhs>
                           <nt def="prod-xpath40-ForExpr">ForExpr<!--$idref_lang_part = xpath40- --></nt>
                           <br/>|  <nt def="prod-xpath40-LetExpr">LetExpr<!--$idref_lang_part = xpath40- --></nt>
                           <br/>|  <nt def="prod-xpath40-QuantifiedExpr">QuantifiedExpr<!--$idref_lang_part = xpath40- --></nt>
                           <br/>|  <nt def="prod-xpath40-IfExpr">IfExpr<!--$idref_lang_part = xpath40- --></nt>
                           <br/>|  <nt def="prod-xpath40-OrExpr">OrExpr<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-ArrayConstructor-CurlyArrayConstructor">
                        <lhs>CurlyArrayConstructor</lhs>
                        <rhs>"array"  <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-ArrayConstructor-EnclosedExpr">
                        <lhs>EnclosedExpr</lhs>
                        <rhs>"{"  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>?  "}"</rhs>
                     </prod>
                  </scrap>
                  <p>
      If a member of an array is a
      node, its node identity is preserved.

      

        In both forms of an <nt def="doc-xpath40-ArrayConstructor">ArrayConstructor<!--$spec = xpath40--></nt>, if a member
        expression evaluates to a node, the associated value is the
        node itself, not a new node with the same values.  If the
        member expression evaluates to a map or array, the associated
        value is a new map or array with the same values.

        </p>
                  <p>A <nt def="prod-xpath40-SquareArrayConstructor">SquareArrayConstructor<!--$spec = xpath40--></nt> 
      consists of a comma-delimited set of argument expressions. It returns an array in which each member contains the value of the corresponding argument expression.</p>
                  <p>Examples:</p>
                  <ulist>
                     <item>
                        <p>
                           <code nobreak="false">[ 1, 2, 5, 7 ]</code> creates an array with four members: <code nobreak="false">1</code>, <code nobreak="false">2</code>, <code nobreak="false">5</code>, and <code nobreak="false">7</code>.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">[ (), (27, 17, 0) ]</code> creates an array with two members: <code nobreak="false">()</code> and the sequence <code nobreak="false">(27, 17, 0)</code>.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">[ $x, local:items(), &lt;tautology&gt;It is what it is.&lt;/tautology&gt; ]</code> creates an array with three members: the value of $x, the result of evaluating the function call, and a tautology element.</p>
                     </item>
                  </ulist>
                  <p>A <nt def="prod-xpath40-CurlyArrayConstructor">CurlyArrayConstructor<!--$spec = xpath40--></nt>
      can use any  expression to create its members.  It
      evaluates its operand expression to obtain a sequence of items
      and creates an array with these items as members.  Unlike a
      SquareArrayConstructor, a comma in a CurlyArrayConstructor is
      the  <termref def="dt-comma-operator">comma operator</termref>, not a delimiter.
      </p>
                  <p>Examples:</p>
                  <ulist>
                     <item>
                        <p>
                           <code nobreak="false">array { $x }</code> creates an array with one member for each item in the sequence to which $x is bound.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">array { local:items() }</code> creates an array with one member for each item  in the sequence to which <code nobreak="false">local:items()</code> evaluates.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">array { 1, 2, 5, 7 }</code> creates an array with four members: <code nobreak="false">1</code>, <code nobreak="false">2</code>, <code nobreak="false">5</code>, and <code nobreak="false">7</code>.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">array { (), (27, 17, 0) }</code> creates an array with three members: <code nobreak="false">27</code>, <code nobreak="false">17</code>, and <code nobreak="false">0</code>.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">array { $x, local:items(), &lt;tautology&gt;It is what it is.&lt;/tautology&gt; }</code> creates an array with the following members: the items to which <code nobreak="false">$x</code> is bound, followed by the items to which <code nobreak="false">local:items()</code> evaluates, followed by a tautology element.</p>
                     </item>
                  </ulist>
                  <note>
                     <p>XPath 4.0 does not provide explicit support for sparse arrays. Use integer-valued maps to represent sparse arrays, 
                     for example: <code nobreak="false">{ 27 : -1, 153 : 17 }</code>.</p>
                  </note>
               </div4>
               <div4 id="id-array-lookup">
                  <head>Arrays as Functions</head>
                  <p>Arrays are <termref def="dt-function-item">function items</termref>, 
                  and a <termref def="dt-dynamic-function-call"/> can be used to look up
    the value associated with position in an array.

    

    
    If <code nobreak="false">$array</code> is an array and <code nobreak="false">$index</code> is an integer corresponding to a position in the array,
    then <code nobreak="false">$array($key)</code> is equivalent to <code nobreak="false">array:get($array, $key)</code>.
    The semantics of such a function call are formally defined in
    <xspecref spec="FO40" ref="func-array-get"/>.
    
    </p>
                  <p>Examples:</p>
                  <ulist>
                     <item>
                        <p>
                           <code nobreak="false">[ 1, 2, 5, 7 ](4)</code> evaluates to <code nobreak="false">7</code>.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">[ [ 1, 2, 3 ], [ 4, 5, 6 ] ](2)</code> evaluates to <code nobreak="false">[ 4, 5, 6 ]</code>.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">[ [ 1, 2, 3 ], [ 4, 5, 6 ] ](2)(2)</code> evaluates to <code nobreak="false">5</code>.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">[ 'a', 123, &lt;name&gt;Robert Johnson&lt;/name&gt; ](3)</code> evaluates to <code nobreak="false">&lt;name&gt;Robert Johnson&lt;/name&gt;</code>.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">array { (), (27, 17, 0) }(1)</code> evaluates to  <code nobreak="false">27</code>.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">array { (), (27, 17, 0) }(2)</code> evaluates to  <code nobreak="false">17</code>.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">array { "licorice", "ginger" }(20)</code> raises a dynamic error <xerrorref spec="FO40" class="AY" code="0001"/>.</p>
                     </item>
                  </ulist>
                  <note>
                     <p>XPath 4.0 also provides an alternate syntax for map and
      array lookup that is more terse, supports wildcards, and allows
      lookup to iterate over a sequence of maps or arrays. See
      <specref ref="id-lookup"/> for details.</p>
                  </note>
               </div4>
            </div3>
            <div3 id="id-lookup">
               <head>Lookup Expressions</head>
               <changes>
                  <change issue="1996" PR="2134" date="2025-07-29">
                  The lookup operator <code nobreak="false">?</code> 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.
               </change>
               </changes>
               <p diff="add" at="2023-11-15">The operator "?", known as the lookup operator,
               returns values found in the operand map or array.</p>
               <div4 id="id-postfix-lookup">
                  <head>Postfix Lookup Expressions</head>
                  <scrap headstyle="show">
                     <prod id="doc-xpath40-LookupExpr">
                        <lhs>LookupExpr</lhs>
                        <rhs>
                           <nt def="prod-xpath40-PostfixExpr">PostfixExpr<!--$idref_lang_part = xpath40- --></nt>
                           <nt def="prod-xpath40-Lookup">Lookup<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-LookupExpr-PostfixExpr">
                        <lhs>PostfixExpr</lhs>
                        <rhs>
                           <nt def="prod-xpath40-PrimaryExpr">PrimaryExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-FilterExpr">FilterExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-DynamicFunctionCall">DynamicFunctionCall<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-LookupExpr">LookupExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-MethodCall">MethodCall<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-FilterExprAM">FilterExprAM<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-LookupExpr-Lookup">
                        <lhs>Lookup</lhs>
                        <rhs>"?"  <nt def="prod-xpath40-KeySpecifier">KeySpecifier<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-LookupExpr-KeySpecifier">
                        <lhs>KeySpecifier</lhs>
                        <rhs>
                           <nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-Literal">Literal<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ContextValueRef">ContextValueRef<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-VarRef">VarRef<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ParenthesizedExpr">ParenthesizedExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-LookupWildcard">LookupWildcard<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-LookupExpr-Literal">
                        <lhs>Literal</lhs>
                        <rhs>
                           <nt def="prod-xpath40-NumericLiteral">NumericLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="doc-xpath40-StringLiteral">StringLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-QNameLiteral">QNameLiteral<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-LookupExpr-ContextValueRef">
                        <lhs>ContextValueRef</lhs>
                        <rhs>"."</rhs>
                     </prod>

                     <prod id="doc-xpath40-LookupExpr-VarRef">
                        <lhs>VarRef</lhs>
                        <rhs>"$"  <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-LookupExpr-ParenthesizedExpr">
                        <lhs>ParenthesizedExpr</lhs>
                        <rhs>"("  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>?  ")"</rhs>
                     </prod>

                     <prod id="doc-xpath40-LookupExpr-LookupWildcard">
                        <lhs>LookupWildcard</lhs>
                        <rhs>"*"</rhs>
                     </prod>
                  </scrap>
                  <p>A postfix <code nobreak="false">Lookup</code> has two parts: the left hand operand
                  selects maps or arrays to be searched, and
                  the <code nobreak="false">KeySelector</code> defines the search criteria.</p>
                  <p>First a simple example: given an array <code nobreak="false">$array</code> of maps:</p>
                  <eg xml:space="preserve">[ { "John": 3, "Jill": 5}, {"Peter": 8, "Mary": 6} ]</eg>
                  <ulist>
                     <item>
                        <p>
                           <code nobreak="false">$array?1?John</code> returns <code nobreak="false">3</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">$array?2?Mary</code> returns <code nobreak="false">6</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">$array?*?*</code> returns <code nobreak="false">(3, 5, 8, 6)</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">$array?2?*</code> returns <code nobreak="false">(8, 6)</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">$array?*?Peter</code> returns <code nobreak="false">8</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">'Peter' -&gt; $array?*?.</code> returns <code nobreak="false">8</code>
                        </p>
                     </item>
                  </ulist>
                  <p>The required type of the left-hand operand is a sequence of maps or arrays
                  (specifically, <code nobreak="false">(map(*) | array(*))*</code>), and the <termref def="dt-coercion-rules"/>
                  are applied with this required type: this means that if the supplied value
                  includes JNodes, these will be coerced to maps or arrays
               by extracting the <term>·jvalue·</term> property of the JNode. The lookup
               operation is applied independently to each of these maps or arrays,
               and the final expression result is the <termref def="dt-sequence-concatenation"/>
               of the individual results.</p>
                  <p>The semantics of a postfix lookup expression <code nobreak="false">
                        <var>E</var>?<var>KS</var>
                     </code> are 
                  defined by the following rules:</p>
                  <olist>
                     <item>
                        <p>
                           <var>E</var> is evaluated to produce a value <code nobreak="false">$V</code>.</p>
                     </item>
                     <item>
                        <p>If <code nobreak="false">$V</code> is not a <termref def="dt-singleton"/> 
                     (that is if <code nobreak="false">count($V) ne 1</code>),
                  then the result (by recursive application of these rules) is the value of
                  <code nobreak="false">for $v in $V return $v?<var>KS</var>
                           </code>.</p>
                     </item>
                     <item>
                        <p>If <code nobreak="false">$V</code> is a <termref def="dt-JNode"/> then it is
                  coerced to the required type <code nobreak="false">(map(*)|array(*))</code>: see
                  <termref def="dt-coercion-rules"/>.</p>
                     </item>
                     <item>
                        <p>If <code nobreak="false">$V</code> (after coercion) is a <termref def="dt-singleton"/> array item (that is, 
                     if <code nobreak="false">$V instance of array(*)</code>) then:</p>
                        <olist>
                           <item>
                              <p>If the <nt def="prod-xpath40-KeySpecifier">KeySpecifier<!--$spec = xpath40--></nt>
                                 <var>KS</var> is either a
                         <code nobreak="false">Literal</code>, a <code nobreak="false">ContextValueRef</code>, a <code nobreak="false">VarRef</code>,
                        or a <code nobreak="false">ParenthesizedExpr</code>,
                        then it is evaluated as an expression to produce a value <code nobreak="false">$K</code>
                        and the result is:</p>
                              <eg xml:space="preserve">data($K) ! array:get($V, .)</eg>
                              <note>
                                 <p>The focus for evaluating the key specifier expression is the 
                              same as the focus for the <code nobreak="false">Lookup</code> expression itself.</p>
                                 <p>The order of items in the result reflects the order of subscripts in
                              <code nobreak="false">$K</code>: <code nobreak="false">[10, 20, 30]?(3, 1)</code> returns <code nobreak="false">(30, 10)</code>.</p>
                                 <p>This rule implies that a type error (<errorref class="TY" code="0004"/>)
                              is raised if an item in the atomized value of <var>$K</var> cannot be coerced 
                              to the type <code nobreak="false">xs:integer</code>.</p>
                                 <p>This rule also implies that a dynamic error (<xerrorref spec="FO40" class="AY" code="0001"/>)
                              is raised if an integer in the atomized value of <var>$K</var> is outside
                              the range 1 to <code nobreak="false">array:size($V)</code>.</p>
                              </note>
                           </item>
                           <item>
                              <p>If the <nt def="prod-xpath40-KeySpecifier">KeySpecifier<!--$spec = xpath40--></nt>
                                 <var>KS</var> is an <code nobreak="false">NCName</code>
                           then it is evaluated in the same way as if the <code nobreak="false">NCName</code> were written
                           in quotation marks as a <code nobreak="false">StringLiteral</code>: in consequence,
                           the expression raises a type error <errorref class="TY" code="0004"/>.</p>
                           </item>
                           <item>
                              <p>If the <nt def="prod-xpath40-KeySpecifier">KeySpecifier<!--$spec = xpath40--></nt>
                                 <code nobreak="false">KS</code> is a wildcard
                           (<code nobreak="false">*</code>), 
                           the result is the same as <code nobreak="false">$V?(1 to array:size($V))</code>:</p>
                              <note>
                                 <p>Note that array items are returned in order.</p>
                              </note>
                           </item>
                        </olist>
                     </item>
                     <item>
                        <p>If <var>$V</var> is a <termref def="dt-singleton"/> 
                     map item (that is, if <code nobreak="false">$V instance of map(*)</code>)
                     then:</p>
                        <olist>
                           <item>
                              <p>If the <nt def="prod-xpath40-KeySpecifier">KeySpecifier<!--$spec = xpath40--></nt>
                                 <var>KS</var> is either a
                         <code nobreak="false">Literal</code>, a <code nobreak="false">ContextValueRef</code>, a <code nobreak="false">VarRef</code>,
                        or a <code nobreak="false">ParenthesizedExpr</code>,
                        then it is evaluated as an expression to produce a value <code nobreak="false">$K</code>
                        and the result is:</p>
                              <eg xml:space="preserve">data($K) ! map:get($V, .)</eg>
                              <note>
                                 <p>The focus for evaluating the key specifier expression is the 
                                 same as the focus for the <code nobreak="false">Lookup</code> expression itself.</p>
                                 <p>The order of items in the result reflects the order of keys in
                              <code nobreak="false">$K</code>: <code nobreak="false">{'a':10, 'b':20, 'c':30}?('c', 'a')</code> 
                                 returns <code nobreak="false">(30, 10)</code>.</p>
                                 <p>There is no error when <code nobreak="false">$K</code> includes a key that is not
                              present in the map.</p>
                              </note>
                           </item>
                           <item>
                              <p>If the <nt def="prod-xpath40-KeySpecifier">KeySpecifier<!--$spec = xpath40--></nt>
                                 <var>KS</var> is an <code nobreak="false">NCName</code>, then the result
                              is the same as if it were written in quotes as
                              a <code nobreak="false">StringLiteral</code>: for example <code nobreak="false">$map?name</code>
                           returns the same result as <code nobreak="false">map?"name"</code>.</p>
                           </item>
                           <item>
                              <p>If the <nt def="prod-xpath40-KeySpecifier">KeySpecifier<!--$spec = xpath40--></nt>
                                 <var>KS</var> is a wildcard (<code nobreak="false">*</code>), 
                              the result is the same as <code nobreak="false">$V?(map:keys($V))</code>.</p>
                              <note>
                                 <p>The order of entries in the result sequence 
                                 reflects the <xtermref spec="DM40" ref="dt-entry-order">entry order</xtermref>
                                 of the map.</p>
                              </note>
                           </item>
                        </olist>
                     </item>
                     <item>
                        <p>Otherwise (that is, if <code nobreak="false">$V</code> is neither a map nor an array)
                     a <termref def="dt-type-error">type error</termref> is raised <errorref class="TY" code="0004"/>.</p>
                     </item>
                  </olist>
                  <p>Examples:</p>
                  <ulist>
                     <item>
                        <p>
                           <code nobreak="false">[ 1, 2, 5, 7 ]?*</code> evaluates to <code nobreak="false">(1, 2, 5, 7)</code>.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">[ [ 1, 2, 3 ], [ 4, 5, 6 ] ]?*</code> evaluates to <code nobreak="false">([ 1, 2, 3 ], [ 4, 5, 6 ])</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">[ [ 1, 2, 3 ], 4, 5 ]?*[. instance of array(xs:integer)]</code> evaluates to <code nobreak="false">([ 1, 2, 3 ])</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">[ [ 1, 2, 3 ], [ 4, 5, 6 ], 7 ]?*[. instance of array(*)]?2</code> evaluates to <code nobreak="false">(2, 5)</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">[ [ 1, 2, 3 ], 4, 5 ]?*[. instance of xs:integer]</code> 
                        evaluates to <code nobreak="false">(4, 5)</code>.
                     </p>
                     </item>
                  </ulist>
               </div4>
               <div4 id="id-unary-lookup">
                  <head>Unary Lookup</head>
                  <scrap headstyle="show">
                     <prod id="doc-xpath40-UnaryLookup">
                        <lhs>UnaryLookup</lhs>
                        <rhs>
                           <nt def="prod-xpath40-Lookup">Lookup<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-UnaryLookup-Lookup">
                        <lhs>Lookup</lhs>
                        <rhs>"?"  <nt def="prod-xpath40-KeySpecifier">KeySpecifier<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-UnaryLookup-KeySpecifier">
                        <lhs>KeySpecifier</lhs>
                        <rhs>
                           <nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-Literal">Literal<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ContextValueRef">ContextValueRef<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-VarRef">VarRef<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ParenthesizedExpr">ParenthesizedExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-LookupWildcard">LookupWildcard<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-UnaryLookup-Literal">
                        <lhs>Literal</lhs>
                        <rhs>
                           <nt def="prod-xpath40-NumericLiteral">NumericLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="doc-xpath40-StringLiteral">StringLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-QNameLiteral">QNameLiteral<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-UnaryLookup-ContextValueRef">
                        <lhs>ContextValueRef</lhs>
                        <rhs>"."</rhs>
                     </prod>

                     <prod id="doc-xpath40-UnaryLookup-VarRef">
                        <lhs>VarRef</lhs>
                        <rhs>"$"  <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                        </rhs>
                     </prod>

                     <prod id="doc-xpath40-UnaryLookup-ParenthesizedExpr">
                        <lhs>ParenthesizedExpr</lhs>
                        <rhs>"("  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>?  ")"</rhs>
                     </prod>

                     <prod id="doc-xpath40-UnaryLookup-LookupWildcard">
                        <lhs>LookupWildcard</lhs>
                        <rhs>"*"</rhs>
                     </prod>
                  </scrap>
                  <p>Unary lookup is most commonly used in predicates (for example, <code nobreak="false">$map[?name = 'Mike']</code>)
                  or with the simple map operator (for example, <code nobreak="false">avg($maps ! (?price - ?discount))</code>).</p>
                  <p>The unary lookup expression <code nobreak="false">?KS</code> is defined to be equivalent to the postfix lookup
                  expression <code nobreak="false">.?KS</code>, which has the context value (<code nobreak="false">.</code>) as the implicit first operand.
                  See <specref ref="id-postfix-lookup"/> for the postfix lookup operator.</p>
                  <note>
                     <p>Although the grammar allows the key specifier to be a context value expression,
               this is of no practical use with a unary lookup. The expression <code nobreak="false">[1, 2, 3] -&gt; ?.</code> expands to
               <code nobreak="false">[1, 2, 3]?(1, 2, 3)</code> which returns <code nobreak="false">(1, 2, 3)</code>; but a more
               likely result is a type error or array bounds error.</p>
                  </note>
                  <p>Examples:</p>
                  <ulist>
                     <item>
                        <p>
                           <code nobreak="false">?name</code> is equivalent to <code nobreak="false">.("name")</code>, an appropriate lookup for a map.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">?2</code> is equivalent to <code nobreak="false">.(2)</code>, an appropriate lookup for an array or an integer-valued map.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">?"first name"</code> is equivalent to <code nobreak="false">.("first name")</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">?#code</code> is equivalent to <code nobreak="false">.(#code)</code>
                        </p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">?($a)</code> and <code nobreak="false">?$a</code> are 
                        equivalent to <code nobreak="false">for $k in $a return .($k)</code>, 
                        allowing keys for an array or map to be passed using a variable.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">?(3e0)</code> and <code nobreak="false">?3e0</code> return the same result as
                        <code nobreak="false">?3</code>, because <code nobreak="false">xs:double(3e0)</code> and
                        <code nobreak="false">xs:integer(3)</code> compare equal under the rules of the
                        <function>atomic-equal</function> function.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">?(2 to 4)</code> is equivalent to <code nobreak="false">for $k in (2, 3, 4) return .($k)</code>, 
                        a convenient way to return a range of values from an array.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">([ 1, 2, 3 ], [ 1, 2, 5 ], [ 1, 2 ])[?3 = 5]</code> raises an error,
                        because <code nobreak="false">?3</code> applied to one of the
                        items in the sequence fails.</p>
                     </item>
                  </ulist>
               </div4>
               <div4 id="id-lookup-vs-path-expressions">
                  <head>Comparing Lookup and Path Expressions</head>
                  <p>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.</p>
                  <p>For more complex queries into trees of maps and arrays, XPath 4.0
                  introduces a generalization of path expressions (see <specref ref="id-path-expressions"/>)
                  which can now handle <termref def="dt-JTree">JTrees</termref> 
                     as well as <termref def="dt-XTree">XTrees</termref>.</p>
                  <p>For simple expressions, the capabilities of the two constructs overlap.
                  For example, if <code nobreak="false">$m</code> is a map, then the expressions
                  <code nobreak="false">$m?code = 3</code> and <code nobreak="false">$m/code = 3</code> have the same effect.
                  Path expressions, however, have more power, and with it, more complexity.
                  The expression <code nobreak="false">$m/code = 3</code> (unless simplified by an optimizer)
                  effectively expands the expression to
                  <code nobreak="false">(jtree($m)/child::get("code") =&gt; jvalue()) = 3</code>:
                  that is, the supplied map is wrapped in a JNode, the child axis returns a sequence of JNodes,
                  and the <term>·jvalue·</term> properties of these JNodes are compared with the
                  supplied value <code nobreak="false">3</code>.</p>
                  <p>Whereas simple lookups of specific entries in maps and arrays work well,
                  experience has shown that the <code nobreak="false">?*</code> wildcard lookup can be problematic.
                  This is because of the flattening effect: for example, given the array
                  <code nobreak="false">let $A := [(1,2), (3,4), (), 5]</code> the result of the expression
                  <code nobreak="false">$A?*</code> is the sequence <code nobreak="false">(1, 2, 3, 4, 5)</code> which loses information
                  that might be needed for further processing. By contrast, the path expression
                  <code nobreak="false">$A/*</code> (or <code nobreak="false">$A/child::*</code>) returns a sequence of four
                  JNodes, whose <term>·jvalue·</term> properties are respectively <code nobreak="false">(1,2)</code>, 
                     <code nobreak="false">(3,4)</code>, <code nobreak="false">()</code>, and <code nobreak="false">5</code>.</p>
                  <p>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 <termref def="dt-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 <term>·jvalue·</term> properties of the JNodes are 
                  needed, these will usually be extracted automatically by virtue of the
                  <termref def="dt-coercion-rules"/>: for example if the value is used in an
                  arithmetic expression or a value comparison, atomization of the JNode
                  automatically extracts its <term>·jvalue·</term>. In other cases the value can
                  be extracted explicitly by a call of the <function>jvalue</function> function.</p>
                  <p>Lookup expressions on arrays result in a dynamic error if the subscript is out
                  of bounds, whereas the equivalent path expression succeeds, returning the empty
                  sequence. For example <code nobreak="false">array{1 to 5}?10</code> raises 
                     <xerrorref spec="FO40" class="AY" code="0001"/>, whereas <code nobreak="false">array{1 to 5}/get(10)</code>
                     returns a empty sequence.
                 </p>
               </div4>
               <div4 id="id-implausible-lookup-expressions" diff="add" at="Issue602">
                  <head>Implausible Lookup Expressions</head>
                  <p>Under certain conditions a lookup expression that will never select anything
                  is classified as <termref def="dt-implausible"/>. During the static analysis
                  phase, a processor <rfc2119>may</rfc2119> (subject to the rules in
                  <specref ref="id-implausible-expressions"/>) report a static error
                  when such lookup expressions are encountered: <errorref class="TY" code="0145"/>.</p>
                  <p>More specifically, a shallow unary or postfix lookup is classified as 
                  <termref def="dt-implausible"/> if any of the following conditions applies:</p>
                  <olist>
                     <item>
                        <p>The inferred type of the left-hand operand (or the context value, in the case
                  of a unary expression) is a record type (see <specref ref="id-record-test"/>),
                  and the <code nobreak="false">KeySpecifier</code> is an <code nobreak="false">IntegerLiteral</code>.
                  </p>
                     </item>
                     <item>
                        <p>The inferred type of the left-hand operand (or the context value, in the case
                     of a unary expression) is a record type (see <specref ref="id-record-test"/>),
                     and the <code nobreak="false">KeySpecifier</code> is an <code nobreak="false">NCName</code> or <code nobreak="false">StringLiteral</code>
                     that cannot validly appear as a field name in the record.
                  </p>
                     </item>
                     <item>
                        <p>The inferred type of the left-hand operand (or the context value, in the case
                     of a unary expression) is a map type,
                     and the inferred type of the <code nobreak="false">KeySpecifier</code>, after coercion, is a type that
                     is disjoint with the key type of the map.
                  </p>
                     </item>
                     <item>
                        <p>The inferred type of the left-hand operand (or the context value, in the case
                     of a unary expression) is an array type,
                     and the <code nobreak="false">KeySpecifier</code> is the <code nobreak="false">IntegerLiteral</code>
                           <code nobreak="false">0</code> (zero).
                  </p>
                     </item>
                  </olist>
                  <note>
                     <p>Other errors, such as using an <code nobreak="false">NCName</code>
                        <code nobreak="false">KeySpecifier</code>
               for an array lookup, are handled under the general provisions for type errors.</p>
                  </note>
                  <p>Examples of implausible lookup expressions include the following:</p>
                  <ulist>
                     <item>
                        <p>
                           <code nobreak="false">parse-uri($uri)?3</code>: the declared result type of <code nobreak="false">parse-uri</code> is a record
                  test, so the selector <code nobreak="false">3</code> will never select anything.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">in-scope-namespaces($node)(current-date())</code>: the result type of
                  <code nobreak="false">in-scope-namespaces</code> is a map with <code nobreak="false">xs:string</code> keys, so the selector
                  <code nobreak="false">current-date()</code> will never select anything.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">array:subarray($a, 2, 5)?0</code>: the integer zero cannot select any member
                  of an array, because numbering starts at 1.</p>
                     </item>
                  </ulist>
               </div4>
            </div3>
            <div3 id="id-methods">
               <head>Method Calls</head>
               <changes>
                  <change issue="2143" date="2025-08-04">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.</change>
               </changes>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-MethodCall">
                     <lhs>MethodCall</lhs>
                     <rhs>
                        <nt def="prod-xpath40-PostfixExpr">PostfixExpr<!--$idref_lang_part = xpath40- --></nt>  "=?&gt;"  <nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-PositionalArgumentList">PositionalArgumentList<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-MethodCall-PostfixExpr">
                     <lhs>PostfixExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-PrimaryExpr">PrimaryExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-FilterExpr">FilterExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-DynamicFunctionCall">DynamicFunctionCall<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-LookupExpr">LookupExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-MethodCall">MethodCall<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-FilterExprAM">FilterExprAM<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-MethodCall-PositionalArgumentList">
                     <lhs>PositionalArgumentList</lhs>
                     <rhs>"("  <nt def="prod-xpath40-PositionalArguments">PositionalArguments<!--$idref_lang_part = xpath40- --></nt>?  ")"</rhs>
                  </prod>

                  <prod id="doc-xpath40-MethodCall-PositionalArguments">
                     <lhs>PositionalArguments</lhs>
                     <rhs>(<nt def="prod-xpath40-Argument">Argument<!--$idref_lang_part = xpath40- --></nt> ++ ",")</rhs>
                  </prod>

                  <prod id="doc-xpath40-MethodCall-Argument">
                     <lhs>Argument</lhs>
                     <rhs>
                        <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ArgumentPlaceholder">ArgumentPlaceholder<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-MethodCall-ExprSingle">
                     <lhs>ExprSingle</lhs>
                     <rhs>
                        <nt def="prod-xpath40-ForExpr">ForExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-LetExpr">LetExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-QuantifiedExpr">QuantifiedExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-IfExpr">IfExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-OrExpr">OrExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-MethodCall-ArgumentPlaceholder">
                     <lhs>ArgumentPlaceholder</lhs>
                     <rhs>"?"</rhs>
                  </prod>
               </scrap>
               <p>A method call combines accessing a map <var>M</var> to look up an entry
               whose value is a function item <var>F</var>, and calling the function item <var>F</var>
               supplying the map <var>M</var> as the implicit value of the first argument.</p>
               <p>For example, given the variable:</p>
               <eg xml:space="preserve">
let $rectangle := {
  'height':    3,
  'width':     4,
  'area':      fn ($rect) { 
                  $rect?height × $rect?width 
               },
  'perimeter': fn ($rect) { 
                 2 × ($rect?height + $rect?width) 
               },
  'resize':    fn ($rect, $factor) { 
                  $rect 
                     =&gt; map:put('height', $rect?height × $factor)
                     =&gt; map:put('width', $rect?width × $factor)
               }
}
               </eg>
               <p>The method call <code nobreak="false">$rectangle =?&gt; area()</code> returns <code nobreak="false">12</code>, while
               the method call <code nobreak="false">$rectangle =?&gt; perimeter()</code> returns <code nobreak="false">14</code>,
                  and <code nobreak="false">$rectangle =?&gt; resize(2)</code> returns a map representing
               a rectangle with <code nobreak="false">height = 6</code> and <code nobreak="false">width = 8</code>.</p>
               <p>An arity-one function can also be written as a <termref def="dt-focus-function"/>:</p>
               <eg xml:space="preserve">
let $rectangle := {
  'height': 3,
  'width': 4,
  'area': fn { ?height × ?width }
}
               </eg>
               <p>The expression <code nobreak="false">
                     <var>M</var> =?&gt; <var>N</var>(<var>X</var>, <var>Y</var>, ...)</code>
                  is by definition equivalent to:</p>
               <eg xml:space="preserve">for $map as map(*) in <var>M</var>
let $f as function(*) := $map?<var>N</var>                 
return $f($map, <var>X</var>, <var>Y</var>, ...)</eg>
               <p>(where <code nobreak="false">$map</code> and <code nobreak="false">$f</code>
                  are otherwise unused variable names).</p>
               <note>
                  <p>The left-hand operand can be a sequence of maps. For example, given <code nobreak="false">$rectangle</code>
              defined as in the first example above, the expression <code nobreak="false">((1 to 2) ! $rectangle =?&gt; resize(.)) =?&gt; area()</code>
              returns the sequence <code nobreak="false">(12, 48)</code>.</p>
               </note>
               <p>The argument list in a method call must not include an argument placeholder; that is,
               the call must not be a partial function application (<errorref class="ST" code="0003"/>).</p>
               <note>
                  <p>Implicit in this definition are the following rules:</p>
                  <ulist>
                     <item>
                        <p>The value of <var>M</var> must be
                     a sequence of zero or more maps;</p>
                     </item>
                     <item>
                        <p>Each of those maps must have an entry with the
                        key <var>N</var> (as an instance of <code nobreak="false">xs:string</code>,
                        <code nobreak="false">xs:untypedAtomic</code>, or <code nobreak="false">xs:anyURI</code>);</p>
                     </item>
                     <item>
                        <p>The value of that entry must be
                     a single function item;</p>
                     </item>
                     <item>
                        <p>That function item must have an arity equal to one plus the number
                        of supplied arguments, and the signature of the function
                        must allow a map to be supplied as the first argument.</p>
                     </item>
                  </ulist>
                  <p>The error codes raised if these conditions are not satisfied are
                  exactly the same as if the expanded code were used directly.</p>
               </note>
               <note>
                  <p>Although methods mimic some of the capability of object-oriented
                  languages, the functionality is more limited:</p>
                  <ulist>
                     <item>
                        <p>There is no encapsulation: the entries in a map are all publicly
                     exposed.</p>
                     </item>
                     <item>
                        <p>There is no class hierarchy, and no inheritance or overriding.</p>
                     </item>
                     <item>
                        <p>Methods within a map can be removed or replaced in the same way as
                     any other entries in the map.</p>
                     </item>
                  </ulist>
               </note>
               <note>
                  <p>Methods can be useful when there is a need to write inline recursive
                  functions. For example:</p>
                  <eg xml:space="preserve">
let $lib := {
  'product': fn($map as map(*), $in as xs:double*) {
    if (empty( $in ))
    then 1
    else head($in) × $map =?&gt; product(tail($in))
  }
}
return $lib =?&gt; product((1.2, 1.3, 1.4))
                  </eg>
                  <p>In an environment that supports XPath but not XQuery, this mechanism can be used 
                  to define all the functions that a particular XPath expression needs to invoke,
                  and these functions can be mutually recursive.</p>
               </note>
               <example>
                  <head>Chaining method calls</head>
                  <p>In the example above, <code nobreak="false">$rectangle =?&gt; area()</code>, <code nobreak="false">$rectangle</code>
               is typically a single map, and <code nobreak="false">area</code> is the key of one of the entries in the map, the value
               of the entry being a function item that takes the map as its implicit first argument. 
               The method call
                  <code nobreak="false">$rectangle =?&gt; area()</code> first performs a map lookup (<code nobreak="false">$rectangle?area</code>)
                  to select the function item, and then calls the function item, supplying the containing
                  map as the first (and in this case only) argument.</p>
                  <p>Such calls can be chained. For example, <code nobreak="false">$rectangle =?&gt; resize(2)</code> returns a rectangle that
               is twice the size of the original, so <code nobreak="false">$rectangle =?&gt; resize(2) =?&gt; area()</code> returns the area of the
               enlarged rectangle.</p>
                  <note>
                     <p>Note how the <code nobreak="false">resize</code> function is implemented using <code nobreak="false">map:put</code>, which
               ensures that the map entries holding function items (<code nobreak="false">area</code>, <code nobreak="false">perimeter</code>, and
               <code nobreak="false">resize</code>, are automatically present and unchanged in the modified map.</p>
                  </note>
                  <p>This kind of chaining extends to the case where a method returns zero or more maps. For example, suppose
               that rectangles are nested, and that <code nobreak="false">$rectangle =?&gt; contents()</code> delivers a sequence of zero or more 
               rectangles. Then the expression <code nobreak="false">$rectangle =?&gt; area() - sum($rectangle =?&gt; contents() =?&gt; area())</code> returns
               the difference between the area of the containing rectangle and the total area of the contained
               rectangles. This works because the dynamic function call <code nobreak="false">$rectangle =?&gt; contents() =?&gt; area()</code>
               applies the <code nobreak="false">area</code> function in each of the maps in the sequence returned
               by the expression <code nobreak="false">$rectangle =?&gt; contents()</code>.</p>
               </example>
            </div3>
            <div3 id="id-filter-maps-and-arrays">
               <head>Filter Expressions for Maps and Arrays</head>
               <changes>
                  <change issue="1159" PR="1163" date="2024-04-20">
                  Filter expressions for maps and arrays are introduced.
               </change>
                  <change issue="1207" PR="1217" date="2024-05-15">
                  Predicates in filter expressions for maps and arrays can now be numeric.
               </change>
                  <change issue="2351">
                  The group is considering removing or substantially changing this feature,
                  it is considered <loc xmlns:xlink="http://www.w3.org/1999/xlink"
                          href="#at-risk"
                          xlink:type="simple"
                          xlink:show="replace"
                          xlink:actuate="onRequest">at risk</loc>.
               </change>
               </changes>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-FilterExprAM">
                     <lhs>FilterExprAM</lhs>
                     <rhs>
                        <nt def="prod-xpath40-PostfixExpr">PostfixExpr<!--$idref_lang_part = xpath40- --></nt>  "?["  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>  "]"</rhs>
                  </prod>

                  <prod id="doc-xpath40-FilterExprAM-PostfixExpr">
                     <lhs>PostfixExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-PrimaryExpr">PrimaryExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-FilterExpr">FilterExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-DynamicFunctionCall">DynamicFunctionCall<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-LookupExpr">LookupExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-MethodCall">MethodCall<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-FilterExprAM">FilterExprAM<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-FilterExprAM-Expr">
                     <lhs>Expr</lhs>
                     <rhs>(<nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt> ++ ",")</rhs>
                  </prod>
               </scrap>
               <p>Maps and arrays can be filtered using the construct <code nobreak="false">
                     <var>INPUT</var>?[<var>FILTER</var>]</code>.
            For example, <code nobreak="false">$array?[count(.)=1]</code> filters an array to retain only those members that 
            are single items.</p>
               <note>
                  <p>The character-pair <code nobreak="false">?[</code> forms a single token; no intervening whitespace
            or comment is allowed.</p>
               </note>
               <p>The required type of the left-hand operand <code nobreak="false">
                     <var>INPUT</var>
                  </code> is
               <code nobreak="false">(map(*)|array(*))?</code>: that is, it must be either the empty sequence, a single
            map, or a single array <errorref class="TY" code="0004"/>. 
               However, the coercion rules also allow a JNode
                  whose <term>·jvalue·</term> is a map or array to be supplied.
               If the value is the empty sequence, 
               the result of the expression is the empty sequence.</p>
               <p>If the value of <code nobreak="false">
                     <var>INPUT</var>
                  </code> is an array, then the 
               <code nobreak="false">
                     <var>FILTER</var>
                  </code> 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 <termref def="dt-predicate-truth-value"/> of the 
               <code nobreak="false">
                     <var>FILTER</var>
                  </code> expression is true. The order
            of retained members is preserved.</p>
               <p>For example, the following expression:</p>
               <eg xml:space="preserve">let $array := [ (), 1, (2, 3), (4, 5, 6) ]
return $array?[count(.) ge 2]</eg>
               <p>returns:</p>
               <eg xml:space="preserve">[ (2, 3), (4, 5, 6) ]</eg>
               <note>
                  <p>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 <code nobreak="false">$array</code> shown above, the result
            of <code nobreak="false">$array?[3]</code> is the <xtermref spec="DM40" ref="dt-single-member-array"/>
                     <code nobreak="false">[ (2, 3) ]</code>.
            Contrast this with <code nobreak="false">$array?3</code> which delivers the sequence <code nobreak="false">2, 3</code>.</p>
               </note>
               <p>If the value of <code nobreak="false">
                     <var>INPUT</var>
                  </code> is a map, then the 
               <code nobreak="false">
                     <var>FILTER</var>
                  </code> expression is evaluated
               for each entry in the map, with the context value set to an item of type
               <code nobreak="false">record(key as xs:anyAtomicType, value as item()*)</code>, in which the <code nobreak="false">key</code>
               and <code nobreak="false">value</code> fields represent the key and value of the map entry. 
               The context position is the position of the entry in the map 
               (in <xtermref spec="DM40" ref="dt-entry-order"/>),
               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 <termref def="dt-predicate-truth-value"/> of the <code nobreak="false">
                     <var>FILTER</var>
                  </code> expression is true.
               The relative order of entries in the result retains the relative order of entries in the input.
            </p>
               <p>For example, the following expression:</p>
               <eg xml:space="preserve">let $map := { 1: "alpha", 2: "beta", 3: "gamma" }
return $map?[?key ge 2]</eg>
               <p>returns:</p>
               <eg xml:space="preserve">{ 2: "beta", 3: "gamma" }</eg>
               <note>
                  <p>A filter expression such as <code nobreak="false">$map?[last()-1, last()]</code>
                  might be used to return the last two entries of a map in
                  <xtermref spec="DM40" ref="dt-entry-order"/>.</p>
               </note>
            </div3>
         </div2>
         <div2 id="id-conditionals">
            <head>Conditional Expressions</head>
            <changes>
               <change issue="234" PR="284" date="2023-01-23">
               Alternative syntax for conditional expressions is available: <code nobreak="false">if (condition) { X }</code>.
            </change>
            </changes>
            <p diff="chg" at="2022-12-07">XPath 4.0 allows conditional expressions to be written in several different ways.</p>
            <scrap headstyle="show">
               <prod id="doc-xpath40-IfExpr">
                  <lhs>IfExpr</lhs>
                  <rhs>"if"  "("  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>  ")"  (<nt def="prod-xpath40-UnbracedActions">UnbracedActions<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-BracedAction">BracedAction<!--$idref_lang_part = xpath40- --></nt>)</rhs>
               </prod>

               <prod id="doc-xpath40-IfExpr-Expr">
                  <lhs>Expr</lhs>
                  <rhs>(<nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt> ++ ",")</rhs>
               </prod>

               <prod id="doc-xpath40-IfExpr-UnbracedActions">
                  <lhs>UnbracedActions</lhs>
                  <rhs>"then"  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>  "else"  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-IfExpr-ExprSingle">
                  <lhs>ExprSingle</lhs>
                  <rhs>
                     <nt def="prod-xpath40-ForExpr">ForExpr<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-LetExpr">LetExpr<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-QuantifiedExpr">QuantifiedExpr<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-IfExpr">IfExpr<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-OrExpr">OrExpr<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-IfExpr-BracedAction">
                  <lhs>BracedAction</lhs>
                  <rhs>
                     <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-IfExpr-EnclosedExpr">
                  <lhs>EnclosedExpr</lhs>
                  <rhs>"{"  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>?  "}"</rhs>
               </prod>
            </scrap>
            <p>The braced expression <code nobreak="false">if (<var>C</var>) then {<var>T</var>}</code> is equivalent to the
         unbraced expression <code nobreak="false">if (<var>C</var>) then <var>T</var> else ()</code>.</p>
            <p>The value <var>V</var> of a conditional expression in the form <code nobreak="false">if (<var>C</var>) then <var>T</var>
         else <var>E</var>
               </code> is obtained as follows:</p>
            <olist>
               <item>
                  <p>Let <var>B</var> be the <termref def="dt-ebv">effective boolean value</termref> of the test expression
                       <var>C</var>, as defined in <specref ref="id-ebv"/>.</p>
               </item>
               <item>
                  <p>If <var>B</var> is true, <var>V</var> is the
                    result of evaluating <var>T</var>.</p>
               </item>
               <item>
                  <p>Otherwise, <var>V</var> is the
                    result of evaluating <var>E</var>.</p>
               </item>
            </olist>
            <p>Conditional expressions have a special rule for propagating <termref def="dt-dynamic-error">dynamic errors</termref>: <phrase diff="chg" at="2023-01-10">expressions whose value is not needed for
                  computing the result are
            <termref def="dt-guarded"/>, as described in <specref ref="id-guarded-expressions"/>, to prevent
                  spurious dynamic errors.</phrase>
            </p>
            <p>Here are some examples of conditional expressions:</p>
            <ulist>
               <item>
                  <p>In this example, the test expression is a comparison expression:</p>
                  <eg role="parse-test" xml:space="preserve">if ($widget1/unit-cost &lt; $widget2/unit-cost)
then $widget1
else $widget2</eg>
               </item>
               <item>
                  <p>In this example, the test expression tests for the existence of an attribute
named <code nobreak="false">discounted</code>, independently of its value:</p>
                  <eg role="parse-test" xml:space="preserve">if ($part/@discounted)
then $part/wholesale
else $part/retail</eg>
               </item>
               <item diff="add" at="2022-12-07">
                  <p>The following example returns the attribute node <code nobreak="false">@discount</code> provided the value of <code nobreak="false">@price</code>
                  is greater than 100; otherwise it returns the empty sequence:</p>
                  <eg role="parse-test" xml:space="preserve">if (@price gt 100) { @discount }</eg>
               </item>
               <item diff="add" at="2023-01-10">
                  <p>The following example tests a number of conditions:</p>
                  <eg role="parse-test" xml:space="preserve">if (@code = 1) then
  "food"
else if (@code = 2) then
  "fashion"
else if (@code = 3) then
  "household"
else 
  "general"
</eg>
               </item>
            </ulist>
            <note diff="add" at="2023-01-10">
               <p>The “dangling else ambiguity” found in many other languages cannot arise:</p>
               <ulist>
                  <item>
                     <p>In the unbraced format, both the <code nobreak="false">then</code> and <code nobreak="false">else</code> clauses
                  are mandatory.</p>
                  </item>
                  <item>
                     <p>In the braced format, the expression terminates unambiguously with the closing
                  brace.</p>
                  </item>
               </ulist>
            </note>
         </div2>
         <div2 id="id-otherwise" diff="add" at="A">
            <head>Otherwise Expressions</head>
            <changes>
               <change issue="1024" PR="1031" date="2024-02-27">
               An <code nobreak="false">otherwise</code> operator is introduced: <code nobreak="false">A otherwise B</code> returns the
               value of <code nobreak="false">A</code>, unless it is the empty sequence, in which case it returns the value of <code nobreak="false">B</code>.
            </change>
            </changes>
            <scrap headstyle="show">
               <prod id="doc-xpath40-OtherwiseExpr">
                  <lhs>OtherwiseExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-StringConcatExpr">StringConcatExpr<!--$idref_lang_part = xpath40- --></nt>  ("otherwise"  <nt def="prod-xpath40-StringConcatExpr">StringConcatExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
               </prod>

               <prod id="doc-xpath40-OtherwiseExpr-StringConcatExpr">
                  <lhs>StringConcatExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-RangeExpr">RangeExpr<!--$idref_lang_part = xpath40- --></nt>  ("||"  <nt def="prod-xpath40-RangeExpr">RangeExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
               </prod>
            </scrap>
            <p>The <code nobreak="false">otherwise</code> expression returns the value of its first operand, unless this is the empty
         sequence, in which case it returns the value of its second operand.</p>
            <p>For example, <code nobreak="false">@price - (@discount otherwise 0)</code> returns the value of <code nobreak="false">@price - @discount</code>,
         if the attribute <code nobreak="false">@discount</code> exists, or the value of <code nobreak="false">@price</code> if the <code nobreak="false">@discount</code>
            attribute is absent.</p>
            <p>To prevent spurious errors, the right hand operand is <termref def="dt-guarded"/>: it cannot throw any
            dynamic error unless the left-hand operand returns the empty sequence.</p>
            <note>
               <p>The operator is associative (even under error conditions): <code nobreak="false">A otherwise (B otherwise C)</code> returns
         the same result as <code nobreak="false">(A otherwise B) otherwise C</code>.</p>
               <p>The <code nobreak="false">otherwise</code> operator binds more tightly than comparison operators such as
            <code nobreak="false">=</code>, but less tightly than string concatenation (<code nobreak="false">||</code>) or arithemetic
            operators. The expression <code nobreak="false">$a = @x otherwise @y + 1</code> parses as 
               <code nobreak="false">$a = (@x otherwise (@y + 1))</code>.</p>
            </note>
         </div2>
         <div2 id="id-quantified-expressions">
            <head>Quantified Expressions</head>
            <changes>
               <change issue="1316" PR="1384" date="2024-08-13">
               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.
            </change>
            </changes>
            <p>Quantified expressions support existential and universal quantification. The
value of a quantified expression is always <code nobreak="false">true</code> or <code nobreak="false">false</code>.</p>
            <scrap headstyle="show">
               <prod id="doc-xpath40-QuantifiedExpr">
                  <lhs>QuantifiedExpr</lhs>
                  <rhs>("some"  |  "every")  (<nt def="prod-xpath40-QuantifierBinding">QuantifierBinding<!--$idref_lang_part = xpath40- --></nt> ++ ",")  "satisfies"  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-QuantifiedExpr-QuantifierBinding">
                  <lhs>QuantifierBinding</lhs>
                  <rhs>
                     <nt def="prod-xpath40-VarNameAndType">VarNameAndType<!--$idref_lang_part = xpath40- --></nt>  "in"  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-QuantifiedExpr-VarNameAndType">
                  <lhs>VarNameAndType</lhs>
                  <rhs>"$"  <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                     <nt def="prod-xpath40-TypeDeclaration">TypeDeclaration<!--$idref_lang_part = xpath40- --></nt>?</rhs>
               </prod>

               <prod id="doc-xpath40-QuantifiedExpr-EQName">
                  <lhs>EQName</lhs>
                  <rhs>
                     <nt def="prod-xpath40-QName">QName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-QuantifiedExpr-TypeDeclaration">
                  <lhs>TypeDeclaration</lhs>
                  <rhs>"as"  <nt def="prod-xpath40-SequenceType">SequenceType<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-QuantifiedExpr-SequenceType">
                  <lhs>SequenceType</lhs>
                  <rhs>("empty-sequence"  "("  ")")<br/>|  (<nt def="prod-xpath40-ItemType">ItemType<!--$idref_lang_part = xpath40- --></nt>
                     <nt def="prod-xpath40-OccurrenceIndicator">OccurrenceIndicator<!--$idref_lang_part = xpath40- --></nt>?)</rhs>
               </prod>

               <prod id="doc-xpath40-QuantifiedExpr-ExprSingle">
                  <lhs>ExprSingle</lhs>
                  <rhs>
                     <nt def="prod-xpath40-ForExpr">ForExpr<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-LetExpr">LetExpr<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-QuantifiedExpr">QuantifiedExpr<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-IfExpr">IfExpr<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-OrExpr">OrExpr<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>
            </scrap>
            <p>A <term>quantified expression</term> begins with
a <term>quantifier</term>, which is the keyword <code nobreak="false">some</code> or <code nobreak="false">every</code>, 
followed by one or more in-clauses that are used to bind variables,
followed by the keyword <code nobreak="false">satisfies</code> 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:</p>
            <olist>
               <item>
                  <p>If the <nt def="doc-xpath40-QuantifiedExpr">QuantifiedExpr<!--$spec = xpath40--></nt> contains
               more than one <nt def="prod-xpath40-QuantifierBinding">QuantifierBinding<!--$spec = xpath40--></nt>, then it is equivalent
            to the expression obtained by replacing each comma with <code nobreak="false">satisfies some</code> or <code nobreak="false">satisfies every</code>
            respectively. For example, the expression <code nobreak="false">some $x in X, $y in Y satisfies $x = $y</code>
               is equivalent to <code nobreak="false">some $x in X satisfies some $y in Y satisfies $x = $y</code>,
               while the expression <code nobreak="false">every $x in X, $y in Y satisfies $x lt $y</code> is equivalent to
               <code nobreak="false">every $x in X satisfies every $y in Y satisfies $x lt $y</code>
                  </p>
               </item>
               <item>
                  <p>If the quantifier is <code nobreak="false">some</code>, the <nt def="doc-xpath40-QuantifiedExpr">QuantifiedExpr<!--$spec = xpath40--></nt> returns <code nobreak="false">true</code> 
                  if at least one evaluation of the test expression has the <termref def="dt-ebv">effective boolean value</termref>
                     <code nobreak="false">true</code>; otherwise it returns <code nobreak="false">false</code>. In consequence, if the binding sequence is empty, 
                  the result of the <nt def="doc-xpath40-QuantifiedExpr">QuantifiedExpr<!--$spec = xpath40--></nt> is <code nobreak="false">false</code>.</p>
               </item>
               <item>
                  <p>If the quantifier is <code nobreak="false">every</code>, the <nt def="doc-xpath40-QuantifiedExpr">QuantifiedExpr<!--$spec = xpath40--></nt> returns <code nobreak="false">true</code> 
                  if every evaluation of the test expression has the <termref def="dt-ebv">effective boolean value</termref>
                     <code nobreak="false">true</code>; otherwise it returns <code nobreak="false">false</code>. In consequence, if the binding sequence is empty, 
                  the result of the <nt def="doc-xpath40-QuantifiedExpr">QuantifiedExpr<!--$spec = xpath40--></nt> is <code nobreak="false">true</code>.</p>
               </item>
            </olist>
            <p>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.
</p>
            <p>Each variable binding may be accompanied by a <term>type declaration</term>, 
            which consists of the keyword <code nobreak="false">as</code> followed by the static type of 
            the variable, declared using the syntax in  <specref ref="id-sequencetype-syntax"/>. 
            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 <termref def="dt-coercion-rules"/>. If conversion is not possible,                     
            a <termref def="dt-type-error">type error</termref> is raised <errorref class="TY" code="0004"/>.</p>
            <p diff="chg" at="issue845">The order in which test expressions are evaluated 
            for the various items in the binding sequence is <termref def="dt-implementation-dependent">implementation-dependent</termref>. If the quantifier
               is <code nobreak="false">some</code>, an implementation may
               return <code nobreak="false">true</code> as soon as it finds one item for which the test expression has
               an <termref def="dt-ebv">effective boolean value</termref> of <code nobreak="false">true</code>, and it may raise a <termref def="dt-dynamic-error">dynamic error</termref> as soon as it finds one item for
            which the test expression raises an error. Similarly, if the quantifier is <code nobreak="false">every</code>, an 
            implementation may return <code nobreak="false">false</code> as soon as it finds one item for which the test expression has
            an <termref def="dt-ebv">effective boolean value</termref> of <code nobreak="false">false</code>, and it may raise a <termref def="dt-dynamic-error">dynamic error</termref> 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.</p>
            <p>Here are some examples of quantified expressions:</p>
            <ulist>
               <item>
                  <p>This expression is <code nobreak="false">true</code> if every <code nobreak="false">part</code> element has a <code nobreak="false">discounted</code> attribute (regardless of the values of these attributes):</p>
                  <eg role="parse-test" xml:space="preserve">every $part in /parts/part satisfies $part/@discounted</eg>
               </item>
               <item>
                  <p>This expression is <code nobreak="false">true</code> if at least
one <code nobreak="false">employee</code> element satisfies the given comparison expression:</p>
                  <eg role="parse-test" xml:space="preserve">some $emp in /emps/employee satisfies $emp/bonus &gt; 0.25 * $emp/salary</eg>
               </item>
               <item>
                  <p>This expression is <code nobreak="false">true</code> if every
                  <code nobreak="false">employee</code> element has at least one <code nobreak="false">salary</code> child with the attribute <code nobreak="false">current="true"</code>:</p>
                  <eg role="parse-test" xml:space="preserve">every $emp in /emps/employee satisfies (
  some $sal in $emp/salary satisfies $sal/@current = 'true'
)</eg>
                  <note diff="add" at="A">
                     <p>Like many quantified expressions, this can be simplified. This example can be written
                  <code nobreak="false">every $emp in /emps/employee satisfies $emp/salary[@current = 'true']</code>, or even
                  more concisely as <code nobreak="false">empty(/emps/employee[not(salary/@current = 'true')]</code>.</p>
                     <p>Another alternative in XPath 4.0 is to use the higher-order functions <function>fn:some</function> and <function>fn:every</function>.
               This example can be written <code diff="chg" at="2023-04-25" nobreak="false">every(/emps/employee, fn { salary/@current = 'true' })</code>
                     </p>
                  </note>
               </item>
               <item>
                  <p>In the following examples, each quantified expression evaluates its test
expression over nine pairs of items, formed from the Cartesian
product of the sequences <code nobreak="false">(1, 2, 3)</code> and <code nobreak="false">(2, 3, 4)</code>. 
                  The expression beginning with <code nobreak="false">some</code> evaluates to <code nobreak="false">true</code>, 
                  and the expression beginning with <code nobreak="false">every</code> evaluates to <code nobreak="false">false</code>.</p>
                  <eg role="parse-test" xml:space="preserve">some $x in (1, 2, 3), $y in (2, 3, 4) satisfies $x + $y = 4</eg>
                  <eg role="parse-test" xml:space="preserve">every $x in (1, 2, 3), $y in (2, 3, 4) satisfies $x + $y = 4</eg>
               </item>
               <item>
                  <p>This quantified expression may either return  <code nobreak="false">true</code> or raise a <termref def="dt-type-error">type error</termref>, since its test expression returns <code nobreak="false">true</code> for one item
and raises a <termref def="dt-type-error">type error</termref> for another:</p>
                  <eg role="parse-test" xml:space="preserve">some $x in (1, 2, "cat") satisfies $x * 2 = 4</eg>
               </item>
               <item>
                  <p>This quantified expression may either return <code nobreak="false">false</code> or raise a <termref def="dt-type-error">type error</termref>, since its test expression returns <code nobreak="false">false</code> for one item and raises a <termref def="dt-type-error">type error</termref> for another:</p>
                  <eg role="parse-test" xml:space="preserve">every $x in (1, 2, "cat") satisfies $x * 2 = 4</eg>
               </item>
               <item>
                  <p>This quantified expression returns <code nobreak="false">true</code>, because the binding sequence
                  is empty, despite the fact that the condition can never be satisfied:</p>
                  <eg role="parse-test" xml:space="preserve">every $x in () satisfies ($x lt 0 and $x gt 0)</eg>
               </item>
               <item>
                  <p>This quantified expression is <termref def="dt-implausible"/> because
                  it will always fail with a type error except in the case where <code nobreak="false">$input</code>
                  is the empty sequence. If <code nobreak="false">$input</code> contains one or more <code nobreak="false">xs:date</code>
                  values, a processor <rfc2119>must</rfc2119> raise a type error on the grounds that an <code nobreak="false">xs:date</code>
                  cannot be compared to an <code nobreak="false">xs:integer</code>. If <code nobreak="false">$input</code> is empty, the
                  processor <rfc2119>may</rfc2119> (or may not) report this error:</p>
                  <eg role="parse-test" xml:space="preserve">every $x as xs:date in $input satisfies ($x lt 0)</eg>
               </item>
               <item>
                  <p>This quantified expression  contains a <nt def="prod-xpath40-TypeDeclaration">type declaration<!--$spec = xpath40--></nt> that is not satisfied by every item in the  test expression. 
                  The expression may either return <code nobreak="false">true</code> or raise a <termref def="dt-type-error">type error</termref>.</p>
                  <eg role="parse-test" xml:space="preserve">some $x as xs:integer in (1, 2, "cat") satisfies $x * 2 = 4</eg>
               </item>
            </ulist>
         </div2>
         <div2 id="id-expressions-on-datatypes">
            <head>Expressions on SequenceTypes</head>
            <p>
The <code nobreak="false">instance
of</code>, <code nobreak="false">cast</code>, <code nobreak="false">castable</code>,
and <code nobreak="false">treat</code> expressions are used to test whether a value
conforms to a given type or to convert it to an instance of a given
type.
</p>
            <div3 id="id-instance-of">
               <head>Instance Of</head>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-InstanceofExpr">
                     <lhs>InstanceofExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-TreatExpr">TreatExpr<!--$idref_lang_part = xpath40- --></nt>  ("instance"  "of"  <nt def="prod-xpath40-SequenceType">SequenceType<!--$idref_lang_part = xpath40- --></nt>)?</rhs>
                  </prod>

                  <prod id="doc-xpath40-InstanceofExpr-TreatExpr">
                     <lhs>TreatExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-CastableExpr">CastableExpr<!--$idref_lang_part = xpath40- --></nt>  ("treat"  "as"  <nt def="prod-xpath40-SequenceType">SequenceType<!--$idref_lang_part = xpath40- --></nt>)?</rhs>
                  </prod>

                  <prod id="doc-xpath40-InstanceofExpr-SequenceType">
                     <lhs>SequenceType</lhs>
                     <rhs>("empty-sequence"  "("  ")")<br/>|  (<nt def="prod-xpath40-ItemType">ItemType<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-OccurrenceIndicator">OccurrenceIndicator<!--$idref_lang_part = xpath40- --></nt>?)</rhs>
                  </prod>
               </scrap>
               <p>The boolean
operator <code nobreak="false">instance of</code>
returns <code nobreak="false">true</code> if the value of its first operand matches
the <nt def="doc-xpath40-SequenceType">SequenceType<!--$spec = xpath40--></nt> in its second
operand, according to the rules for <termref def="dt-sequencetype-matching">SequenceType
matching</termref>; otherwise it returns <code nobreak="false">false</code>. For example:</p>
               <ulist>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">5 instance of xs:integer</code>
                     </p>
                     <p>This example returns <code nobreak="false">true</code> because the given value is an instance of the given type.</p>
                  </item>
                  <item>
                     <p>
                        <code nobreak="false">5 instance of xs:decimal</code>
                     </p>
                     <p>This example returns <code nobreak="false">true</code> because the given value is an integer literal, and <code nobreak="false">xs:integer</code> is derived by restriction from <code nobreak="false">xs:decimal</code>.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">(5, 6) instance of xs:integer+</code>
                     </p>
                     <p>This example returns <code nobreak="false">true</code> because the given sequence contains two integers, and is a valid instance of the specified type.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">. instance of element()</code>
                     </p>
                     <p>This example returns <code nobreak="false">true</code> if the context value is a
                     single element node or <code nobreak="false">false</code> if the context value is defined 
                     but is not a single element node. If the context value is <xtermref spec="DM40" ref="dt-absent"/>, a <termref def="dt-type-error"/>
                        is raised <errorref class="DY" code="0002"/>.</p>
                  </item>
               </ulist>
               <note>
                  <p>An <code nobreak="false">instance of</code> test does not allow any kind of casting or coercion.
            The results may therefore be counterintuitive. For example, the expression
            <code nobreak="false">3 instance of xs:positiveInteger</code> returns <code nobreak="false">false</code>, because
            the expression <code nobreak="false">3</code> evaluates to an instance of <code nobreak="false">xs:integer</code>,
            not <code nobreak="false">xs:positiveInteger</code>. For similar reasons, <code nobreak="false">"red" instance of
            enum("red", "green", "blue")</code> returns false.</p>
                  <p>On such occasions, a <code nobreak="false">castable as</code> test may be more appropriate:
            see <specref ref="id-castable"/>
                  </p>
               </note>
            </div3>
            <div3 id="id-cast">
               <head>Cast</head>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-CastExpr">
                     <lhs>CastExpr</lhs>
                     <rhs>
                        <nt def="doc-xpath40-PipelineExpr">PipelineExpr<!--$idref_lang_part = xpath40- --></nt>  ("cast"  "as"  <nt def="prod-xpath40-CastTarget">CastTarget<!--$idref_lang_part = xpath40- --></nt>  "?"?)?</rhs>
                  </prod>

                  <prod id="doc-xpath40-CastExpr-PipelineExpr">
                     <lhs>PipelineExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-ArrowExpr">ArrowExpr<!--$idref_lang_part = xpath40- --></nt>  ("-&gt;"  <nt def="prod-xpath40-ArrowExpr">ArrowExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
                  </prod>

                  <prod id="doc-xpath40-CastExpr-CastTarget">
                     <lhs>CastTarget</lhs>
                     <rhs>
                        <nt def="prod-xpath40-TypeName">TypeName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ChoiceItemType">ChoiceItemType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-EnumerationType">EnumerationType<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-CastExpr-TypeName">
                     <lhs>TypeName</lhs>
                     <rhs>
                        <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-CastExpr-EQName">
                     <lhs>EQName</lhs>
                     <rhs>
                        <nt def="prod-xpath40-QName">QName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-CastExpr-ChoiceItemType">
                     <lhs>ChoiceItemType</lhs>
                     <rhs>"("  (<nt def="prod-xpath40-ItemType">ItemType<!--$idref_lang_part = xpath40- --></nt> ++ "|")  ")"</rhs>
                  </prod>

                  <prod id="doc-xpath40-CastExpr-ItemType">
                     <lhs>ItemType</lhs>
                     <rhs>
                        <nt def="prod-xpath40-RegularItemType">RegularItemType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-FunctionType">FunctionType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-TypeName">TypeName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ChoiceItemType">ChoiceItemType<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-CastExpr-EnumerationType">
                     <lhs>EnumerationType</lhs>
                     <rhs>"enum"  "("  (<nt def="doc-xpath40-StringLiteral">StringLiteral<!--$idref_lang_part = xpath40- --></nt> ++ ",")  ")"</rhs>
                  </prod>
               </scrap>
               <p>Sometimes
it is necessary to convert a value to a specific datatype. For this
purpose, XPath 4.0 provides a <code nobreak="false">cast</code> expression that
creates a new value of a specific type based on an existing value. A
<code nobreak="false">cast</code> expression takes two operands: an <term>input
expression</term> and a <term>target type</term>. The type of the
atomized value of the input expression is called the <term>input type</term>. 
The target type must be a <termref def="dt-generalized-atomic-type"/>. In practice
               this means it may be any of:</p>
               <ulist>
                  <item diff="add" at="issue688">
                     <p>The name of an <termref def="dt-named-item-type">named item type</termref>
               defined in the <termref def="dt-static-context"/>, which in turn must refer to an item
               type in one of the following categories.</p>
                  </item>
                  <item>
                     <p>The name of a type defined in the  <termref def="dt-is-types">in-scope schema types</termref>, 
                  which must be a simple type (of variety atomic, list or union) <errorref class="ST" code="0052"/> .
                  In addition, the target type cannot be <code nobreak="false">xs:NOTATION</code>, <code nobreak="false">xs:anySimpleType</code>,
                  or <code nobreak="false">xs:anyAtomicType</code>
                     </p>
                  </item>
                  <item diff="add" at="A">
                     <p>A <code nobreak="false">ChoiceItemType</code> representing a 
                  <termref def="dt-generalized-atomic-type"/> (such as <code nobreak="false">(xs:date | xs:dateTime)</code>).</p>
                  </item>
                  <item diff="add" at="issue688">
                     <p>An <code nobreak="false">EnumerationType</code> such as <code nobreak="false">enum("red", "green", "blue")</code>.</p>
                  </item>
               </ulist>
               <p>Otherwise, a static error is raised <errorref class="ST" code="0080"/>.</p>
               <p>The optional occurrence indicator <code nobreak="false">?</code> denotes that the empty
sequence is permitted.</p>
               <p>Casting a node to <code nobreak="false">xs:QName</code> can cause surprises because it uses the <termref def="dt-static-context"/>
               of the cast expression to provide the <termref def="dt-namespace-binding">namespace bindings</termref> for this operation. 
               Instead of casting to <code nobreak="false">xs:QName</code>, it is generally preferable to use the <function>fn:QName</function> 
               function, which allows the namespace context to be taken from the document containing the QName.</p>
               <p>The semantics of the <code nobreak="false">cast</code> expression
are as follows:</p>
               <olist>
                  <item>
                     <p>The input expression is evaluated.</p>
                  </item>
                  <item>
                     <p>The result of the first step is <termref def="dt-atomization">atomized</termref>.</p>
                  </item>
                  <item>
                     <p> If the result of atomization is a
sequence of more than one atomic item, a <termref def="dt-type-error">type error</termref> is raised <errorref class="TY" code="0004"/>.</p>
                  </item>
                  <item>
                     <p>If the result
of atomization is the empty sequence:</p>
                     <olist>
                        <item>
                           <p>If
<code nobreak="false">?</code> is specified after the target type, the result of the
<code nobreak="false">cast</code> expression is the empty sequence.</p>
                        </item>
                        <item>
                           <p>
If <code nobreak="false">?</code> is not specified after the target type, a <termref def="dt-type-error">type error</termref> is raised <errorref class="TY" code="0004"/>.</p>
                        </item>
                     </olist>
                  </item>
                  <item>
                     <p>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 <xspecref spec="FO40" ref="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 <termref def="dt-issd">in-scope schema
definitions</termref> or by using an alternative, <termref def="dt-implementation-dependent">implementation-dependent</termref>
mechanism such as a data dictionary.

The result of a cast expression is one of the following: 

<olist>
                           <item>
                              <p> 
    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).
  </p>
                           </item>
                           <item>
                              <p> 
    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).
  </p>
                           </item>
                           <item>
                              <p> 
    A dynamic error, if the particular input value cannot be
    converted to the target type (for example, attempting to convert
    the string <code nobreak="false">"three"</code> to an integer).
  </p>
                           </item>
                        </olist>
                     </p>
                     <note diff="add" at="issue688">
                        <p>Casting to an enumeration type relies on the fact that an enumeration type
                  is a generalized atomic type. So the expression <code nobreak="false">cast $x as enum("red", "green")</code> 
                  has the following effect:</p>
                        <ulist>
                           <item>
                              <p>If <code nobreak="false">$x</code> is an instance of <code nobreak="false">xs:string</code>,
                           the expression returns <code nobreak="false">$x</code> unchanged if it is one of the
                           permitted strings, and raises a dynamic error otherwise;</p>
                           </item>
                           <item>
                              <p>In other cases, the expression first casts <code nobreak="false">$x</code> to
                     <code nobreak="false">xs:string</code>, and then proceeds as above.</p>
                           </item>
                        </ulist>
                     </note>
                  </item>
               </olist>
            </div3>
            <div3 id="id-castable">
               <head>Castable</head>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-CastableExpr">
                     <lhs>CastableExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-CastExpr">CastExpr<!--$idref_lang_part = xpath40- --></nt>  ("castable"  "as"  <nt def="prod-xpath40-CastTarget">CastTarget<!--$idref_lang_part = xpath40- --></nt>  "?"?)?</rhs>
                  </prod>

                  <prod id="doc-xpath40-CastableExpr-CastExpr">
                     <lhs>CastExpr</lhs>
                     <rhs>
                        <nt def="doc-xpath40-PipelineExpr">PipelineExpr<!--$idref_lang_part = xpath40- --></nt>  ("cast"  "as"  <nt def="prod-xpath40-CastTarget">CastTarget<!--$idref_lang_part = xpath40- --></nt>  "?"?)?</rhs>
                  </prod>

                  <prod id="doc-xpath40-CastableExpr-CastTarget">
                     <lhs>CastTarget</lhs>
                     <rhs>
                        <nt def="prod-xpath40-TypeName">TypeName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ChoiceItemType">ChoiceItemType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-EnumerationType">EnumerationType<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-CastableExpr-TypeName">
                     <lhs>TypeName</lhs>
                     <rhs>
                        <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-CastableExpr-EQName">
                     <lhs>EQName</lhs>
                     <rhs>
                        <nt def="prod-xpath40-QName">QName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-CastableExpr-ChoiceItemType">
                     <lhs>ChoiceItemType</lhs>
                     <rhs>"("  (<nt def="prod-xpath40-ItemType">ItemType<!--$idref_lang_part = xpath40- --></nt> ++ "|")  ")"</rhs>
                  </prod>

                  <prod id="doc-xpath40-CastableExpr-ItemType">
                     <lhs>ItemType</lhs>
                     <rhs>
                        <nt def="prod-xpath40-RegularItemType">RegularItemType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-FunctionType">FunctionType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-TypeName">TypeName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ChoiceItemType">ChoiceItemType<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="doc-xpath40-CastableExpr-EnumerationType">
                     <lhs>EnumerationType</lhs>
                     <rhs>"enum"  "("  (<nt def="doc-xpath40-StringLiteral">StringLiteral<!--$idref_lang_part = xpath40- --></nt> ++ ",")  ")"</rhs>
                  </prod>
               </scrap>
               <p>XPath 4.0
provides an expression that tests whether a given value
is castable into a given target type. 

The <phrase diff="chg" at="A">target type</phrase> is subject to the same
               rules as the target type of a <code nobreak="false">cast</code> expression.</p>
               <p>The expression <code role="parse-test" nobreak="false">E castable as T</code> returns <code nobreak="false">true</code> 
if the result of evaluating <code nobreak="false">E</code>  
can be successfully cast into the target type <code nobreak="false">T</code> by using a <code nobreak="false">cast</code> expression; 
otherwise it returns <code nobreak="false">false</code>. 
If evaluation of <code nobreak="false">E</code> fails with a dynamic error or if the value of <code nobreak="false">E</code> cannot be atomized, 
the <code nobreak="false">castable</code> expression as a whole fails.</p>
               <p>The <code nobreak="false">castable</code> expression can be used as a <termref def="dt-predicate">predicate</termref>  to
avoid errors at evaluation time. 
It can also be used to select an appropriate type for processing of a given value, as illustrated in
the following example:</p>
               <eg role="parse-test" xml:space="preserve">
if ($x castable as hatsize)
then $x cast as hatsize
else if ($x castable as IQ)
then $x cast as IQ
else $x cast as xs:string</eg>
               <note diff="add" at="issue688">
                  <p>The expression <code nobreak="false">$x castable as enum("red", "green", "blue")</code>
               is for most practical purposes equivalent to <code nobreak="false">$x = ("red", "green", "blue")</code>;
            the main difference is that it uses the Unicode codepoint collation for comparing strings,
            not the default collation from the static context.</p>
               </note>
            </div3>
            <div3 id="id-constructor-functions">
               <head>Constructor Functions</head>
               <p>For every simple type in the <termref def="dt-is-types">in-scope schema types</termref>  (except <code nobreak="false">xs:NOTATION</code> and 
               <code nobreak="false">xs:anyAtomicType</code>, and <code nobreak="false">xs:anySimpleType</code>, which 
               are not instantiable), a <term>constructor function</term> is implicitly defined. 
               In each case, the name of the constructor function is the same as the name of 
               its target type (including namespace). The signature of the constructor 
               function for  a given type depends on the type that is being constructed, 
               and can be found in <xspecref spec="FO40" ref="constructor-functions"/>.</p>
               <p>There is also a constructor function for every <termref def="dt-named-item-type"/> 
               in the <termref def="dt-static-context"/>
            that expands either to a <termref def="dt-generalized-atomic-type"/>
                  <phrase diff="add" at="issue617">or to
            a <nt def="doc-xpath40-RecordType">RecordType<!--$spec = xpath40--></nt>
                  </phrase>.</p>
               <p>All such constructor functions are classified as
               <termref def="dt-system-function">system functions</termref>.</p>
               <note diff="add" at="issue617">
                  <p>The constructor function is present in the static
            context if and only if the corresponding type is present in the static context.</p>
                  <p>For XSLT, this means that a constructor function corresponding to an imported
            schema type is private to the stylesheet package, and a constructor function
            corresponding to an <code nobreak="false">xsl:item-type</code> declaration has the same visibility
               as the <code nobreak="false">xsl:item-type</code> declaration.</p>
                  <p>For XQuery, this means that a constructor function corresponding to an imported
                  schema type is private to the query module, and a constructor function
                  corresponding to a named item type declaration is <code nobreak="false">%public</code>
                  or <code nobreak="false">%private</code> according to the annotations on the item type declaration.</p>
               </note>
               <p>
                  <termdef term="constructor function" id="dt-constructor-function">The <term>constructor function</term> 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 <code nobreak="false">T($arg)</code> are defined to be equivalent to the expression <code role="parse-test" nobreak="false">$arg cast as T?</code>.</termdef>
               </p>
               <p>The following examples illustrate the use of constructor functions:</p>
               <ulist>
                  <item>
                     <p>This
example is equivalent to <code role="parse-test" nobreak="false">"2000-01-01" cast as
xs:date?</code>.</p>
                     <eg role="parse-test" xml:space="preserve">xs:date("2000-01-01")</eg>
                  </item>
                  <item>
                     <p>This
example is equivalent to

<code role="parse-test" nobreak="false">($floatvalue * 0.2E-5) cast as xs:decimal?</code>.</p>
                     <eg role="parse-test" xml:space="preserve">xs:decimal($floatvalue * 0.2E-5)</eg>
                  </item>
                  <item>
                     <p>This example returns an
<code nobreak="false">xs:dayTimeDuration</code> value equal to 21 days. It is
equivalent to <code role="parse-test" nobreak="false">"P21D" cast as xs:dayTimeDuration?</code>.</p>
                     <eg role="parse-test" xml:space="preserve">xs:dayTimeDuration("P21D")</eg>
                  </item>
                  <item diff="add" at="issue688">
                     <p>If
                     <code nobreak="false">usa:zipcode</code> is a user-defined <termref def="dt-atomic-type"/>
in the <termref def="dt-is-types">in-scope schema types</termref>, then the
following expression is equivalent to the
expression <code role="parse-test" nobreak="false">("12345" cast as
usa:zipcode?)</code>.</p>
                     <eg role="parse-test" xml:space="preserve">usa:zipcode("12345")</eg>
                  </item>
                  <item>
                     <p>If <code nobreak="false">my:chrono</code> is a named item type that expands to
                     <code nobreak="false">(xs:date | xs:time | xs:dateTime)</code>, then the result
                     of <code nobreak="false">my:chrono("12:00:00Z")</code> is the <code nobreak="false">xs:time</code>
                     value <code nobreak="false">12:00:00Z</code>.</p>
                  </item>
                  <item diff="add" at="issue617">
                     <p>If <code nobreak="false">my:location</code> is a named item type that expands
                  to <code nobreak="false">record(latitude as xs:double, longitude as xs:double)</code>,
                  then the result of <code nobreak="false">my:location(50.52, -3.02)</code> is
                  the map <code nobreak="false">{ 'latitude': 50.52e0, 'longitude': -3.02e0 }</code>.</p>
                  </item>
               </ulist>
               <note>
                  <p>
                  An instance of an <termref def="dt-atomic-type"/> whose name is in no namespace can be
  constructed by using a <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$spec = xpath40--></nt> 
  in either a cast expression or a constructor function call.  Examples:
  </p>
                  <eg role="parse-test" xml:space="preserve">17 cast as Q{}apple</eg>
                  <eg role="parse-test" xml:space="preserve">Q{}apple(17)</eg>
                  <p diff="chg" at="A">In either context, using an unqualified NCName might not work:
                  in a cast expression, an unqualified name is it is interpreted
                  according to the <termref def="dt-default-namespace-elements-and-types"/>,
                  while an unqualified name in a constructor function call is resolved using the
                  <termref def="dt-default-function-namespace"/> which will often be inappropriate.
               </p>
               </note>
            </div3>
            <div3 id="id-treat">
               <head>Treat</head>
               <changes>
                  <change issue="2165">The <code nobreak="false">treat as</code> expression now raises
               a type error rather than a dynamic error when it fails.</change>
               </changes>
               <scrap headstyle="show">
                  <prod id="doc-xpath40-TreatExpr">
                     <lhs>TreatExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-CastableExpr">CastableExpr<!--$idref_lang_part = xpath40- --></nt>  ("treat"  "as"  <nt def="prod-xpath40-SequenceType">SequenceType<!--$idref_lang_part = xpath40- --></nt>)?</rhs>
                  </prod>

                  <prod id="doc-xpath40-TreatExpr-CastableExpr">
                     <lhs>CastableExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-CastExpr">CastExpr<!--$idref_lang_part = xpath40- --></nt>  ("castable"  "as"  <nt def="prod-xpath40-CastTarget">CastTarget<!--$idref_lang_part = xpath40- --></nt>  "?"?)?</rhs>
                  </prod>

                  <prod id="doc-xpath40-TreatExpr-SequenceType">
                     <lhs>SequenceType</lhs>
                     <rhs>("empty-sequence"  "("  ")")<br/>|  (<nt def="prod-xpath40-ItemType">ItemType<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-OccurrenceIndicator">OccurrenceIndicator<!--$idref_lang_part = xpath40- --></nt>?)</rhs>
                  </prod>
               </scrap>
               <p>The expression <code nobreak="false">
                     <var>E</var> treat as <var>T</var>
                  </code>
            evaluates the subexpression <var>E</var> to produce a value <var>V</var>,
               and then checks whether <var>V</var> matches
            the <termref def="dt-sequence-type"/>
                  <var>T</var>. If it matches,
            the result of the expression is <var>V</var>; otherwise, the expression
            fails with a type error <errorref class="DY" code="0050"/>.</p>
               <p>The value <var>V</var> must be an actual instance of the type <var>T</var>.
            No casting or coercion is applied to change the value to make it an instance
            of <var>T</var>. The result of the expression is equivalent to:</p>
               <eg xml:space="preserve">let $V := <var>E</var>
return if ($V instance of <var>T</var>)
       then $V
       else error(#err:XPDY0050)</eg>
               <ulist>
                  <item>
                     <p>Example:</p>
                     <eg role="parse-test" xml:space="preserve">$myaddress treat as element(*, USAddress)</eg>
                     <p>The
<termref def="dt-static-type">static type</termref> of
<code nobreak="false">$myaddress</code> may be <code nobreak="false">element(*, Address)</code>, a
less specific type than <code nobreak="false">element(*, USAddress)</code>. However,
at run-time, the value of <code nobreak="false">$myaddress</code> must match the type
<code nobreak="false">element(*, USAddress)</code> using rules for <termref def="dt-sequencetype-matching">SequenceType
matching</termref>;
otherwise a <termref def="dt-type-error"/> is
raised <errorref class="DY" code="0050"/>.</p>
                  </item>
               </ulist>
               <note>
                  <p>Earlier releases of XPath and XQuery defined a mode of operation,
               sometimes called strict static typing, in which it was required that the static
               type of every expression should conform to the required type of the context
               in which it appeared. In this situation it was often necessary to define
               a more precise static type for an expression by the use of <code nobreak="false">treat as</code>.
               In the absence of this feature, the <code nobreak="false">treat as</code> expression is
               rarely necessary, though it can be useful for documentation, and might in
               some cases (depending on the processor) have performance benefits.
             </p>
                  <p>XPath 4.0 redefines the error raised by a <code nobreak="false">treat as</code> expression
             as a type error rather than a dynamic error, which allows a processor to raise
             the error statically in the case of an expression (such as <code nobreak="false">3 treat as xs:string</code>)
             which can never succeed. However, the error code remains unchanged, for compatibility.</p>
               </note>
            </div3>
         </div2>
         <div2 id="id-pipeline-operator">
            <head>Pipeline operator</head>
            <changes>
               <change issue="1685" PR="1686" date="2025-01-09">
               With the pipeline operator <code nobreak="false">-&gt;</code>, the result of an expression
               can be bound to the context value before evaluating another expression.
            </change>
            </changes>
            <scrap headstyle="show">
               <head/>
               <prod id="doc-xpath40-PipelineExpr">
                  <lhs>PipelineExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-ArrowExpr">ArrowExpr<!--$idref_lang_part = xpath40- --></nt>  ("-&gt;"  <nt def="prod-xpath40-ArrowExpr">ArrowExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
               </prod>

               <prod id="doc-xpath40-PipelineExpr-ArrowExpr">
                  <lhs>ArrowExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-UnaryExpr">UnaryExpr<!--$idref_lang_part = xpath40- --></nt>  (<nt def="prod-xpath40-SequenceArrowTarget">SequenceArrowTarget<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-MappingArrowTarget">MappingArrowTarget<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
               </prod>
            </scrap>
            <p diff="add" at="A">
               <termdef term="pipeline operator" id="dt-pipeline-operator">
            The <term>pipeline operator</term>
                  <code nobreak="false">-&gt;</code> evaluates an expression and
            binds the result to the context value before evaluating another expression.</termdef>
            </p>
            <p>Each operation <code nobreak="false">
                  <var>E1</var> -&gt; <var>E2</var>
               </code> is evaluated as follows: 
            Expression <var>E1</var> is evaluated to a sequence <code nobreak="false">S</code>. 
            <var>S</var> then serves in turn to provide an inner <termref def="dt-fixed-focus"/>
            (with the context value set to <var>S</var>) for an evaluation of <var>E2</var> in the
            <termref def="dt-dynamic-context">dynamic context</termref>.
            Unlike the <specref ref="id-map-operator"/>, the result of <var>E1</var> is bound
            just once and as a whole to the context value.
         </p>
            <p>The following examples illustrate the use of pipeline operators:</p>
            <example>
               <ulist>
                  <item>
                     <p>Tokenizes a string, counts the tokens, creates a concatenated string and returns
                     <code nobreak="false">count=3</code>:</p>
                     <eg role="parse-test" xml:space="preserve">'a b c' -&gt; tokenize(.) -&gt; count(.) -&gt; concat('count=', .)
</eg>
                     <p>An equivalent expression is:
                     <eg role="parse-test" xml:space="preserve">
let $string := 'a b c'
let $tokens := tokenize($string)
let $count := count($tokens)
return concat('count=', $count)
                     </eg>
                     </p>
                  </item>
                  <item>
                     <p>Calculates the sum of powers of <code nobreak="false">2</code> and returns
                     <code nobreak="false">2046</code>.</p>
                     <eg role="parse-test" xml:space="preserve">(1 to 10) ! math:pow(2, .) -&gt; sum(.)</eg>
                     <p>An equivalent expression is:
                     <eg role="parse-test" xml:space="preserve">
let $powers := (
  for $exp in 1 to 10
  return math:pow(2, $exp)
)
return sum($powers)
                     </eg>
                     </p>
                  </item>
                  <item>
                     <p>Doubles the values of a sequence, compares the values pairwise with another
                     sequence, checks if some comparisons were successful, and returns
                     <code nobreak="false">true</code>.</p>
                     <eg role="parse-test" xml:space="preserve">
(1 to 4)
-&gt; for-each(., op('+'))
-&gt; for-each-pair(4 to 7, ., op('&gt;'))
-&gt; some(.)
                  </eg>
                     <p>An equivalent expression is:
                     <eg role="parse-test" xml:space="preserve">
let $data := 1 to 4
let $data := for-each($data, op('+'))
let $data := for-each-pair(4 to 7, $data, op('&gt;'))
return some($data)
                     </eg>
                     </p>
                  </item>
                  <item>
                     <p>Reduces a long sequence to at most 9 elements, with dots appended,
                  and returns a single string.</p>
                     <eg role="parse-test" xml:space="preserve">
$dictionary/word
-&gt; (if (count(.) &lt; 10) then . else (.[1 to 9], '…'))
-&gt; string-join(., '; ')
                  </eg>
                     <p>An equivalent expression is:
                     <eg role="parse-test" xml:space="preserve">
let $words := $dictionary/word
let $chopped := (if (count($words) &lt; 10) then $words else ($words[1 to 9], '…'))
return string-join($chopped, '; ')
                     </eg>
                     </p>
                  </item>
               </ulist>
            </example>
         </div2>
         <div2 id="id-map-operator">
            <head>Simple map operator (<code nobreak="false">!</code>)</head>
            <scrap headstyle="show">
               <prod id="doc-xpath40-SimpleMapExpr">
                  <lhs>SimpleMapExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-PathExpr">PathExpr<!--$idref_lang_part = xpath40- --></nt>  ("!"  <nt def="prod-xpath40-PathExpr">PathExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
               </prod>

               <prod id="doc-xpath40-SimpleMapExpr-PathExpr">
                  <lhs>PathExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-AbsolutePathExpr">AbsolutePathExpr<!--$idref_lang_part = xpath40- --></nt>
                     <br/>|  <nt def="prod-xpath40-RelativePathExpr">RelativePathExpr<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
                  <com>
                     <loc href="#parse-note-leading-lone-slash">xgc: leading-lone-slash</loc>
                  </com>
               </prod>
            </scrap>
            <p>
    A mapping expression <code nobreak="false">
                  <var>S</var>!<var>E</var>
               </code> evaluates the
    expression <var>E</var> once for every item in the sequence
    obtained by evaluating <var>S</var>. The simple mapping operator
    <code nobreak="false">!</code> can be applied to any sequence, regardless of the
    types of its items, and it can deliver a mixed sequence of nodes,
    atomic items, and functions. Unlike the similar <code nobreak="false">/</code>
    operator, it does not sort nodes into document order or eliminate
    duplicates.
  </p>
            <p>Each operation <code nobreak="false">
                  <var>E1</var>!<var>E2</var>
               </code> is evaluated as follows: 
            Expression <var>E1</var> is evaluated to a sequence <code nobreak="false">S</code>. 
            Each item in <var>S</var> then serves in turn to provide an inner focus 
            (the item as the context value, its position in <var>S</var> as the 
            context position, the length of <var>S</var> as the context size) 
            for an evaluation of <var>E2</var> in the <termref def="dt-dynamic-context">dynamic context</termref>. The sequences resulting from all the 
            evaluations of <var>E2</var> are combined as follows: Every evaluation 
            of <var>E2</var> returns a (possibly empty) sequence of items. 
            The final result is the <termref def="dt-sequence-concatenation"/> of these sequences.
            The returned sequence preserves the orderings within and among the subsequences 
            generated by the evaluations of <var>E2</var>.
         </p>
            <p>Simple map operators have functionality similar to <specref ref="id-path-operator"/>.
  The following table summarizes the differences between these two operators</p>
            <table role="medium" width="100%">
               <thead>
                  <tr>
                     <th rowspan="1" colspan="1">Operator</th>
                     <th rowspan="1" colspan="1">Path operator (<code nobreak="false">E1 / E2</code>)</th>
                     <th rowspan="1" colspan="1">Simple map operator (<code nobreak="false">E1 ! E2</code>)</th>
                  </tr>
               </thead>
               <tbody>
                  <tr>
                     <th rowspan="1" colspan="1">E1</th>
                     <td rowspan="1" colspan="1">Any sequence of nodes</td>
                     <td rowspan="1" colspan="1">Any sequence of items</td>
                  </tr>
                  <tr>
                     <th rowspan="1" colspan="1">E2</th>
                     <td rowspan="1" colspan="1">Either a sequence of nodes or a sequence of non-node items</td>
                     <td rowspan="1" colspan="1">A sequence of items</td>
                  </tr>
                  <tr>
                     <th rowspan="1" colspan="1">Additional processing</th>
                     <td rowspan="1" colspan="1">Duplicate elimination and document ordering</td>
                     <td rowspan="1" colspan="1">Simple <termref def="dt-sequence-concatenation"/>
                     </td>
                  </tr>
               </tbody>
            </table>
            <p>The following examples illustrate the use of simple map operators combined with path expressions.</p>
            <example>
               <ulist>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">child::div1 / child::para / string() ! concat("id-", .)</code>
                     </p>
                     <p>Selects the <code nobreak="false">para</code> element children of the <code nobreak="false">div1</code> element children of the context node; that is, the <code nobreak="false">para</code> element grandchildren of the context node that have <code nobreak="false">div1</code> parents. It then outputs the strings obtained by prepending <code nobreak="false">"id-"</code> to each of the string values of these grandchildren.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">$emp ! (@first, @middle, @last)</code>
                     </p>
                     <p>Returns the values of the attributes <code nobreak="false">first</code>, <code nobreak="false">middle</code>, and <code nobreak="false">last</code> for each element in <code nobreak="false">$emp</code>, in the order given. (The <code nobreak="false">/</code> operator, if used here, would return the attributes in an unpredictable order.)</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">$docs ! ( //employee)</code>
                     </p>
                     <p>Returns all the <code nobreak="false">employee</code> elements within all the documents identified by the variable <code nobreak="false">$docs</code>, in document order within each document, but retaining the order of documents.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">avg( //employee / salary ! translate(., '$', '') ! number(.))</code>
                     </p>
                     <p>Returns the average salary of the employees, having converted the salary to a number by removing any <code nobreak="false">$</code> sign and then converting to a number. (The second occurrence of <code nobreak="false">!</code> could not be written as <code nobreak="false">/</code> because the left-hand operand of <code nobreak="false">/</code> cannot be an atomic item.)</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">string-join((1 to $n) ! "*")</code>
                     </p>
                     <p>Returns a string containing <code nobreak="false">$n</code> asterisks.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">$values ! (.*.) =&gt; sum()</code>
                     </p>
                     <p>Returns the sum of the squares of a sequence of numbers.</p>
                  </item>
                  <item>
                     <p>
                        <code role="parse-test" nobreak="false">string-join(ancestor::* ! name(), '/')</code>
                     </p>
                     <p>Returns the names of ancestor elements, joined by <code nobreak="false">/</code> characters, i.e., the path to the parent of the context.</p>
                  </item>
               </ulist>
            </example>
         </div2>
         <div2 id="id-arrow-operator">
            <head>Arrow Expressions</head>
            <changes>
               <change issue="1716 1829" PR="1763 1830" date="2025-02-25">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.</change>
            </changes>
            <p>Arrow expressions apply a function (or more generally, a sequence of functions) to a value, using the value of the
         left-hand expression as the first argument to the function.</p>
            <scrap headstyle="show">
               <prod id="doc-xpath40-ArrowExpr">
                  <lhs>ArrowExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-UnaryExpr">UnaryExpr<!--$idref_lang_part = xpath40- --></nt>  (<nt def="prod-xpath40-SequenceArrowTarget">SequenceArrowTarget<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-MappingArrowTarget">MappingArrowTarget<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
               </prod>

               <prod id="doc-xpath40-ArrowExpr-UnaryExpr">
                  <lhs>UnaryExpr</lhs>
                  <rhs>("-"  |  "+")*  <nt def="prod-xpath40-ValueExpr">ValueExpr<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-ArrowExpr-SequenceArrowTarget">
                  <lhs>SequenceArrowTarget</lhs>
                  <rhs>"=&gt;"  <nt def="prod-xpath40-ArrowTarget">ArrowTarget<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-ArrowExpr-ArrowTarget">
                  <lhs>ArrowTarget</lhs>
                  <rhs>
                     <nt def="prod-xpath40-FunctionCall">FunctionCall<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-RestrictedDynamicCall">RestrictedDynamicCall<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-ArrowExpr-FunctionCall">
                  <lhs>FunctionCall</lhs>
                  <rhs>
                     <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                     <nt def="prod-xpath40-ArgumentList">ArgumentList<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
                  <com>
                     <loc href="#parse-note-reserved-function-names">xgc: reserved-function-names</loc>
                  </com>
                  <com>
                     <loc href="#parse-note-parens">gn: parens</loc>
                  </com>
               </prod>

               <prod id="doc-xpath40-ArrowExpr-RestrictedDynamicCall">
                  <lhs>RestrictedDynamicCall</lhs>
                  <rhs>(<nt def="prod-xpath40-VarRef">VarRef<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ParenthesizedExpr">ParenthesizedExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-FunctionItemExpr">FunctionItemExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-MapConstructor">MapConstructor<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ArrayConstructor">ArrayConstructor<!--$idref_lang_part = xpath40- --></nt>)  <nt def="prod-xpath40-PositionalArgumentList">PositionalArgumentList<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-ArrowExpr-VarRef">
                  <lhs>VarRef</lhs>
                  <rhs>"$"  <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-ArrowExpr-ParenthesizedExpr">
                  <lhs>ParenthesizedExpr</lhs>
                  <rhs>"("  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>?  ")"</rhs>
               </prod>

               <prod id="doc-xpath40-ArrowExpr-FunctionItemExpr">
                  <lhs>FunctionItemExpr</lhs>
                  <rhs>
                     <nt def="prod-xpath40-NamedFunctionRef">NamedFunctionRef<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-InlineFunctionExpr">InlineFunctionExpr<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-ArrowExpr-NamedFunctionRef">
                  <lhs>NamedFunctionRef</lhs>
                  <rhs>
                     <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>  "#"  <nt def="prod-xpath40-IntegerLiteral">IntegerLiteral<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
                  <com>
                     <loc href="#parse-note-reserved-function-names">xgc: reserved-function-names</loc>
                  </com>
               </prod>

               <prod id="doc-xpath40-ArrowExpr-InlineFunctionExpr">
                  <lhs>InlineFunctionExpr</lhs>
                  <rhs>("function"  |  "fn")  <nt def="prod-xpath40-FunctionSignature">FunctionSignature<!--$idref_lang_part = xpath40- --></nt>?  <nt def="prod-xpath40-FunctionBody">FunctionBody<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-ArrowExpr-MapConstructor">
                  <lhs>MapConstructor</lhs>
                  <rhs>"map"?  "{"  (<nt def="prod-xpath40-MapConstructorEntry">MapConstructorEntry<!--$idref_lang_part = xpath40- --></nt> ** ",")  "}"</rhs>
               </prod>

               <prod id="doc-xpath40-ArrowExpr-ArrayConstructor">
                  <lhs>ArrayConstructor</lhs>
                  <rhs>
                     <nt def="prod-xpath40-SquareArrayConstructor">SquareArrayConstructor<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-CurlyArrayConstructor">CurlyArrayConstructor<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>

               <prod id="doc-xpath40-ArrowExpr-PositionalArgumentList">
                  <lhs>PositionalArgumentList</lhs>
                  <rhs>"("  <nt def="prod-xpath40-PositionalArguments">PositionalArguments<!--$idref_lang_part = xpath40- --></nt>?  ")"</rhs>
               </prod>

               <prod id="doc-xpath40-ArrowExpr-PositionalArguments">
                  <lhs>PositionalArguments</lhs>
                  <rhs>(<nt def="prod-xpath40-Argument">Argument<!--$idref_lang_part = xpath40- --></nt> ++ ",")</rhs>
               </prod>

               <prod id="doc-xpath40-ArrowExpr-MappingArrowTarget">
                  <lhs>MappingArrowTarget</lhs>
                  <rhs>"=!&gt;"  <nt def="prod-xpath40-ArrowTarget">ArrowTarget<!--$idref_lang_part = xpath40- --></nt>
                  </rhs>
               </prod>
            </scrap>
            <p>The arrow syntax is particularly helpful when applying multiple
            functions to a value in turn. For example, the following
            expression invites syntax errors due to misplaced parentheses:
         </p>
            <eg role="parsetest" xml:space="preserve">tokenize((normalize-unicode(upper-case($string))),"\s+")</eg>
            <p>In the following reformulation, it is easier to see that the parentheses are balanced:</p>
            <eg role="parse-test" xml:space="preserve">$string =&gt; upper-case() =&gt; normalize-unicode() =&gt; tokenize("\s+")</eg>
            <p diff="add" at="A">When the operator is written as <code nobreak="false">=!&gt;</code>, the function
            is applied to each item in the sequence in turn. 
            Assuming that <code nobreak="false">$string</code> is a single string, the above example could
            equally be written:</p>
            <eg role="parse-test" xml:space="preserve">$string =!&gt; upper-case() =!&gt; normalize-unicode() =!&gt; tokenize("\s+")</eg>
            <p diff="add" at="A">The difference between the two operators is seen when the left-hand
            operand evaluates to a sequence:</p>
            <eg role="parse-test" xml:space="preserve">(1, 2, 3) =&gt; avg()</eg>
            <p diff="add" at="2023-07-24">returns a value of only one item, <code nobreak="false">2</code>, the average of all three items. </p>
            <p>This example could also be written as using the <termref def="dt-pipeline-operator"/> as:</p>
            <eg xml:space="preserve">(1, 2, 3) -&gt; avg(.)</eg>
            <p>By contrast, an expression using the <termref def="dt-mapping-arrow-operator"/>:</p>
            <eg role="parse-test" xml:space="preserve">(1, 2, 3) =!&gt; avg()</eg>
            <p diff="add" at="2023-07-24">would return the original sequence of three items, <code nobreak="false">(1, 2, 3)</code>, 
            each item being the average of itself.</p>
            <p>There are two significant differences between the <termref def="dt-pipeline-operator"/>
               <code nobreak="false">-&gt;</code>
            and the <termref def="dt-sequence-arrow-operator"/>
               <code nobreak="false">=&gt;</code>:</p>
            <ulist>
               <item>
                  <p>The <code nobreak="false">-&gt;</code> operator takes an arbitrary expression as its right-hand operand,
            whereas the <code nobreak="false">=&gt;</code> operator requires the right-hand operand to be a function call.</p>
               </item>
               <item>
                  <p>When the right hand operand is a function call, the first argument
            is omitted in the case of the <code nobreak="false">=&gt;</code> operator, but is included explicitly
            (as a context value expression, <code nobreak="false">.</code>) in the case of the <code nobreak="false">-&gt;</code> operator.</p>
               </item>
            </ulist>
            <p>The following example:</p>
            <eg role="parse-test" xml:space="preserve">"The cat sat on the mat"
=&gt; tokenize()
=!&gt; concat(".")
=!&gt; upper-case()
=&gt; string-join(" ")</eg>
            <p>returns <code nobreak="false">"THE. CAT. SAT. ON. THE. MAT."</code>. The first arrow
            could be written either as <code nobreak="false">=&gt;</code> or <code nobreak="false">=!&gt;</code> because the operand is a 
            <termref def="dt-singleton"/>; the next two

            arrows have to be <code nobreak="false">=!&gt;</code> because the function is applied to each item in the tokenized
            sequence individually; the final arrow must be <code nobreak="false">=&gt;</code> because the <code nobreak="false">string-join</code>
            function applies to the sequence as a whole.</p>
            <note>
               <p>It may be useful to think of this as a map/reduce pipeline. The functions
            introduced by <code nobreak="false">=!&gt;</code> are mapping operations; the function introduced by <code nobreak="false">=&gt;</code>
            is a reduce operation.</p>
            </note>
            <p>The following example introduces an inline function to the pipeline:</p>
            <eg role="parse-test" diff="add" at="A" xml:space="preserve">(1 to 5) =!&gt; xs:double() =!&gt; math:sqrt() =!&gt; fn($a) { $a + 1 }() =&gt; sum()</eg>
            <p>This is equivalent to <code nobreak="false">sum((1 to 5) ! (math:sqrt(xs:double(.)) + 1))</code>.</p>
            <p>The same effect can be achieved using a <termref def="dt-focus-function"/>:</p>
            <eg role="parse-test" xml:space="preserve">(1 to 5) =!&gt; xs:double() =!&gt; math:sqrt() =!&gt; fn { . + 1 }() =&gt; sum()</eg>
            <p>It could also be expressed using the mapping operator <code nobreak="false">!</code>:</p>
            <eg role="parse-test" xml:space="preserve">(1 to 5) ! xs:double(.) ! math:sqrt(.) ! (. + 1) =&gt; sum()</eg>
            <note diff="add" at="A">
               <p>The <code nobreak="false">ArgumentList</code> may include <code nobreak="false">PlaceHolders</code>,
            though this is not especially useful. For example, the expression <code nobreak="false">"$" =&gt; concat(?)</code> is equivalent
            to <code nobreak="false">concat("$", ?)</code>: its value is a function that prepends a supplied string with
            a <code nobreak="false">$</code> symbol.</p>
            </note>
            <note diff="add" at="A">
               <p>The <code nobreak="false">ArgumentList</code> may include keyword arguments if the
            function is identified statically (that is, by name). For example,
            the following is valid: <code nobreak="false">$xml =&gt; xml-to-json(indent := true()) =&gt; parse-json(escape := false())</code>.</p>
            </note>
            <p diff="add" at="A">The sequence arrow operator thus applies the supplied function to 
            the left-hand operand as a whole, while the mapping arrow operator applies the function to
            each item in the value of the left-hand operand individually. In the case where the result
            of the left-hand operand is a single item, the two operators have the same effect.</p>
            <note>
               <p>The mapping arrow symbol <code nobreak="false">=!&gt;</code> is intended to suggest a combination of
            function application (<code nobreak="false">=&gt;</code>) and sequence mapping
            (<code nobreak="false">!</code>) combined in a single operation.</p>
               <p>Similarly, the method call operator <code nobreak="false">=?&gt;</code> is intended to suggest a combination
               of function application (<code nobreak="false">=&gt;</code>) and map lookup (<code nobreak="false">?</code>) in a single
            operation.</p>
            </note>
            <p>The construct on the right-hand side of the arrow operator (<code nobreak="false">=&gt;</code>) can
         either be a static function call, or a restricted form of dynamic function call. The
         restrictions are there to ensure that the two forms can be distinguished by the parser
         with limited lookahead. For a dynamic call, the function item(s) to be called can be 
         expressed as a variable reference, an inline function expression, a named function reference, 
         a map constructor, or an array constructor. Any other expression used to return the required function
         item must be enclosed in parentheses.</p>
            <p>Because the semantics of the arrow operator (<code nobreak="false">=&gt;</code>) are defined in terms of
         static and dynamic functions calls, it is possible for the right-hand side to deliver
         a sequence of functions; the result of the arrow expression is the sequence-concatenation
         of the results of the function calls. For example,</p>
            <eg xml:space="preserve">"London" =&gt; (upper-case#1, lower-case#1, string-length#1)</eg>
            <p>returns the sequence <code nobreak="false">("LONDON", "london", 6)</code>.</p>
            <div3 id="id-sequence-arrow-expression">
               <head>Sequence Arrow Expressions</head>
               <p diff="add" at="2023-04-18">
                  <termdef term="sequence arrow operator" id="dt-sequence-arrow-operator">
               The <term>sequence arrow operator</term>
                     <code nobreak="false">=&gt;</code> applies a function to a
               supplied sequence.</termdef> It is defined as follows:</p>
               <ulist>
                  <item>
                     <p>If the arrow is followed by a static <nt def="doc-xpath40-FunctionCall">FunctionCall<!--$spec = xpath40--></nt>:</p>
                     <p>Given a  <nt def="doc-xpath40-UnaryExpr">UnaryExpr<!--$spec = xpath40--></nt>
                        <var>U</var> and a <nt def="doc-xpath40-FunctionCall">FunctionCall<!--$spec = xpath40--></nt>
                        <code nobreak="false">
                           <var>F</var>(<var>A</var>, <var>B</var>, <var>C</var>...)</code>, 
                  the expression <code nobreak="false">
                           <var>U</var> =&gt; <var>F</var>(<var>A</var>, <var>B</var>, <var>C</var>...)</code> 
                  is equivalent to the expression 
                  <code nobreak="false">
                           <var>F</var>(<var>U</var>, <var>A</var>, <var>B</var>, <var>C</var>...)</code>.</p>
                  </item>
                  <item>
                     <p>If the arrow is followed by a <nt def="prod-xpath40-RestrictedDynamicCall">RestrictedDynamicCall<!--$spec = xpath40--></nt>:</p>
                     <p>Given a  <nt def="doc-xpath40-UnaryExpr">UnaryExpr<!--$spec = xpath40--></nt>
                        <var>U</var>, and a <nt def="prod-xpath40-RestrictedDynamicCall">RestrictedDynamicCall<!--$spec = xpath40--></nt>
                        <code nobreak="false">
                           <var>E</var>(<var>A</var>, <var>B</var>, <var>C</var>...)</code>, the expression 
                  <code nobreak="false">
                           <var>U</var> =&gt; <var>E</var>(<var>A</var>, <var>B</var>, <var>C</var>...)</code> is equivalent to the
                  dynamic function call <code nobreak="false">
                           <var>E</var>(<var>U</var>, <var>A</var>, <var>B</var>, <var>C</var>...)</code>.</p>
                  </item>
               </ulist>
               <!--<note><p>Although the syntax of an arrow expression makes use of the grammatical productions
            <nt def="FunctionCall">FunctionCall</nt> and <nt def="DynamicFunctionCall">DynamicFunctionCall</nt>,
            these are not evaluated in the same way as a function call that appears as a 
            free-standing expression.</p></note>-->
            </div3>
            <div3 id="id-mapping-arrow-expression">
               <head>Mapping Arrow Expressions</head>
               <changes>
                  <change>
               The arrow operator <code nobreak="false">=&gt;</code> is now complemented by a “mapping arrow” operator <code nobreak="false">=!&gt;</code>
               which applies the supplied function to each item in the input sequence independently.
            </change>
               </changes>
               <p>
                  <termdef term="mapping arrow operator" id="dt-mapping-arrow-operator">
            The <term>mapping arrow operator</term>
                     <code nobreak="false">=!&gt;</code> applies a function to each
            item in a sequence.</termdef> It is defined as follows:</p>
               <ulist>
                  <item>
                     <p>If the arrow is followed by a static <nt def="doc-xpath40-FunctionCall">FunctionCall<!--$spec = xpath40--></nt>:</p>
                     <p>Given a <nt def="doc-xpath40-UnaryExpr">UnaryExpr<!--$spec = xpath40--></nt>
                        <var>U</var> and a <nt def="doc-xpath40-FunctionCall">FunctionCall<!--$spec = xpath40--></nt>
                        <code nobreak="false">
                           <var>F</var>(<var>A</var>, <var>B</var>, <var>C</var>...)</code>, 
                  the expression <code nobreak="false">
                           <var>U</var> =!&gt; <var>F</var>(<var>A</var>, <var>B</var>, <var>C</var>...)</code> 
                  is equivalent to the expression 
                  <code nobreak="false">for $u in <var>U</var> return 
                     <var>F</var>(<var>$u</var>, <var>A</var>, <var>B</var>, <var>C</var>...)</code>.</p>
                  </item>
                  <item>
                     <p>If the arrow is followed by a <nt def="prod-xpath40-RestrictedDynamicCall">RestrictedDynamicCall<!--$spec = xpath40--></nt>:</p>
                     <p>Given a  <nt def="doc-xpath40-UnaryExpr">UnaryExpr<!--$spec = xpath40--></nt>
                        <var>U</var>, and a <nt def="prod-xpath40-RestrictedDynamicCall">RestrictedDynamicCall<!--$spec = xpath40--></nt>
                        <code nobreak="false">
                           <var>E</var>(<var>A</var>, <var>B</var>, <var>C</var>...)</code>, the expression 
               <code nobreak="false">
                           <var>U</var> =&gt; <var>E</var>(<var>A</var>, <var>B</var>, <var>C</var>...)</code> is equivalent to the
               expression <code nobreak="false">for $u in U return <var>E</var>(<var>$u</var>, <var>A</var>, <var>B</var>, <var>C</var>...)</code>.</p>
                  </item>
               </ulist>
            </div3>
         </div2>
      </div1>
      <div1 id="id-conformance">
         <head>Conformance</head>
         <changes>
            <change issue="205" PR="326" date="2023-02-01">
           Support for higher-order functions is now a mandatory feature (in 3.1 it was optional).
        </change>
            <change issue="1343" PR="1344" date="2024-09-03">
          The static typing feature has been dropped. 
        </change>
         </changes>
         <p>This section defines the conformance criteria for an XPath 4.0 processor. In this section, the
        following terms are used to indicate the requirement levels defined in <bibref ref="RFC2119"/>. <termdef id="must" term="must">
               <term>MUST</term> means that the item is an absolute
            requirement of the specification.</termdef>
            <termdef id="mustnot" term="must not">
               <term>MUST NOT</term> means that the item is an
            absolute prohibition of the specification.</termdef>
            <termdef id="may" term="may">
               <term>MAY</term> means that an item is truly
            optional.</termdef>
         </p>
         <p role="xpath">XPath is intended primarily as a component that can be used by
      other specifications. Therefore, XPath relies on specifications that
      use it (such as <bibref ref="XPTR"/> and <bibref ref="xslt-40"/>) to
      specify conformance criteria for XPath in their respective
      environments. Specifications that set conformance criteria for their
      use of XPath <termref def="mustnot">MUST NOT</termref> change the
      syntactic or semantic definitions of XPath as given in this
      specification, except by subsetting and/or compatible extensions.</p>
         <p role="xpath">If a language is described as an extension of XPath, 
      then every expression that conforms to the XPath grammar <termref def="must">MUST</termref> 
          behave as described in this specification.
      </p>
      </div1>
   </body>
   <back id="id-appendices">
      <div1 id="nt-bnf">
         <head>XPath 4.0 Grammar</head>
         <div2 id="id-grammar">
            <head>EBNF</head>
            <changes>
               <change issue="1366" PR="1498">The EBNF operators <code nobreak="false">++</code> and <code nobreak="false">**</code>
      have been introduced, for more concise representation of sequences using a character
      such as <code nobreak="false">","</code> as a separator. The notation is borrowed from Invisible XML.</change>
            </changes>
            <p>The grammar of XPath 4.0 uses the same simple Extended Backus-Naur Form (EBNF) notation as
        <bibref ref="XML"/> with the following differences.</p>
            <ulist>
               <item>
                  <p>The notation <code nobreak="false">XYZ ** ","</code> indicates a sequence of zero or more occurrences of
        <code nobreak="false">XYZ</code>, with a single comma between adjacent occurrences.</p>
               </item>
               <item>
                  <p>The notation <code nobreak="false">XYZ ++ ","</code> indicates a sequence of one or more occurrences of
        <code nobreak="false">XYZ</code>, with a single comma between adjacent occurrences.</p>
               </item>
               <item>
                  <p>All named symbols have a name that begins with an uppercase letter.</p>
               </item>
               <item>
                  <p>It adds a notation for referring to productions in external specifications.</p>
               </item>
               <item>
                  <p>Comments or extra-grammatical constraints on grammar productions are between '/*' and
          '*/' symbols.</p>
                  <ulist>
                     <item>
                        <p>A 'xgc:' prefix is an extra-grammatical constraint, the details of which are
              explained in <specref ref="extra-grammatical-constraints"/>
                        </p>
                     </item>
                     <item>
                        <p>A 'ws:' prefix explains the whitespace rules for the production, the details of which
              are explained in <specref ref="whitespace-rules"/>
                        </p>
                     </item>
                     <item>
                        <p>A 'gn:' prefix means a 'Grammar Note', and is meant as a clarification for parsing
              rules, and is explained in <specref ref="notes-on-parsing"/>. These notes are not
              normative.</p>
                     </item>
                  </ulist>
               </item>
            </ulist>
            <p>The terminal symbols for this grammar include the quoted strings used in the production rules
      below, and the terminal symbols defined in section <specref ref="terminal-symbols"/>.
    <phrase diff="add" at="2023-05-22">The grammar is a little unusual in that parsing and tokenization
    are somewhat intertwined: for more details see <specref ref="lexical-structure"/>.</phrase>
            </p>
            <p>The EBNF notation is described in more detail in <specref ref="EBNFNotation"/>.</p>
            <scrap id="BNF-Grammar"
                   role="non-terminal-structure-expand"
                   headstyle="show">
               <head/>
               <prodgroup>
                  <prod id="prod-xpath40-AbbreviatedStep">
                     <lhs>AbbreviatedStep</lhs>
                     <rhs>".."  |  ("@"  <nt def="doc-xpath40-NodeTest">NodeTest<!--$idref_lang_part = xpath40- --></nt>)  |  <nt def="prod-xpath40-SimpleNodeTest">SimpleNodeTest<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-AbsolutePathExpr">
                     <lhs>AbsolutePathExpr</lhs>
                     <rhs>("/"  <nt def="prod-xpath40-RelativePathExpr">RelativePathExpr<!--$idref_lang_part = xpath40- --></nt>?)  |  ("//"  <nt def="prod-xpath40-RelativePathExpr">RelativePathExpr<!--$idref_lang_part = xpath40- --></nt>)</rhs>
                  </prod>

                  <prod id="prod-xpath40-AdditiveExpr">
                     <lhs>AdditiveExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-MultiplicativeExpr">MultiplicativeExpr<!--$idref_lang_part = xpath40- --></nt>  (("+"  |  "-")  <nt def="prod-xpath40-MultiplicativeExpr">MultiplicativeExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
                  </prod>

                  <prod id="prod-xpath40-AndExpr">
                     <lhs>AndExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-ComparisonExpr">ComparisonExpr<!--$idref_lang_part = xpath40- --></nt>  ("and"  <nt def="prod-xpath40-ComparisonExpr">ComparisonExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
                  </prod>

                  <prod id="prod-xpath40-AnyArrayType">
                     <lhs>AnyArrayType</lhs>
                     <rhs>"array"  "("  "*"  ")"</rhs>
                  </prod>

                  <prod id="prod-xpath40-AnyFunctionType">
                     <lhs>AnyFunctionType</lhs>
                     <rhs>("function"  |  "fn")  "("  "*"  ")"</rhs>
                  </prod>

                  <prod id="prod-xpath40-AnyItemType">
                     <lhs>AnyItemType</lhs>
                     <rhs>"item"  "("  ")"</rhs>
                  </prod>

                  <prod id="prod-xpath40-AnyMapType">
                     <lhs>AnyMapType</lhs>
                     <rhs>"map"  "("  "*"  ")"</rhs>
                  </prod>

                  <prod id="prod-xpath40-AnyXNodeType">
                     <lhs>AnyXNodeType</lhs>
                     <rhs>"node"  "("  ")"</rhs>
                  </prod>

                  <prod id="prod-xpath40-Argument">
                     <lhs>Argument</lhs>
                     <rhs>
                        <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ArgumentPlaceholder">ArgumentPlaceholder<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-ArgumentList">
                     <lhs>ArgumentList</lhs>
                     <rhs>"("  ((<nt def="prod-xpath40-PositionalArguments">PositionalArguments<!--$idref_lang_part = xpath40- --></nt>  (","  <nt def="prod-xpath40-KeywordArguments">KeywordArguments<!--$idref_lang_part = xpath40- --></nt>)?)  |  <nt def="prod-xpath40-KeywordArguments">KeywordArguments<!--$idref_lang_part = xpath40- --></nt>)?  ")"</rhs>
                  </prod>

                  <prod id="prod-xpath40-ArgumentPlaceholder">
                     <lhs>ArgumentPlaceholder</lhs>
                     <rhs>"?"</rhs>
                  </prod>

                  <prod id="prod-xpath40-ArrayConstructor">
                     <lhs>ArrayConstructor</lhs>
                     <rhs>
                        <nt def="prod-xpath40-SquareArrayConstructor">SquareArrayConstructor<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-CurlyArrayConstructor">CurlyArrayConstructor<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-ArrayType">
                     <lhs>ArrayType</lhs>
                     <rhs>
                        <nt def="prod-xpath40-AnyArrayType">AnyArrayType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-TypedArrayType">TypedArrayType<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-ArrowExpr">
                     <lhs>ArrowExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-UnaryExpr">UnaryExpr<!--$idref_lang_part = xpath40- --></nt>  (<nt def="prod-xpath40-SequenceArrowTarget">SequenceArrowTarget<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-MappingArrowTarget">MappingArrowTarget<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
                  </prod>

                  <prod id="prod-xpath40-ArrowTarget">
                     <lhs>ArrowTarget</lhs>
                     <rhs>
                        <nt def="prod-xpath40-FunctionCall">FunctionCall<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-RestrictedDynamicCall">RestrictedDynamicCall<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-AttributeName">
                     <lhs>AttributeName</lhs>
                     <rhs>
                        <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-AttributeNodeType">
                     <lhs>AttributeNodeType</lhs>
                     <rhs>"attribute"  "("  (<nt def="prod-xpath40-NameTestUnion">NameTestUnion<!--$idref_lang_part = xpath40- --></nt>  (","  <nt def="prod-xpath40-TypeName">TypeName<!--$idref_lang_part = xpath40- --></nt>)?)?  ")"</rhs>
                  </prod>

                  <prod id="prod-xpath40-Axis">
                     <lhs>Axis</lhs>
                     <rhs>("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")  "::"</rhs>
                  </prod>

                  <prod id="prod-xpath40-AxisStep">
                     <lhs>AxisStep</lhs>
                     <rhs>(<nt def="doc-xpath40-AbbreviatedStep">AbbreviatedStep<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-FullStep">FullStep<!--$idref_lang_part = xpath40- --></nt>)  <nt def="prod-xpath40-Predicate">Predicate<!--$idref_lang_part = xpath40- --></nt>*</rhs>
                  </prod>

                  <prod id="prod-xpath40-BracedAction">
                     <lhs>BracedAction</lhs>
                     <rhs>
                        <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-CastableExpr">
                     <lhs>CastableExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-CastExpr">CastExpr<!--$idref_lang_part = xpath40- --></nt>  ("castable"  "as"  <nt def="prod-xpath40-CastTarget">CastTarget<!--$idref_lang_part = xpath40- --></nt>  "?"?)?</rhs>
                  </prod>

                  <prod id="prod-xpath40-CastExpr">
                     <lhs>CastExpr</lhs>
                     <rhs>
                        <nt def="doc-xpath40-PipelineExpr">PipelineExpr<!--$idref_lang_part = xpath40- --></nt>  ("cast"  "as"  <nt def="prod-xpath40-CastTarget">CastTarget<!--$idref_lang_part = xpath40- --></nt>  "?"?)?</rhs>
                  </prod>

                  <prod id="prod-xpath40-CastTarget">
                     <lhs>CastTarget</lhs>
                     <rhs>
                        <nt def="prod-xpath40-TypeName">TypeName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ChoiceItemType">ChoiceItemType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-EnumerationType">EnumerationType<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-ChoiceItemType">
                     <lhs>ChoiceItemType</lhs>
                     <rhs>"("  (<nt def="prod-xpath40-ItemType">ItemType<!--$idref_lang_part = xpath40- --></nt> ++ "|")  ")"</rhs>
                  </prod>

                  <prod id="prod-xpath40-CommentNodeType">
                     <lhs>CommentNodeType</lhs>
                     <rhs>"comment"  "("  ")"</rhs>
                  </prod>

                  <prod id="prod-xpath40-ComparisonExpr">
                     <lhs>ComparisonExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-OtherwiseExpr">OtherwiseExpr<!--$idref_lang_part = xpath40- --></nt>  ((<nt def="prod-xpath40-ValueComp">ValueComp<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-GeneralComp">GeneralComp<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-NodeComp">NodeComp<!--$idref_lang_part = xpath40- --></nt>)  <nt def="prod-xpath40-OtherwiseExpr">OtherwiseExpr<!--$idref_lang_part = xpath40- --></nt>)?</rhs>
                  </prod>

                  <prod id="prod-xpath40-CompAttrConstructor">
                     <lhs>CompAttrConstructor</lhs>
                     <rhs>"attribute"  <nt def="prod-xpath40-CompNodeName">CompNodeName<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-CompCommentConstructor">
                     <lhs>CompCommentConstructor</lhs>
                     <rhs>"comment"  <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-CompDocConstructor">
                     <lhs>CompDocConstructor</lhs>
                     <rhs>"document"  <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-CompElemConstructor">
                     <lhs>CompElemConstructor</lhs>
                     <rhs>"element"  <nt def="prod-xpath40-CompNodeName">CompNodeName<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-EnclosedContentExpr">EnclosedContentExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-CompNamespaceConstructor">
                     <lhs>CompNamespaceConstructor</lhs>
                     <rhs>"namespace"  <nt def="prod-xpath40-CompNodeNCName">CompNodeNCName<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-CompNodeName">
                     <lhs>CompNodeName</lhs>
                     <rhs>
                        <nt def="prod-xpath40-QNameLiteral">QNameLiteral<!--$idref_lang_part = xpath40- --></nt>  |  ("{"  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>  "}")</rhs>
                  </prod>

                  <prod id="prod-xpath40-CompNodeNCName">
                     <lhs>CompNodeNCName</lhs>
                     <rhs>
                        <nt def="prod-xpath40-MarkedNCName">MarkedNCName<!--$idref_lang_part = xpath40- --></nt>  |  ("{"  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>  "}")</rhs>
                  </prod>

                  <prod id="prod-xpath40-CompPIConstructor">
                     <lhs>CompPIConstructor</lhs>
                     <rhs>"processing-instruction"  <nt def="prod-xpath40-CompNodeNCName">CompNodeNCName<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-CompTextConstructor">
                     <lhs>CompTextConstructor</lhs>
                     <rhs>"text"  <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-ComputedConstructor">
                     <lhs>ComputedConstructor</lhs>
                     <rhs>
                        <nt def="prod-xpath40-CompDocConstructor">CompDocConstructor<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-CompElemConstructor">CompElemConstructor<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-CompAttrConstructor">CompAttrConstructor<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-CompNamespaceConstructor">CompNamespaceConstructor<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-CompTextConstructor">CompTextConstructor<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-CompCommentConstructor">CompCommentConstructor<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-CompPIConstructor">CompPIConstructor<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-Constant">
                     <lhs>Constant</lhs>
                     <rhs>
                        <nt def="doc-xpath40-StringLiteral">StringLiteral<!--$idref_lang_part = xpath40- --></nt>  |  ("-"?  <nt def="prod-xpath40-NumericLiteral">NumericLiteral<!--$idref_lang_part = xpath40- --></nt>)  |  <nt def="prod-xpath40-QNameLiteral">QNameLiteral<!--$idref_lang_part = xpath40- --></nt>  |  ("true"  "("  ")")  |  ("false"  "("  ")")</rhs>
                  </prod>

                  <prod id="prod-xpath40-ContextValueRef">
                     <lhs>ContextValueRef</lhs>
                     <rhs>"."</rhs>
                  </prod>

                  <prod id="prod-xpath40-CurlyArrayConstructor">
                     <lhs>CurlyArrayConstructor</lhs>
                     <rhs>"array"  <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-DefaultElementNamespaceDecl">
                     <lhs>DefaultElementNamespaceDecl</lhs>
                     <rhs>"declare"  "default"  "element"  "namespace"  <nt def="prod-xpath40-URILiteral">URILiteral<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-DocumentNodeType">
                     <lhs>DocumentNodeType</lhs>
                     <rhs>"document-node"  "("  (<nt def="prod-xpath40-ElementNodeType">ElementNodeType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-SchemaElementNodeType">SchemaElementNodeType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-NameTestUnion">NameTestUnion<!--$idref_lang_part = xpath40- --></nt>)?  ")"</rhs>
                  </prod>

                  <prod id="prod-xpath40-DynamicFunctionCall">
                     <lhs>DynamicFunctionCall</lhs>
                     <rhs>
                        <nt def="prod-xpath40-PostfixExpr">PostfixExpr<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-PositionalArgumentList">PositionalArgumentList<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-ElementName">
                     <lhs>ElementName</lhs>
                     <rhs>
                        <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-ElementNodeType">
                     <lhs>ElementNodeType</lhs>
                     <rhs>"element"  "("  (<nt def="prod-xpath40-NameTestUnion">NameTestUnion<!--$idref_lang_part = xpath40- --></nt>  (","  <nt def="prod-xpath40-TypeName">TypeName<!--$idref_lang_part = xpath40- --></nt>  "?"?)?)?  ")"</rhs>
                  </prod>

                  <prod id="prod-xpath40-EnclosedContentExpr">
                     <lhs>EnclosedContentExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-EnclosedExpr">
                     <lhs>EnclosedExpr</lhs>
                     <rhs>"{"  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>?  "}"</rhs>
                  </prod>

                  <prod id="prod-xpath40-EnumerationType">
                     <lhs>EnumerationType</lhs>
                     <rhs>"enum"  "("  (<nt def="doc-xpath40-StringLiteral">StringLiteral<!--$idref_lang_part = xpath40- --></nt> ++ ",")  ")"</rhs>
                  </prod>

                  <prod id="prod-xpath40-EQName">
                     <lhs>EQName</lhs>
                     <rhs>
                        <nt def="prod-xpath40-QName">QName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-Expr">
                     <lhs>Expr</lhs>
                     <rhs>(<nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt> ++ ",")</rhs>
                  </prod>

                  <prod id="prod-xpath40-ExprSingle">
                     <lhs>ExprSingle</lhs>
                     <rhs>
                        <nt def="prod-xpath40-ForExpr">ForExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-LetExpr">LetExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-QuantifiedExpr">QuantifiedExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-IfExpr">IfExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-OrExpr">OrExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-FieldDeclaration">
                     <lhs>FieldDeclaration</lhs>
                     <rhs>
                        <nt def="prod-xpath40-FieldName">FieldName<!--$idref_lang_part = xpath40- --></nt>  "?"?  ("as"  <nt def="prod-xpath40-SequenceType">SequenceType<!--$idref_lang_part = xpath40- --></nt>)?</rhs>
                  </prod>

                  <prod id="prod-xpath40-FieldName">
                     <lhs>FieldName</lhs>
                     <rhs>
                        <nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="doc-xpath40-StringLiteral">StringLiteral<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-FilterExpr">
                     <lhs>FilterExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-PostfixExpr">PostfixExpr<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-Predicate">Predicate<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-FilterExprAM">
                     <lhs>FilterExprAM</lhs>
                     <rhs>
                        <nt def="prod-xpath40-PostfixExpr">PostfixExpr<!--$idref_lang_part = xpath40- --></nt>  "?["  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>  "]"</rhs>
                  </prod>

                  <prod id="prod-xpath40-ForBinding">
                     <lhs>ForBinding</lhs>
                     <rhs>
                        <nt def="prod-xpath40-ForItemBinding">ForItemBinding<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ForMemberBinding">ForMemberBinding<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ForEntryBinding">ForEntryBinding<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-ForClause">
                     <lhs>ForClause</lhs>
                     <rhs>"for"  (<nt def="prod-xpath40-ForBinding">ForBinding<!--$idref_lang_part = xpath40- --></nt> ++ ",")</rhs>
                  </prod>

                  <prod id="prod-xpath40-ForEntryBinding">
                     <lhs>ForEntryBinding</lhs>
                     <rhs>((<nt def="prod-xpath40-ForEntryKeyBinding">ForEntryKeyBinding<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-ForEntryValueBinding">ForEntryValueBinding<!--$idref_lang_part = xpath40- --></nt>?)  |  <nt def="prod-xpath40-ForEntryValueBinding">ForEntryValueBinding<!--$idref_lang_part = xpath40- --></nt>)  <nt def="prod-xpath40-PositionalVar">PositionalVar<!--$idref_lang_part = xpath40- --></nt>?  "in"  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-ForEntryKeyBinding">
                     <lhs>ForEntryKeyBinding</lhs>
                     <rhs>"key"  <nt def="prod-xpath40-VarNameAndType">VarNameAndType<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-ForEntryValueBinding">
                     <lhs>ForEntryValueBinding</lhs>
                     <rhs>"value"  <nt def="prod-xpath40-VarNameAndType">VarNameAndType<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-ForExpr">
                     <lhs>ForExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-ForClause">ForClause<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-ForLetReturn">ForLetReturn<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-ForItemBinding">
                     <lhs>ForItemBinding</lhs>
                     <rhs>
                        <nt def="prod-xpath40-VarNameAndType">VarNameAndType<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-PositionalVar">PositionalVar<!--$idref_lang_part = xpath40- --></nt>?  "in"  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-ForLetReturn">
                     <lhs>ForLetReturn</lhs>
                     <rhs>
                        <nt def="prod-xpath40-ForExpr">ForExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-LetExpr">LetExpr<!--$idref_lang_part = xpath40- --></nt>  |  ("return"  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>)</rhs>
                  </prod>

                  <prod id="prod-xpath40-ForMemberBinding">
                     <lhs>ForMemberBinding</lhs>
                     <rhs>"member"  <nt def="prod-xpath40-VarNameAndType">VarNameAndType<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-PositionalVar">PositionalVar<!--$idref_lang_part = xpath40- --></nt>?  "in"  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-FullStep">
                     <lhs>FullStep</lhs>
                     <rhs>
                        <nt def="prod-xpath40-Axis">Axis<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="doc-xpath40-NodeTest">NodeTest<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-FunctionBody">
                     <lhs>FunctionBody</lhs>
                     <rhs>
                        <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-FunctionCall">
                     <lhs>FunctionCall</lhs>
                     <rhs>
                        <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-ArgumentList">ArgumentList<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                     <com>
                        <loc href="#parse-note-reserved-function-names">xgc: reserved-function-names</loc>
                     </com>
                     <com>
                        <loc href="#parse-note-parens">gn: parens</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-FunctionItemExpr">
                     <lhs>FunctionItemExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-NamedFunctionRef">NamedFunctionRef<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-InlineFunctionExpr">InlineFunctionExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-FunctionSignature">
                     <lhs>FunctionSignature</lhs>
                     <rhs>"("  <nt def="prod-xpath40-ParamList">ParamList<!--$idref_lang_part = xpath40- --></nt>  ")"  <nt def="prod-xpath40-TypeDeclaration">TypeDeclaration<!--$idref_lang_part = xpath40- --></nt>?</rhs>
                  </prod>

                  <prod id="prod-xpath40-FunctionType">
                     <lhs>FunctionType</lhs>
                     <rhs>
                        <nt def="prod-xpath40-AnyFunctionType">AnyFunctionType<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-TypedFunctionType">TypedFunctionType<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-GeneralComp">
                     <lhs>GeneralComp</lhs>
                     <rhs>"="  |  "!="  |  "&lt;"  |  "&lt;="  |  "&gt;"  |  "&gt;="</rhs>
                  </prod>

                  <prod id="prod-xpath40-GNodeType">
                     <lhs>GNodeType</lhs>
                     <rhs>"gnode"  "("  ")"</rhs>
                  </prod>

                  <prod id="prod-xpath40-IfExpr">
                     <lhs>IfExpr</lhs>
                     <rhs>"if"  "("  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>  ")"  (<nt def="prod-xpath40-UnbracedActions">UnbracedActions<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-BracedAction">BracedAction<!--$idref_lang_part = xpath40- --></nt>)</rhs>
                  </prod>

                  <prod id="prod-xpath40-InlineFunctionExpr">
                     <lhs>InlineFunctionExpr</lhs>
                     <rhs>("function"  |  "fn")  <nt def="prod-xpath40-FunctionSignature">FunctionSignature<!--$idref_lang_part = xpath40- --></nt>?  <nt def="prod-xpath40-FunctionBody">FunctionBody<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-InstanceofExpr">
                     <lhs>InstanceofExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-TreatExpr">TreatExpr<!--$idref_lang_part = xpath40- --></nt>  ("instance"  "of"  <nt def="prod-xpath40-SequenceType">SequenceType<!--$idref_lang_part = xpath40- --></nt>)?</rhs>
                  </prod>

                  <prod id="prod-xpath40-IntersectExceptExpr">
                     <lhs>IntersectExceptExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-InstanceofExpr">InstanceofExpr<!--$idref_lang_part = xpath40- --></nt>  (("intersect"  |  "except")  <nt def="prod-xpath40-InstanceofExpr">InstanceofExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
                  </prod>

                  <prod id="prod-xpath40-ItemType">
                     <lhs>ItemType</lhs>
                     <rhs>
                        <nt def="prod-xpath40-RegularItemType">RegularItemType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-FunctionType">FunctionType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-TypeName">TypeName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ChoiceItemType">ChoiceItemType<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-JNodeType">
                     <lhs>JNodeType</lhs>
                     <rhs>"jnode"  "("  (("*"  |  <nt def="prod-xpath40-JRootSelector">JRootSelector<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-Constant">Constant<!--$idref_lang_part = xpath40- --></nt>)  (","  <nt def="prod-xpath40-SequenceType">SequenceType<!--$idref_lang_part = xpath40- --></nt>)?)?  ")"</rhs>
                  </prod>

                  <prod id="prod-xpath40-JRootSelector">
                     <lhs>JRootSelector</lhs>
                     <rhs>"("  ")"</rhs>
                  </prod>

                  <prod id="prod-xpath40-KeySpecifier">
                     <lhs>KeySpecifier</lhs>
                     <rhs>
                        <nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-Literal">Literal<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ContextValueRef">ContextValueRef<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-VarRef">VarRef<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ParenthesizedExpr">ParenthesizedExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-LookupWildcard">LookupWildcard<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-KeywordArgument">
                     <lhs>KeywordArgument</lhs>
                     <rhs>
                        <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>  ":="  <nt def="prod-xpath40-Argument">Argument<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-KeywordArguments">
                     <lhs>KeywordArguments</lhs>
                     <rhs>(<nt def="prod-xpath40-KeywordArgument">KeywordArgument<!--$idref_lang_part = xpath40- --></nt> ++ ",")</rhs>
                  </prod>

                  <prod id="prod-xpath40-LetArrayBinding">
                     <lhs>LetArrayBinding</lhs>
                     <rhs>"$"  "["  (<nt def="prod-xpath40-VarNameAndType">VarNameAndType<!--$idref_lang_part = xpath40- --></nt> ++ ",")  "]"  <nt def="prod-xpath40-TypeDeclaration">TypeDeclaration<!--$idref_lang_part = xpath40- --></nt>?  ":="  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-LetBinding">
                     <lhs>LetBinding</lhs>
                     <rhs>
                        <nt def="prod-xpath40-LetValueBinding">LetValueBinding<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-LetSequenceBinding">LetSequenceBinding<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-LetArrayBinding">LetArrayBinding<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-LetMapBinding">LetMapBinding<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-LetClause">
                     <lhs>LetClause</lhs>
                     <rhs>"let"  (<nt def="prod-xpath40-LetBinding">LetBinding<!--$idref_lang_part = xpath40- --></nt> ++ ",")</rhs>
                  </prod>

                  <prod id="prod-xpath40-LetExpr">
                     <lhs>LetExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-LetClause">LetClause<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-ForLetReturn">ForLetReturn<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-LetMapBinding">
                     <lhs>LetMapBinding</lhs>
                     <rhs>"$"  "{"  (<nt def="prod-xpath40-VarNameAndType">VarNameAndType<!--$idref_lang_part = xpath40- --></nt> ++ ",")  "}"  <nt def="prod-xpath40-TypeDeclaration">TypeDeclaration<!--$idref_lang_part = xpath40- --></nt>?  ":="  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-LetSequenceBinding">
                     <lhs>LetSequenceBinding</lhs>
                     <rhs>"$"  "("  (<nt def="prod-xpath40-VarNameAndType">VarNameAndType<!--$idref_lang_part = xpath40- --></nt> ++ ",")  ")"  <nt def="prod-xpath40-TypeDeclaration">TypeDeclaration<!--$idref_lang_part = xpath40- --></nt>?  ":="  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-LetValueBinding">
                     <lhs>LetValueBinding</lhs>
                     <rhs>
                        <nt def="prod-xpath40-VarNameAndType">VarNameAndType<!--$idref_lang_part = xpath40- --></nt>  ":="  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-Literal">
                     <lhs>Literal</lhs>
                     <rhs>
                        <nt def="prod-xpath40-NumericLiteral">NumericLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="doc-xpath40-StringLiteral">StringLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-QNameLiteral">QNameLiteral<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-Lookup">
                     <lhs>Lookup</lhs>
                     <rhs>"?"  <nt def="prod-xpath40-KeySpecifier">KeySpecifier<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-LookupExpr">
                     <lhs>LookupExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-PostfixExpr">PostfixExpr<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-Lookup">Lookup<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-LookupWildcard">
                     <lhs>LookupWildcard</lhs>
                     <rhs>"*"</rhs>
                  </prod>

                  <prod id="prod-xpath40-MapConstructor">
                     <lhs>MapConstructor</lhs>
                     <rhs>"map"?  "{"  (<nt def="prod-xpath40-MapConstructorEntry">MapConstructorEntry<!--$idref_lang_part = xpath40- --></nt> ** ",")  "}"</rhs>
                  </prod>

                  <prod id="prod-xpath40-MapConstructorEntry">
                     <lhs>MapConstructorEntry</lhs>
                     <rhs>
                        <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>  (":"  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>)?</rhs>
                  </prod>

                  <prod id="prod-xpath40-MappingArrowTarget">
                     <lhs>MappingArrowTarget</lhs>
                     <rhs>"=!&gt;"  <nt def="prod-xpath40-ArrowTarget">ArrowTarget<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-MapType">
                     <lhs>MapType</lhs>
                     <rhs>
                        <nt def="prod-xpath40-AnyMapType">AnyMapType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-TypedMapType">TypedMapType<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-MarkedNCName">
                     <lhs>MarkedNCName</lhs>
                     <rhs>"#"  <nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-MethodCall">
                     <lhs>MethodCall</lhs>
                     <rhs>
                        <nt def="prod-xpath40-PostfixExpr">PostfixExpr<!--$idref_lang_part = xpath40- --></nt>  "=?&gt;"  <nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-PositionalArgumentList">PositionalArgumentList<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-MultiplicativeExpr">
                     <lhs>MultiplicativeExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-UnionExpr">UnionExpr<!--$idref_lang_part = xpath40- --></nt>  (("*"  |  "×"  |  "div"  |  "÷"  |  "idiv"  |  "mod")  <nt def="prod-xpath40-UnionExpr">UnionExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
                  </prod>

                  <prod id="prod-xpath40-NamedFunctionRef">
                     <lhs>NamedFunctionRef</lhs>
                     <rhs>
                        <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>  "#"  <nt def="prod-xpath40-IntegerLiteral">IntegerLiteral<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                     <com>
                        <loc href="#parse-note-reserved-function-names">xgc: reserved-function-names</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-NamespaceDecl">
                     <lhs>NamespaceDecl</lhs>
                     <rhs>"declare"  "namespace"  <nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>  "="  <nt def="prod-xpath40-URILiteral">URILiteral<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-NamespaceNodeType">
                     <lhs>NamespaceNodeType</lhs>
                     <rhs>"namespace-node"  "("  ")"</rhs>
                  </prod>

                  <prod id="prod-xpath40-NameTest">
                     <lhs>NameTest</lhs>
                     <rhs>
                        <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-Wildcard">Wildcard<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-NameTestUnion">
                     <lhs>NameTestUnion</lhs>
                     <rhs>(<nt def="prod-xpath40-NameTest">NameTest<!--$idref_lang_part = xpath40- --></nt> ++ "|")</rhs>
                  </prod>

                  <prod id="prod-xpath40-NodeComp">
                     <lhs>NodeComp</lhs>
                     <rhs>"is"  |  "is-not"  |  <nt def="prod-xpath40-NodePrecedes">NodePrecedes<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-NodeFollows">NodeFollows<!--$idref_lang_part = xpath40- --></nt>  |  "precedes-or-is"  |  "follows-or-is"</rhs>
                  </prod>

                  <prod id="prod-xpath40-NodeConstructor">
                     <lhs>NodeConstructor</lhs>
                     <rhs>
                        <nt def="prod-xpath40-ComputedConstructor">ComputedConstructor<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-NodeFollows">
                     <lhs>NodeFollows</lhs>
                     <rhs>"&gt;&gt;"  |  "follows"</rhs>
                  </prod>

                  <prod id="prod-xpath40-NodePrecedes">
                     <lhs>NodePrecedes</lhs>
                     <rhs>"&lt;&lt;"  |  "precedes"</rhs>
                  </prod>

                  <prod id="prod-xpath40-NodeTest">
                     <lhs>NodeTest</lhs>
                     <rhs>
                        <nt def="prod-xpath40-UnionNodeTest">UnionNodeTest<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-SimpleNodeTest">SimpleNodeTest<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-NumericLiteral">
                     <lhs>NumericLiteral</lhs>
                     <rhs>
                        <nt def="prod-xpath40-IntegerLiteral">IntegerLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-HexIntegerLiteral">HexIntegerLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-BinaryIntegerLiteral">BinaryIntegerLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-DecimalLiteral">DecimalLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-DoubleLiteral">DoubleLiteral<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-OccurrenceIndicator">
                     <lhs>OccurrenceIndicator</lhs>
                     <rhs>"?"  |  "*"  |  "+"</rhs>
                     <com>
                        <loc href="#parse-note-occurrence-indicators">xgc: occurrence-indicators</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-OrExpr">
                     <lhs>OrExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-AndExpr">AndExpr<!--$idref_lang_part = xpath40- --></nt>  ("or"  <nt def="prod-xpath40-AndExpr">AndExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
                  </prod>

                  <prod id="prod-xpath40-OtherwiseExpr">
                     <lhs>OtherwiseExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-StringConcatExpr">StringConcatExpr<!--$idref_lang_part = xpath40- --></nt>  ("otherwise"  <nt def="prod-xpath40-StringConcatExpr">StringConcatExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
                  </prod>

                  <prod id="prod-xpath40-ParamList">
                     <lhs>ParamList</lhs>
                     <rhs>(<nt def="prod-xpath40-VarNameAndType">VarNameAndType<!--$idref_lang_part = xpath40- --></nt> ** ",")</rhs>
                  </prod>

                  <prod id="prod-xpath40-ParenthesizedExpr">
                     <lhs>ParenthesizedExpr</lhs>
                     <rhs>"("  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>?  ")"</rhs>
                  </prod>

                  <prod id="prod-xpath40-PathExpr">
                     <lhs>PathExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-AbsolutePathExpr">AbsolutePathExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-RelativePathExpr">RelativePathExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                     <com>
                        <loc href="#parse-note-leading-lone-slash">xgc: leading-lone-slash</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-PipelineExpr">
                     <lhs>PipelineExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-ArrowExpr">ArrowExpr<!--$idref_lang_part = xpath40- --></nt>  ("-&gt;"  <nt def="prod-xpath40-ArrowExpr">ArrowExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
                  </prod>

                  <prod id="prod-xpath40-PositionalArgumentList">
                     <lhs>PositionalArgumentList</lhs>
                     <rhs>"("  <nt def="prod-xpath40-PositionalArguments">PositionalArguments<!--$idref_lang_part = xpath40- --></nt>?  ")"</rhs>
                  </prod>

                  <prod id="prod-xpath40-PositionalArguments">
                     <lhs>PositionalArguments</lhs>
                     <rhs>(<nt def="prod-xpath40-Argument">Argument<!--$idref_lang_part = xpath40- --></nt> ++ ",")</rhs>
                  </prod>

                  <prod id="prod-xpath40-PositionalVar">
                     <lhs>PositionalVar</lhs>
                     <rhs>"at"  <nt def="prod-xpath40-VarName">VarName<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-PostfixExpr">
                     <lhs>PostfixExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-PrimaryExpr">PrimaryExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-FilterExpr">FilterExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-DynamicFunctionCall">DynamicFunctionCall<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-LookupExpr">LookupExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-MethodCall">MethodCall<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-FilterExprAM">FilterExprAM<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-Predicate">
                     <lhs>Predicate</lhs>
                     <rhs>"["  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>  "]"</rhs>
                  </prod>

                  <prod id="prod-xpath40-PrimaryExpr">
                     <lhs>PrimaryExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-Literal">Literal<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-VarRef">VarRef<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-ParenthesizedExpr">ParenthesizedExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-ContextValueRef">ContextValueRef<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-FunctionCall">FunctionCall<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-NodeConstructor">NodeConstructor<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-FunctionItemExpr">FunctionItemExpr<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-MapConstructor">MapConstructor<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-ArrayConstructor">ArrayConstructor<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-StringTemplate">StringTemplate<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-UnaryLookup">UnaryLookup<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-ProcessingInstructionNodeType">
                     <lhs>ProcessingInstructionNodeType</lhs>
                     <rhs>"processing-instruction"  "("  (<nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="doc-xpath40-StringLiteral">StringLiteral<!--$idref_lang_part = xpath40- --></nt>)?  ")"</rhs>
                  </prod>

                  <prod id="prod-xpath40-QNameLiteral">
                     <lhs>QNameLiteral</lhs>
                     <rhs>"#"  <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-QuantifiedExpr">
                     <lhs>QuantifiedExpr</lhs>
                     <rhs>("some"  |  "every")  (<nt def="prod-xpath40-QuantifierBinding">QuantifierBinding<!--$idref_lang_part = xpath40- --></nt> ++ ",")  "satisfies"  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-QuantifierBinding">
                     <lhs>QuantifierBinding</lhs>
                     <rhs>
                        <nt def="prod-xpath40-VarNameAndType">VarNameAndType<!--$idref_lang_part = xpath40- --></nt>  "in"  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-RangeExpr">
                     <lhs>RangeExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-AdditiveExpr">AdditiveExpr<!--$idref_lang_part = xpath40- --></nt>  ("to"  <nt def="prod-xpath40-AdditiveExpr">AdditiveExpr<!--$idref_lang_part = xpath40- --></nt>)?</rhs>
                  </prod>

                  <prod id="prod-xpath40-RecordType">
                     <lhs>RecordType</lhs>
                     <rhs>"record"  "("  (<nt def="prod-xpath40-FieldDeclaration">FieldDeclaration<!--$idref_lang_part = xpath40- --></nt> ** ",")  ")"</rhs>
                  </prod>

                  <prod id="prod-xpath40-RegularItemType">
                     <lhs>RegularItemType</lhs>
                     <rhs>
                        <nt def="prod-xpath40-AnyItemType">AnyItemType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-XNodeType">XNodeType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-GNodeType">GNodeType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-JNodeType">JNodeType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-MapType">MapType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ArrayType">ArrayType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-RecordType">RecordType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-EnumerationType">EnumerationType<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-RelativePathExpr">
                     <lhs>RelativePathExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-StepExpr">StepExpr<!--$idref_lang_part = xpath40- --></nt>  (("/"  |  "//")  <nt def="prod-xpath40-StepExpr">StepExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
                  </prod>

                  <prod id="prod-xpath40-RestrictedDynamicCall">
                     <lhs>RestrictedDynamicCall</lhs>
                     <rhs>(<nt def="prod-xpath40-VarRef">VarRef<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ParenthesizedExpr">ParenthesizedExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-FunctionItemExpr">FunctionItemExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-MapConstructor">MapConstructor<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-ArrayConstructor">ArrayConstructor<!--$idref_lang_part = xpath40- --></nt>)  <nt def="prod-xpath40-PositionalArgumentList">PositionalArgumentList<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-SchemaAttributeNodeType">
                     <lhs>SchemaAttributeNodeType</lhs>
                     <rhs>"schema-attribute"  "("  <nt def="prod-xpath40-AttributeName">AttributeName<!--$idref_lang_part = xpath40- --></nt>  ")"</rhs>
                  </prod>

                  <prod id="prod-xpath40-SchemaElementNodeType">
                     <lhs>SchemaElementNodeType</lhs>
                     <rhs>"schema-element"  "("  <nt def="prod-xpath40-ElementName">ElementName<!--$idref_lang_part = xpath40- --></nt>  ")"</rhs>
                  </prod>

                  <prod id="prod-xpath40-Selector">
                     <lhs>Selector</lhs>
                     <rhs>
                        <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-Wildcard">Wildcard<!--$idref_lang_part = xpath40- --></nt>  |  ("get"  "("  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>  ")")</rhs>
                  </prod>

                  <prod id="prod-xpath40-SequenceArrowTarget">
                     <lhs>SequenceArrowTarget</lhs>
                     <rhs>"=&gt;"  <nt def="prod-xpath40-ArrowTarget">ArrowTarget<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-SequenceType">
                     <lhs>SequenceType</lhs>
                     <rhs>("empty-sequence"  "("  ")")<br/>|  (<nt def="prod-xpath40-ItemType">ItemType<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-OccurrenceIndicator">OccurrenceIndicator<!--$idref_lang_part = xpath40- --></nt>?)</rhs>
                  </prod>

                  <prod id="prod-xpath40-SimpleMapExpr">
                     <lhs>SimpleMapExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-PathExpr">PathExpr<!--$idref_lang_part = xpath40- --></nt>  ("!"  <nt def="prod-xpath40-PathExpr">PathExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
                  </prod>

                  <prod id="prod-xpath40-SimpleNodeTest">
                     <lhs>SimpleNodeTest</lhs>
                     <rhs>
                        <nt def="prod-xpath40-TypeTest">TypeTest<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-Selector">Selector<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-SquareArrayConstructor">
                     <lhs>SquareArrayConstructor</lhs>
                     <rhs>"["  (<nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt> ** ",")  "]"</rhs>
                  </prod>

                  <prod id="prod-xpath40-StepExpr">
                     <lhs>StepExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-PostfixExpr">PostfixExpr<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-AxisStep">AxisStep<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-StringConcatExpr">
                     <lhs>StringConcatExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-RangeExpr">RangeExpr<!--$idref_lang_part = xpath40- --></nt>  ("||"  <nt def="prod-xpath40-RangeExpr">RangeExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
                  </prod>

                  <prod id="prod-xpath40-StringTemplate">
                     <lhs>StringTemplate</lhs>
                     <rhs>"`"  (<nt def="prod-xpath40-StringTemplateFixedPart">StringTemplateFixedPart<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-StringTemplateVariablePart">StringTemplateVariablePart<!--$idref_lang_part = xpath40- --></nt>)*  "`"</rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-StringTemplateFixedPart">
                     <lhs>StringTemplateFixedPart</lhs>
                     <rhs>((<nt def="prod-xpath40-Char">Char<!--$idref_lang_part = xpath40- --></nt> - ('{' | '}' | '`'))  |  "{{"  |  "}}"  |  "``")+</rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-StringTemplateVariablePart">
                     <lhs>StringTemplateVariablePart</lhs>
                     <rhs>
                        <nt def="prod-xpath40-EnclosedExpr">EnclosedExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-TextNodeType">
                     <lhs>TextNodeType</lhs>
                     <rhs>"text"  "("  ")"</rhs>
                  </prod>

                  <prod id="prod-xpath40-TreatExpr">
                     <lhs>TreatExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-CastableExpr">CastableExpr<!--$idref_lang_part = xpath40- --></nt>  ("treat"  "as"  <nt def="prod-xpath40-SequenceType">SequenceType<!--$idref_lang_part = xpath40- --></nt>)?</rhs>
                  </prod>

                  <prod id="prod-xpath40-TypedArrayType">
                     <lhs>TypedArrayType</lhs>
                     <rhs>"array"  "("  <nt def="prod-xpath40-SequenceType">SequenceType<!--$idref_lang_part = xpath40- --></nt>  ")"</rhs>
                  </prod>

                  <prod id="prod-xpath40-TypeDeclaration">
                     <lhs>TypeDeclaration</lhs>
                     <rhs>"as"  <nt def="prod-xpath40-SequenceType">SequenceType<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-TypedFunctionParam">
                     <lhs>TypedFunctionParam</lhs>
                     <rhs>("$"  <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>  "as")?  <nt def="prod-xpath40-SequenceType">SequenceType<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-TypedFunctionType">
                     <lhs>TypedFunctionType</lhs>
                     <rhs>("function"  |  "fn")  "("  (<nt def="prod-xpath40-TypedFunctionParam">TypedFunctionParam<!--$idref_lang_part = xpath40- --></nt> ** ",")  ")"  "as"  <nt def="prod-xpath40-SequenceType">SequenceType<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-TypedMapType">
                     <lhs>TypedMapType</lhs>
                     <rhs>"map"  "("  <nt def="prod-xpath40-ItemType">ItemType<!--$idref_lang_part = xpath40- --></nt>  ","  <nt def="prod-xpath40-SequenceType">SequenceType<!--$idref_lang_part = xpath40- --></nt>  ")"</rhs>
                  </prod>

                  <prod id="prod-xpath40-TypeName">
                     <lhs>TypeName</lhs>
                     <rhs>
                        <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-TypeTest">
                     <lhs>TypeTest</lhs>
                     <rhs>
                        <nt def="prod-xpath40-GNodeType">GNodeType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-XNodeType">XNodeType<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-JNodeType">JNodeType<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-UnaryExpr">
                     <lhs>UnaryExpr</lhs>
                     <rhs>("-"  |  "+")*  <nt def="prod-xpath40-ValueExpr">ValueExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-UnaryLookup">
                     <lhs>UnaryLookup</lhs>
                     <rhs>
                        <nt def="prod-xpath40-Lookup">Lookup<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-UnbracedActions">
                     <lhs>UnbracedActions</lhs>
                     <rhs>"then"  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>  "else"  <nt def="prod-xpath40-ExprSingle">ExprSingle<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-UnionExpr">
                     <lhs>UnionExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-IntersectExceptExpr">IntersectExceptExpr<!--$idref_lang_part = xpath40- --></nt>  (("union"  |  "|")  <nt def="prod-xpath40-IntersectExceptExpr">IntersectExceptExpr<!--$idref_lang_part = xpath40- --></nt>)*</rhs>
                  </prod>

                  <prod id="prod-xpath40-UnionNodeTest">
                     <lhs>UnionNodeTest</lhs>
                     <rhs>"("  (<nt def="prod-xpath40-SimpleNodeTest">SimpleNodeTest<!--$idref_lang_part = xpath40- --></nt> ++ "|")  ")"</rhs>
                  </prod>

                  <prod id="prod-xpath40-URILiteral">
                     <lhs>URILiteral</lhs>
                     <rhs>
                        <nt def="doc-xpath40-StringLiteral">StringLiteral<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-ValueComp">
                     <lhs>ValueComp</lhs>
                     <rhs>"eq"  |  "ne"  |  "lt"  |  "le"  |  "gt"  |  "ge"</rhs>
                  </prod>

                  <prod id="prod-xpath40-ValueExpr">
                     <lhs>ValueExpr</lhs>
                     <rhs>
                        <nt def="prod-xpath40-SimpleMapExpr">SimpleMapExpr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-VarName">
                     <lhs>VarName</lhs>
                     <rhs>"$"  <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-VarNameAndType">
                     <lhs>VarNameAndType</lhs>
                     <rhs>"$"  <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                        <nt def="prod-xpath40-TypeDeclaration">TypeDeclaration<!--$idref_lang_part = xpath40- --></nt>?</rhs>
                  </prod>

                  <prod id="prod-xpath40-VarRef">
                     <lhs>VarRef</lhs>
                     <rhs>"$"  <nt def="prod-xpath40-EQName">EQName<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-Wildcard">
                     <lhs>Wildcard</lhs>
                     <rhs>"*"<br/>|  (<nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>  ":*")<br/>|  ("*:"  <nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>)<br/>|  (<nt def="prod-xpath40-BracedURILiteral">BracedURILiteral<!--$idref_lang_part = xpath40- --></nt>  "*")</rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-XNodeType">
                     <lhs>XNodeType</lhs>
                     <rhs>
                        <nt def="prod-xpath40-DocumentNodeType">DocumentNodeType<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-ElementNodeType">ElementNodeType<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="doc-xpath40-AttributeNodeType">AttributeNodeType<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-SchemaElementNodeType">SchemaElementNodeType<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-SchemaAttributeNodeType">SchemaAttributeNodeType<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-ProcessingInstructionNodeType">ProcessingInstructionNodeType<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-CommentNodeType">CommentNodeType<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-TextNodeType">TextNodeType<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-NamespaceNodeType">NamespaceNodeType<!--$idref_lang_part = xpath40- --></nt>
                        <br/>|  <nt def="prod-xpath40-AnyXNodeType">AnyXNodeType<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>

                  <prod id="prod-xpath40-XPath">
                     <lhs>XPath</lhs>
                     <rhs>(<nt def="prod-xpath40-DefaultElementNamespaceDecl">DefaultElementNamespaceDecl<!--$idref_lang_part = xpath40- --></nt>  ";")?  (<nt def="prod-xpath40-NamespaceDecl">NamespaceDecl<!--$idref_lang_part = xpath40- --></nt>  ";")*  <nt def="prod-xpath40-Expr">Expr<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                  </prod>
               </prodgroup>
            </scrap>
            <div3 id="EBNFNotation">
               <head>Notation</head>
               <changes>
                  <change issue="1366" PR="1498">The EBNF operators <code nobreak="false">++</code> and <code nobreak="false">**</code>
        have been introduced, for more concise representation of sequences using a character
        such as <code nobreak="false">","</code> as a separator. The notation is borrowed from Invisible XML.</change>
               </changes>
               <p>
                  <termdef id="symbol" term="symbol">Each rule in the grammar defines one <term>symbol</term>,
          using the following format: <eg xml:space="preserve">symbol ::= expression</eg>
                  </termdef>
               </p>
               <p>
                  <termdef term="terminal" id="terminal">A <term>terminal</term> 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.</termdef> The following constructs are used to match strings
        of one or more characters in a terminal:</p>
               <glist>
                  <gitem>
                     <label>[a-zA-Z]</label>
                     <def>
                        <p>matches any <nt def="prod-xpath40-Char">Char<!--$spec = xpath40--></nt> with a value in the range(s) indicated
              (inclusive).</p>
                     </def>
                  </gitem>
                  <gitem>
                     <label>[abc]</label>
                     <def>
                        <p>matches any <nt def="prod-xpath40-Char">Char<!--$spec = xpath40--></nt> with a value among the characters enumerated.
            </p>
                     </def>
                  </gitem>
                  <gitem>
                     <label>[^abc]</label>
                     <def>
                        <p>matches any <nt def="prod-xpath40-Char">Char<!--$spec = xpath40--></nt> with a value not among the characters given.</p>
                     </def>
                  </gitem>
                  <gitem>
                     <label>"string" or 'string'</label>
                     <def>
                        <p>matches the sequence of characters that appear inside the double or single quotation marks.</p>
                     </def>
                  </gitem>
                  <gitem>
                     <label> [http://www.w3.org/TR/REC-example/#NT-Example]</label>
                     <def>
                        <p>matches any string matched by the production defined in the external specification as
              per the provided reference.</p>
                     </def>
                  </gitem>
               </glist>
               <p>Patterns (including the above constructs) can be combined with grammatical operators to
        form more complex patterns, matching more complex sets of character strings. In the examples
        that follow, <var>A</var> and <var>B</var> represent (sub-)patterns.</p>
               <glist>
                  <gitem>
                     <label>(A)</label>
                     <def>
                        <p>
                           <code nobreak="false">A</code> is treated as a unit and may be combined as described in this list.</p>
                     </def>
                  </gitem>
                  <gitem>
                     <label>A?</label>
                     <def>
                        <p>matches <code nobreak="false">A</code> or nothing; optional <code nobreak="false">A</code>.</p>
                     </def>
                  </gitem>
                  <gitem>
                     <label>A B</label>
                     <def>
                        <p>matches <code nobreak="false">A</code> followed by <code nobreak="false">B</code>. This implicit operator has higher
              precedence than the choice operator <code nobreak="false">|</code>; thus <code nobreak="false">A B | C D</code> is 
              interpreted as <code nobreak="false">(A B) | (C D)</code>.</p>
                     </def>
                  </gitem>
                  <gitem>
                     <label>A | B</label>
                     <def>
                        <p>matches <code nobreak="false">A</code> or <code nobreak="false">B</code> but not both.</p>
                     </def>
                  </gitem>
                  <gitem>
                     <label>A - B</label>
                     <def>
                        <p>matches any string that matches <code nobreak="false">A</code> but does not match <code nobreak="false">B</code>.</p>
                     </def>
                  </gitem>
                  <gitem>
                     <label>A+</label>
                     <def>
                        <p>matches one or more occurrences of <code nobreak="false">A</code>. Concatenation has higher
              precedence than choice; thus <code nobreak="false">A+ | B+</code> is identical to <code nobreak="false">(A+) |
                (B+)</code>.</p>
                     </def>
                  </gitem>
                  <gitem>
                     <label>A*</label>
                     <def>
                        <p>matches zero or more occurrences of <code nobreak="false">A</code>. Concatenation has higher
              precedence than choice; thus <code nobreak="false">A* | B*</code> is identical to <code nobreak="false">(A*) |
                (B*)</code>
                        </p>
                     </def>
                  </gitem>
                  <gitem>
                     <label>(A ++ B)</label>
                     <def>
                        <p>matches one or more occurrences of <code nobreak="false">A</code>, with one occurrence of <code nobreak="false">B</code>
              between adjacent occurrences of <code nobreak="false">A</code>. 
              The notation <code nobreak="false">A ++ B</code> is a shorthand for <code nobreak="false">A (B A)*</code>. The construct
              is always parenthesized to avoid ambiguity, and although in principle
              <code nobreak="false">B</code> could be any pattern, in practice the notation is used only when it is a simple string literal
              (typically but not invariably <code nobreak="false">","</code>).</p>
                        <p>For example, <code nobreak="false">(Digit ++ ".")</code> matches <code nobreak="false">1</code> or <code nobreak="false">1.2</code>
            or <code nobreak="false">1.2.3</code>.</p>
                     </def>
                  </gitem>
                  <gitem>
                     <label>(A ** B)</label>
                     <def>
                        <p>matches zero or more occurrences of <code nobreak="false">A</code>, with one occurrence of <code nobreak="false">B</code>
              between adjacent occurrences of <code nobreak="false">A</code>.  
              The notation <code nobreak="false">A ** B</code> is a shorthand for <code nobreak="false">(A (B A)*)?</code>. The construct
              is always parenthesized to avoid ambiguity, and although in principle
              <code nobreak="false">B</code> could be any pattern, in practice the notation is used only when it is a simple string literal
              (typically but not invariably <code nobreak="false">","</code>).</p>
                        <p>For example, <code nobreak="false">"[" (Digit ** "|") "]"</code> matches <code nobreak="false">[]</code> or <code nobreak="false">[1]</code> or <code nobreak="false">[1|2]</code>
            or <code nobreak="false">[1|2|3]</code>.</p>
                     </def>
                  </gitem>
               </glist>
            </div3>
            <div3 id="extra-grammatical-constraints">
               <head>Extra-grammatical Constraints</head>
               <p>This section contains constraints on the EBNF productions, which are required to parse
        syntactically valid sentences. The notes below are referenced from the right side of the
        production, with the notation: <emph>/* xgc: &lt;id&gt; */</emph>.</p>
               <constraintnote id="parse-note-leading-lone-slash" type="xgc">
                  <head>leading-lone-slash</head>
                  <p>A single slash may appear either as a complete path expression or as the first part of a
          path expression in which it is followed by a <nt def="doc-xpath40-RelativePathExpr">RelativePathExpr<!--$spec = xpath40--></nt>. In some cases, the next terminal after the slash is insufficient to
          allow a parser to distinguish these two possibilities: a <code nobreak="false">*</code> symbol or a
          keyword like <code nobreak="false">union</code> could be either an operator or a <nt def="prod-xpath40-NameTest">NameTest<!--$spec = xpath40--></nt>. For example, the expression <code nobreak="false">/union/*</code> could be parsed
          either as <code nobreak="false">(/) union (/*)</code> or as <code nobreak="false">/child::union/child::*</code> (the
          second interpretation is the one chosen).</p>
                  <p>The situation where <code nobreak="false">/</code> is followed by <code nobreak="false">&lt;</code> is a little more
          complicated. In XPath, this is unambiguous: the <code nobreak="false">&lt;</code> can only indicate
          one of the operators <code nobreak="false">&lt;</code>, <code nobreak="false">&lt;=</code>, or <code nobreak="false">&lt;&lt;</code>.
          In XQuery, however, it can also be the start of a direct constructor: specifically,
          a direct constructor for an element node, processing instruction node, or comment node.
          These constructs are identified by the tokenizer, independently of their syntactic
          context, as described in <specref ref="lexical-structure"/>.</p>
                  <p>The rule adopted is as follows: if the terminal immediately following a slash
          can form the start of a <nt def="doc-xpath40-RelativePathExpr">RelativePathExpr<!--$spec = xpath40--></nt>, then the slash
          must be the beginning of a <nt def="doc-xpath40-PathExpr">PathExpr<!--$spec = xpath40--></nt>, not the entirety of it.</p>
                  <p>The terminals that can form the start of a <nt def="doc-xpath40-RelativePathExpr">RelativePathExpr<!--$spec = xpath40--></nt>
        are: <code nobreak="false">NCName</code>, <code nobreak="false">QName</code>, <code nobreak="false">URIQualifiedName</code>,
          <code nobreak="false">StringLiteral</code>, <code nobreak="false">NumericLiteral</code>, 
          <code nobreak="false">Wildcard</code>, and <code nobreak="false">StringTemplate</code>; 
        plus <code nobreak="false">@</code>
                     <code nobreak="false">.</code>
                     <code nobreak="false">..</code>
                     <code nobreak="false">*</code>
                     <code nobreak="false">$</code>
                     <code nobreak="false">?</code>
                     <code nobreak="false">??</code>
                     <code nobreak="false">%</code>
                     <code nobreak="false">(</code>
                     <code nobreak="false">[</code>; and in XQuery <code nobreak="false">StringConstructor</code> and <code nobreak="false">DirectConstructor</code>.
        </p>
                  <!-- The above list was obtained by running the stylesheet leading-tokens.xsl against xpath-grammar.xml -->
                  <p>A single slash may be used as the left-hand argument of an operator by parenthesizing it:
            <code role="parse-test" nobreak="false">(/) * 5</code>. The expression <code role="parse-test" nobreak="false">5 *
            /</code>, on the other hand, is syntactically valid without parentheses.</p>
               </constraintnote>
               <constraintnote id="parse-note-xml-version" type="xgc">
                  <head>xml-version</head>
                  <p>The version of XML and XML Names (e.g. <bibref ref="XML"/> and <bibref ref="XMLNAMES"/>,
          or <bibref ref="XML1.1"/> and <bibref ref="XMLNAMES11"/>) is <termref def="dt-implementation-defined">implementation-defined</termref>. It is recommended that
          the latest applicable version be used (even if it is published later than this
          specification). The EBNF in this specification links only to the 1.0 versions. Note also
          that these external productions follow the whitespace rules of their respective
          specifications, and not the rules of this specification, in particular <specref ref="DefaultWhitespaceHandling"/>. Thus <code nobreak="false">prefix : localname</code> is not a
          syntactically valid <termref def="dt-qname">lexical QName</termref> for purposes of this
          specification, just as it is not permitted in a XML document. Also, comments are not
          permissible on either side of the colon. Also extra-grammatical constraints such as
          well-formedness constraints must be taken into account.</p>
               </constraintnote>
               <constraintnote id="parse-note-reserved-function-names" type="xgc">
                  <head>reserved-function-names</head>
                  <p>Unprefixed function names spelled the same way as language keywords could make the
          language impossible to parse. For instance, <code nobreak="false">element(foo)</code> could be taken either as
          a <nt def="doc-xpath40-FunctionCall">FunctionCall<!--$spec = xpath40--></nt> or as an <nt def="doc-xpath40-ElementNodeType"><!--$spec = xpath40--></nt>. 
          Therefore, an unprefixed function name must not be any of the names in
            <specref ref="id-reserved-fn-names"/>.</p>
                  <p>A function named <code nobreak="false">if</code> can be called by binding its namespace to a prefix and using the
          prefixed form: <code nobreak="false">library:if(foo)</code> instead of <code nobreak="false">if(foo)</code>.</p>
               </constraintnote>
               <constraintnote id="parse-note-occurrence-indicators" type="xgc">
                  <head>occurrence-indicators</head>
                  <p diff="chg" at="2023-05-22">As written, the grammar in <specref ref="nt-bnf"/> is ambiguous for some forms using the
          <code nobreak="false">"+"</code>, <code nobreak="false">"?"</code> and <code nobreak="false">"*"</code>
                     <nt def="prod-xpath40-OccurrenceIndicator">OccurrenceIndicators<!--$spec = xpath40--></nt>. 
          The ambiguity is resolved as follows: these operators are
          tightly bound to the <nt def="doc-xpath40-SequenceType">SequenceType<!--$spec = xpath40--></nt> expression, and have higher
          precedence than other uses of these symbols. Any occurrence of <code nobreak="false">"+"</code>, 
          <code nobreak="false">"?"</code> or <code nobreak="false">"*"</code>, that follows a sequence type is assumed to be an occurrence indicator, which binds to
          the last <nt def="doc-xpath40-ItemType">ItemType<!--$spec = xpath40--></nt> in the <nt def="doc-xpath40-SequenceType">SequenceType<!--$spec = xpath40--></nt>.</p>
                  <p>Thus, <code role="parse-test" nobreak="false">4 treat as item() + - 5</code> must be interpreted as <code role="parse-test" nobreak="false">(4 treat as item()+) - 5</code>, taking the '+' as an
          occurrence indicator and the '-' as a subtraction operator. To force the interpretation of
          "+" as an addition operator (and the corresponding interpretation of the "-" as a unary
          minus), parentheses may be used: the form <code role="parse-test" nobreak="false">(4 treat as item()) +
            -5</code> surrounds the <nt def="doc-xpath40-SequenceType">SequenceType<!--$spec = xpath40--></nt> expression with
          parentheses and leads to the desired interpretation.</p>
                  <p>
                     <code nobreak="false">function () as xs:string *</code> is interpreted as <code nobreak="false">function () as (xs:string
            *)</code>, not as <code nobreak="false">(function () as xs:string) *</code>. Parentheses can be used as
          shown to force the latter interpretation.</p>
                  <p>This rule has as a consequence that certain forms which would otherwise be syntactically
          valid and unambiguous are not recognized: in <code nobreak="false">4 treat as item() + 5</code>, the <code nobreak="false">"+"</code> is taken as
          an <nt def="prod-xpath40-OccurrenceIndicator">OccurrenceIndicator<!--$spec = xpath40--></nt>, and not as an operator, which
          means this is not a syntactically valid expression.</p>
               </constraintnote>
               <!--<constraintnote id="constructor-op-brace" type="xgc">
        
        <head>constructor-op-brace</head>
        
        <p>In XQuery, there are two ways that the expression <code>element otherwise {}</code> could be parsed:
        it could be treated as a computed element constructor creating an element named <code>otherwise</code>
        with empty content, or it could be treated as an attempt to select a child node named <code>element</code>,
        returning an empty map if no such node exists.</p>
        
        <p>This ambiguity has been introduced in 4.0 as a consequence of allowing map constructors to be
        written without the leading <code>map</code> keyword. The ambiguity is therefore resolved to retain
        the XQuery 3.1 interpretation, constructing an element named <code>otherwise</code>.</p>
        
        <p>More generally, if an expression starts with the three tokens (<var>K</var> <var>N</var> "{"), 
          where <var>K</var> is one of <code>element</code>, <code>attribute</code>, 
          <code>processing-instruction</code>, or <code>namespace</code>, and <var>N</var> is an
          <code>NCName</code> that could be interpreted as a binary operator (for example <code>div</code> or
          <code>otherwise</code>) then the expression is parsed as a node construction expression,
          creating a node of kind <var>K</var> whose name is <var>N</var>.</p>
        
        <p>This ambiguity does not arise in XPath, which does not recognize computed node constructor
        expressions. However, in the interests of compatibility between XPath and XQuery, and to retain
        the option of adding computed node constructors to XPath in the future, XPath processors
        <code>should</code> reject such expressions as invalid.</p>
        
      </constraintnote>-->
            </div3>
            <div3 id="notes-on-parsing">
               <head>Grammar Notes</head>
               <p>This section contains general notes on the EBNF productions, which may be helpful in
        understanding how to interpret and implement the EBNF. These notes are not normative. The
        notes below are referenced from the right side of the production, with the notation:
          <emph>/* gn: &lt;id&gt; */</emph>.</p>
               <note>
                  <glist>
                     <gitem id="parse-note-parens">
                        <label>grammar-note: parens</label>
                        <def>
                           <p>Lookahead is required to distinguish a <nt def="doc-xpath40-FunctionCall">FunctionCall<!--$spec = xpath40--></nt> from
                an EQName or keyword followed by a 
                <nt def="doc-xpath40-Comment">Comment<!--$spec = xpath40--></nt>. For example: <code role="parse-test" nobreak="false">address (: this
                  may be empty :)</code> may be mistaken for a call to a function named "address"
                unless this lookahead is employed. Another example is <code role="parse-test" nobreak="false">for (:
                  whom the bell :) $tolls in 3 return $tolls</code>, where the keyword "for" must
                not be mistaken for a function name.</p>
                        </def>
                     </gitem>
                     <gitem id="parse-note-comments">
                        <label>grammar-note: comments</label>
                        <def>
                           <p>Comments are allowed everywhere that <termref def="IgnorableWhitespace">ignorable
                  whitespace</termref> is allowed, and the <nt def="doc-xpath40-Comment">Comment<!--$spec = xpath40--></nt> symbol
                does not explicitly appear on the right-hand side of the grammar (except in its own
                production). See <specref ref="DefaultWhitespaceHandling"/>. </p>
                           <p>A comment can contain nested comments, as long as all <code nobreak="false">"(:"</code> and <code nobreak="false">":)"</code> patterns are
                balanced, no matter where they occur within the outer comment.</p>
                           <note>
                              <p>Lexical analysis may typically handle nested comments by incrementing a counter
                  for each <code nobreak="false">"(:"</code> pattern, and decrementing the counter for each <code nobreak="false">":)"</code> pattern. The
                  comment does not terminate until the counter is back to zero.</p>
                           </note>
                           <p>Some illustrative examples:</p>
                           <ulist>
                              <item>
                                 <p>
                                    <code nobreak="false">(: commenting out a (: comment :) may be confusing, but often helpful
                      :)</code> is a syntactically valid <nt def="doc-xpath40-Comment">Comment<!--$spec = xpath40--></nt>, since balanced nesting of comments
                    is allowed.</p>
                              </item>
                              <item>
                                 <p>
                                    <code role="parse-test" nobreak="false">"this is just a string :)"</code> is a syntactically
                    valid expression. However, <code nobreak="false">(: "this is just a string :)" :)</code> will
                    cause a syntax error. Likewise, <code role="parse-test" nobreak="false">"this is another string
                      (:"</code> is a syntactically valid expression, but <code nobreak="false">(: "this is another
                      string (:" :)</code> will cause a syntax error. It is a limitation of nested
                    comments that literal content can cause unbalanced nesting of comments.</p>
                              </item>
                              <item>
                                 <p>
                                    <code role="parse-test" nobreak="false">for (: set up loop :) $i in $x return $i</code> is
                    syntactically valid, ignoring the comment.</p>
                              </item>
                              <item>
                                 <p>
                                    <code role="parse-test" nobreak="false">5 instance (: strange place for a comment :) of
                      xs:integer</code> is also syntactically valid.</p>
                              </item>
                           </ulist>
                        </def>
                     </gitem>
                  </glist>
               </note>
            </div3>
         </div2>
         <div2 id="productions-derived-from-XML">
            <head>Productions Derived from XML</head>
            <p>Some productions are defined by reference to the XML and XML Names specifications (e.g.
      <bibref ref="XML"/> and <bibref ref="XMLNAMES"/>, or <bibref ref="XML1.1"/> and <bibref ref="XMLNAMES11"/>. <phrase role="xpath">A host language may choose</phrase> which version of these specifications is
      used; it is recommended that the latest applicable version be used (even if it is published
      later than this specification).</p>
            <p role="xpath">A <term>host language</term> may choose whether the lexical rules of <bibref ref="XML"/> and <bibref ref="XMLNAMES"/> are followed, or alternatively, the lexical rules
      of <bibref ref="XML1.1"/> and <bibref ref="XMLNAMES11"/> are followed.</p>
         </div2>
         <div2 id="lexical-structure">
            <head>Lexical structure</head>
            <changes>
               <change issue="327" PR="519" date="2023-05-30">
        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.
      </change>
            </changes>
            <p diff="add" at="2023-05-22">This section describes how an XPath 4.0 text is tokenized prior to parsing.</p>
            <p>All keywords are case sensitive. Keywords are not reserved—that is, any <termref def="dt-qname">lexical QName</termref> may duplicate a keyword except as noted in <specref ref="id-reserved-fn-names"/>.</p>
            <p diff="add" at="2023-05-22">Tokenizing an input string is a process that follows the following rules:</p>
            <ulist diff="add" at="2023-05-22">
               <item>
                  <p>
                     <termdef id="dt-ordinary-production-rule" term="ordinary production rule">An <term>ordinary production rule</term> 
        is a production rule in <specref ref="id-grammar"/> that is not annotated <code nobreak="false">ws:explicit</code>.</termdef>
                  </p>
               </item>
               <item>
                  <p>
                     <termdef id="dt-literal-terminal" term="literal terminal">A <term>literal terminal</term> is a token appearing as a string 
        in quotation marks on the right-hand side of an <termref def="dt-ordinary-production-rule"/>.</termdef>
                  </p>
                  <note>
                     <p>Strings that appear in other production rules do not qualify.
        
          <phrase role="xpath">For example, <nt def="prod-xpath40-BracedURILiteral">BracedURILiteral<!--$spec = xpath40--></nt>
            does not quality because it appears only in <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$spec = xpath40--></nt>, and <code nobreak="false">"0x"</code> does not qualify
            because it appears only in <nt def="prod-xpath40-HexIntegerLiteral">HexIntegerLiteral<!--$spec = xpath40--></nt>.</phrase>
                     </p>
                  </note>
                  <p>
          The <termref def="dt-literal-terminal">literal terminals</termref>  in XPath 4.0 are: <code>!</code>
                     <code>!=</code>
                     <code>#</code>
                     <code>$</code>
                     <code>(</code>
                     <code>)</code>
                     <code>*</code>
                     <code>+</code>
                     <code>,</code>
                     <code>.</code>
                     <code>..</code>
                     <code>/</code>
                     <code>//</code>
                     <code>:</code>
                     <code>::</code>
                     <code>:=</code>
                     <code>;</code>
                     <code>&lt;</code>
                     <code>&lt;&lt;</code>
                     <code>&lt;=</code>
                     <code>=</code>
                     <code>=!&gt;</code>
                     <code>=&gt;</code>
                     <code>=?&gt;</code>
                     <code>&gt;</code>
                     <code>&gt;=</code>
                     <code>&gt;&gt;</code>
                     <code>?</code>
                     <code>?[</code>
                     <code>@</code>
                     <code>[</code>
                     <code>]</code>
                     <code>{</code>
                     <code>|</code>
                     <code>||</code>
                     <code>}</code>
                     <code>×</code>
                     <code>÷</code>
                     <code>-</code>
                     <code>-&gt;</code>
                     <code>ancestor</code>
                     <code>ancestor-or-self</code>
                     <code>and</code>
                     <code>array</code>
                     <code>as</code>
                     <code>at</code>
                     <code>attribute</code>
                     <code>cast</code>
                     <code>castable</code>
                     <code>child</code>
                     <code>comment</code>
                     <code>declare</code>
                     <code>default</code>
                     <code>descendant</code>
                     <code>descendant-or-self</code>
                     <code>div</code>
                     <code>document</code>
                     <code>document-node</code>
                     <code>element</code>
                     <code>else</code>
                     <code>empty-sequence</code>
                     <code>enum</code>
                     <code>eq</code>
                     <code>every</code>
                     <code>except</code>
                     <code>false</code>
                     <code>fn</code>
                     <code>following</code>
                     <code>following-or-self</code>
                     <code>following-sibling</code>
                     <code>following-sibling-or-self</code>
                     <code>follows</code>
                     <code>follows-or-is</code>
                     <code>for</code>
                     <code>function</code>
                     <code>ge</code>
                     <code>get</code>
                     <code>gnode</code>
                     <code>gt</code>
                     <code>idiv</code>
                     <code>if</code>
                     <code>in</code>
                     <code>instance</code>
                     <code>intersect</code>
                     <code>is</code>
                     <code>is-not</code>
                     <code>item</code>
                     <code>jnode</code>
                     <code>key</code>
                     <code>le</code>
                     <code>let</code>
                     <code>lt</code>
                     <code>map</code>
                     <code>member</code>
                     <code>mod</code>
                     <code>namespace</code>
                     <code>namespace-node</code>
                     <code>ne</code>
                     <code>node</code>
                     <code>of</code>
                     <code>or</code>
                     <code>otherwise</code>
                     <code>parent</code>
                     <code>precedes</code>
                     <code>precedes-or-is</code>
                     <code>preceding</code>
                     <code>preceding-or-self</code>
                     <code>preceding-sibling</code>
                     <code>preceding-sibling-or-self</code>
                     <code>processing-instruction</code>
                     <code>record</code>
                     <code>return</code>
                     <code>satisfies</code>
                     <code>schema-attribute</code>
                     <code>schema-element</code>
                     <code>self</code>
                     <code>some</code>
                     <code>text</code>
                     <code>then</code>
                     <code>to</code>
                     <code>treat</code>
                     <code>true</code>
                     <code>union</code>
                     <code>value</code> 
                  </p>
               </item>
               <item>
                  <p>
                     <termdef id="dt-variable-terminal" term="variable terminal">A <term>variable terminal</term> is an instance
        of a production rule that is not itself an <termref def="dt-ordinary-production-rule"/> but that is named (directly) on the right-hand
        side of an <termref def="dt-ordinary-production-rule"/>.</termdef>
                  </p>
                  <p>
          The <termref def="dt-variable-terminal">variable terminals</termref> in XPath 4.0 are: <nt def="prod-xpath40-BinaryIntegerLiteral">BinaryIntegerLiteral</nt>
                     <nt def="prod-xpath40-DecimalLiteral">DecimalLiteral</nt>
                     <nt def="prod-xpath40-DoubleLiteral">DoubleLiteral</nt>
                     <nt def="prod-xpath40-HexIntegerLiteral">HexIntegerLiteral</nt>
                     <nt def="prod-xpath40-IntegerLiteral">IntegerLiteral</nt>
                     <code>NCName</code>
                     <nt def="prod-xpath40-QName">QName</nt>
                     <nt def="prod-xpath40-StringLiteral">StringLiteral</nt>
                     <nt def="prod-xpath40-StringTemplate">StringTemplate</nt>
                     <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName</nt>
                     <nt def="prod-xpath40-Wildcard">Wildcard</nt> 
                  </p>
               </item>
               <item>
                  <p>
                     <termdef id="dt-complex-terminal" term="complex terminal">A <term>complex terminal</term> is
        a <termref def="dt-variable-terminal"/> whose production rule references, directly or indirectly, an 
        <termref def="dt-ordinary-production-rule"/>.</termdef>
                  </p>
                  <p>
          The <termref def="dt-complex-terminal">complex terminals</termref>  in XPath 4.0 are: <nt def="prod-xpath40-StringTemplate">StringTemplate</nt> 
                  </p>
                  <note>
                     <p>The significance of complex terminals is that at one level, a complex terminal is treated as a single
      token, but internally it may contain arbitrary expressions that must be parsed using the full EBNF grammar.</p>
                  </note>
               </item>
               <item>
                  <p>Tokenization is the process of splitting the supplied input string into a sequence of terminals, where each
      terminal is either a <termref def="dt-literal-terminal"/> or a <termref def="dt-variable-terminal"/> (which may itself
      be a <termref def="dt-complex-terminal"/>). Tokenization is done by repeating the following steps:</p>
                  <olist>
                     <item>
                        <p>Starting at the current position, skip any whitespace and comments.</p>
                     </item>
                     <item>
                        <p>If the current position is not the end of the input, then
          return the longest <termref def="dt-literal-terminal"/> or <termref def="dt-variable-terminal"/> 
        that can be matched starting at the current position, regardless whether this terminal is valid at this point
        in the grammar. If no such terminal can be identified starting at the current position, or if the terminal that
        is identified is not a valid continuation of the grammar rules, then a syntax error is reported.</p>
                        <note>
                           <p>Here are some examples showing the effect of the longest token rule:</p>
                           <ulist>
                              <item>
                                 <p>The expression <code nobreak="false">map{a:b}</code> is a syntax error. Although there is a 
              tokenization of this string that satisfies the grammar (by treating <code nobreak="false">a</code> and <code nobreak="false">b</code>
              as separate expressions), this tokenization does not satisfy the longest token rule,
              which requires that <code nobreak="false">a:b</code> is interpreted as a single <code nobreak="false">QName</code>.</p>
                              </item>
                              <item>
                                 <p>The expression <code nobreak="false">10 div3</code> is a syntax error. The longest token rule requires that this
              be interpreted as two tokens (<code nobreak="false">"10"</code> and <code nobreak="false">"div3"</code>) even though it would
              be a valid expression if treated as three tokens (<code nobreak="false">"10"</code>, <code nobreak="false">"div"</code>, and <code nobreak="false">"3"</code>).</p>
                              </item>
                              <item>
                                 <p>The expression <code nobreak="false">$x-$y</code> is a syntax error. This is interpreted as four tokens,
              (<code nobreak="false">"$"</code>, <code nobreak="false">"x-"</code>, <code nobreak="false">"$"</code>, and <code nobreak="false">"y"</code>).</p>
                              </item>
                              <!--<item role="xquery"><p>In XQuery, the expression <code>error(#err:XPTY0004)</code> is a syntax error. 
              The presence of <code>(#</code>, without intervening whitespace, indicates the start of a pragma.
              To interpret this as a call on the <function>fn:error</function> function with a <code>QNameLiteral</code> argument,
              whitespace separation is needed: <code>error( #err:XPTY0004 )</code>.</p></item>-->
                           </ulist>
                        </note>
                        <note>
                           <p>The lexical production rules for <termref def="dt-variable-terminal">variable terminals</termref>
        have been designed so that there is minimal need for backtracking. For example, if the next terminal
        starts with <code nobreak="false">"0x"</code>, then it can only be either a <nt def="prod-xpath40-HexIntegerLiteral">HexIntegerLiteral<!--$spec = xpath40--></nt> or an error;
        if it starts with <code nobreak="false">"`"</code> (and not with <code nobreak="false">"```"</code>) then it can only be a
          <nt def="doc-xpath40-StringTemplate">StringTemplate<!--$spec = xpath40--></nt> or an error. </p>
                           <p>This convention, together with the rules for whitespace separation of tokens (see <specref ref="id-terminal-delimitation"/>) 
          means that the longest-token rule does not normally result in any need for backtracking. For example, suppose 
          that a <termref def="dt-variable-terminal"/> has been identified as a <nt def="doc-xpath40-StringTemplate">StringTemplate<!--$spec = xpath40--></nt> by examining
          its first few characters. If the construct turns out not to be a valid <nt def="doc-xpath40-StringTemplate">StringTemplate<!--$spec = xpath40--></nt>, 
          an error can be reported without first considering whether there is some shorter token that might be returned instead.</p>
                        </note>
                     </item>
                  </olist>
               </item>
               <item>
                  <p>Tokenization unambiguously identifies the boundaries of the terminals in the input, and this
        can be achieved without backtracking or lookahead. However, tokenization does
      not unambiguously classify each terminal. For example, it might identify the string <code nobreak="false">"div"</code> as a terminal, but it does not
      resolve whether this is the operator symbol <code nobreak="false">div</code>, or an <code nobreak="false">NCName</code> 
        or <code nobreak="false">QName</code> used as a 
      node test or as a variable or function name. Classification of terminals generally requires information about the
      grammatical context, and in some cases requires lookahead.</p>
                  <note>
                     <p>Operationally, classification of terminals may be done either in the tokenizer or the parser, or
      in some combination of the two. For example, according to the EBNF, the expression 
        <code nobreak="false">"parent::x"</code> is made up of three
      tokens, <code nobreak="false">"parent"</code>, <code nobreak="false">"::"</code>, and <code nobreak="false">"x"</code>. The name <code nobreak="false">"parent"</code>
        can be classified as an axis name as soon as the following token <code nobreak="false">"::"</code> is recognized, and this
      might be done either in the tokenizer or in the parser. (Note that whitespace and comments are allowed
      both before and after <code nobreak="false">"::"</code>.)</p>
                  </note>
               </item>
               <item>
                  <p>In the case of a <termref def="dt-complex-terminal"/>, identifying the end of the complex terminal
      typically involves invoking the parser to process any embedded expressions. Tokenization, as described
      here, is therefore a recursive process. But other implementations are possible.</p>
               </item>
            </ulist>
            <note>
               <p>Previous versions of this specification included the statement: 
      <emph>When tokenizing, the longest possible match that is consistent with the EBNF is used.</emph>
               </p>
               <p>Different processors are known to have interpreted this in different ways. One interpretation,
      for example, was that the expression <code nobreak="false">10 div-3</code> should be split into four tokens (<code nobreak="false">10</code>,
      <code nobreak="false">div</code>, <code nobreak="false">-</code>, <code nobreak="false">3</code>) on the grounds that any other tokenization would give a
      result that was inconsistent with the EBNF grammar. Other processors report a syntax error on this example.</p>
               <p>This rule has therefore been rewritten in version 4.0. Tokenization is now entirely insensitive to the
      grammatical context; <code nobreak="false">div-3</code> is recognized as a single token even though this results in a syntax
      error. For some implementations this may mean that expressions that were accepted in earlier releases
      are no longer accepted in 4.0.</p>
            </note>
            <div3 id="terminal-symbols">
               <head>Terminal Symbols</head>
               <scrap headstyle="show">
                  <head/>
                  <prod id="prod-xpath40-IntegerLiteral">
                     <lhs>IntegerLiteral</lhs>
                     <rhs>
                        <nt def="prod-xpath40-Digits">Digits<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-HexIntegerLiteral">
                     <lhs>HexIntegerLiteral</lhs>
                     <rhs>"0x"  <nt def="prod-xpath40-HexDigits">HexDigits<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-BinaryIntegerLiteral">
                     <lhs>BinaryIntegerLiteral</lhs>
                     <rhs>"0b"  <nt def="prod-xpath40-BinaryDigits">BinaryDigits<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-DecimalLiteral">
                     <lhs>DecimalLiteral</lhs>
                     <rhs>("."  <nt def="prod-xpath40-Digits">Digits<!--$idref_lang_part = xpath40- --></nt>)  |  (<nt def="prod-xpath40-Digits">Digits<!--$idref_lang_part = xpath40- --></nt>  "."  <nt def="prod-xpath40-Digits">Digits<!--$idref_lang_part = xpath40- --></nt>?)</rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-DoubleLiteral">
                     <lhs>DoubleLiteral</lhs>
                     <rhs>(("."  <nt def="prod-xpath40-Digits">Digits<!--$idref_lang_part = xpath40- --></nt>)  |  (<nt def="prod-xpath40-Digits">Digits<!--$idref_lang_part = xpath40- --></nt>  ("."  <nt def="prod-xpath40-Digits">Digits<!--$idref_lang_part = xpath40- --></nt>?)?))  [eE]  [+-]?  <nt def="prod-xpath40-Digits">Digits<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-StringLiteral">
                     <lhs>StringLiteral</lhs>
                     <rhs>
                        <nt def="prod-xpath40-AposStringLiteral">AposStringLiteral<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-QuotStringLiteral">QuotStringLiteral<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-AposStringLiteral">
                     <lhs>AposStringLiteral</lhs>
                     <rhs>"'"  (<nt def="prod-xpath40-EscapeApos">EscapeApos<!--$idref_lang_part = xpath40- --></nt>  |  [^'])*  "'"</rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-QuotStringLiteral">
                     <lhs>QuotStringLiteral</lhs>
                     <rhs>'"'  (<nt def="prod-xpath40-EscapeQuot">EscapeQuot<!--$idref_lang_part = xpath40- --></nt>  |  [^"])*  '"'</rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-URIQualifiedName">
                     <lhs>URIQualifiedName</lhs>
                     <rhs>
                        <nt def="prod-xpath40-BracedURILiteral">BracedURILiteral<!--$idref_lang_part = xpath40- --></nt>  (<nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>  ":")?  <nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>
                     </rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-BracedURILiteral">
                     <lhs>BracedURILiteral</lhs>
                     <rhs>"Q"  "{"  [^{}]*  "}"</rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-EscapeQuot">
                     <lhs>EscapeQuot</lhs>
                     <rhs>'""'</rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-EscapeApos">
                     <lhs>EscapeApos</lhs>
                     <rhs>"''"</rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-Comment">
                     <lhs>Comment</lhs>
                     <rhs>"(:"  (<nt def="prod-xpath40-CommentContents">CommentContents<!--$idref_lang_part = xpath40- --></nt>  |  <nt def="prod-xpath40-Comment">Comment<!--$idref_lang_part = xpath40- --></nt>)*  ":)"</rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                     <com>
                        <loc href="#parse-note-comments">gn: comments</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-QName">
                     <lhs>QName</lhs>
                     <rhs>
                        <xnt ref="NT-QName" spec="Names">[http://www.w3.org/TR/REC-xml-names/#NT-QName]</xnt>
                     </rhs>
                     <com>
                        <loc href="#parse-note-xml-version">xgc: xml-version</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-NCName">
                     <lhs>NCName</lhs>
                     <rhs>
                        <xnt ref="NT-NCName" spec="Names">[http://www.w3.org/TR/REC-xml-names/#NT-NCName]</xnt>
                     </rhs>
                     <com>
                        <loc href="#parse-note-xml-version">xgc: xml-version</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-Char">
                     <lhs>Char</lhs>
                     <rhs>
                        <xnt ref="NT-Char" spec="XML">[http://www.w3.org/TR/REC-xml#NT-Char]</xnt>
                     </rhs>
                     <com>
                        <loc href="#parse-note-xml-version">xgc: xml-version</loc>
                     </com>
                  </prod>
               </scrap>
               <p>The following symbols are used only in the definition of terminal symbols; they are not
        terminal symbols in the grammar of <specref ref="id-grammar"/>.</p>
               <scrap headstyle="show">
                  <head/>
                  <prod id="prod-xpath40-Digits">
                     <lhs>Digits</lhs>
                     <rhs>
                        <nt def="prod-xpath40-DecDigit">DecDigit<!--$idref_lang_part = xpath40- --></nt>  ((<nt def="prod-xpath40-DecDigit">DecDigit<!--$idref_lang_part = xpath40- --></nt>  |  "_")*  <nt def="prod-xpath40-DecDigit">DecDigit<!--$idref_lang_part = xpath40- --></nt>)?</rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-DecDigit">
                     <lhs>DecDigit</lhs>
                     <rhs>[0-9]</rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-HexDigits">
                     <lhs>HexDigits</lhs>
                     <rhs>
                        <nt def="prod-xpath40-HexDigit">HexDigit<!--$idref_lang_part = xpath40- --></nt>  ((<nt def="prod-xpath40-HexDigit">HexDigit<!--$idref_lang_part = xpath40- --></nt>  |  "_")*  <nt def="prod-xpath40-HexDigit">HexDigit<!--$idref_lang_part = xpath40- --></nt>)?</rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-HexDigit">
                     <lhs>HexDigit</lhs>
                     <rhs>[0-9a-fA-F]</rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-BinaryDigits">
                     <lhs>BinaryDigits</lhs>
                     <rhs>
                        <nt def="prod-xpath40-BinaryDigit">BinaryDigit<!--$idref_lang_part = xpath40- --></nt>  ((<nt def="prod-xpath40-BinaryDigit">BinaryDigit<!--$idref_lang_part = xpath40- --></nt>  |  "_")*  <nt def="prod-xpath40-BinaryDigit">BinaryDigit<!--$idref_lang_part = xpath40- --></nt>)?</rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-BinaryDigit">
                     <lhs>BinaryDigit</lhs>
                     <rhs>[01]</rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>

                  <prod id="prod-xpath40-CommentContents">
                     <lhs>CommentContents</lhs>
                     <rhs>(<nt def="prod-xpath40-Char">Char<!--$idref_lang_part = xpath40- --></nt>+ - (Char* ('(:' | ':)') Char*))</rhs>
                     <com>
                        <loc href="#ws-explicit">ws: explicit</loc>
                     </com>
                  </prod>
               </scrap>
            </div3>
            <div3 id="id-terminal-delimitation">
               <head>Terminal Delimitation</head>
               <p>XPath 4.0 expressions consist of <loc xmlns:xlink="http://www.w3.org/1999/xlink"
                       href="#terminal-symbols"
                       xlink:type="simple"
                       xlink:show="replace"
                       xlink:actuate="onRequest">terminal symbols</loc> and
          <termref def="symbolseparators">symbol separators</termref>.</p>
               <p>
                  <phrase diff="add" at="2023-05-22">
                     <termref def="dt-literal-terminal">Literal</termref> 
        and <termref def="dt-variable-terminal">variable</termref>
                  </phrase>
        terminal symbols are of two kinds: delimiting and non-delimiting.</p>
               <!-- The next paragraph is "filled in" by various stylesheets used to generate the "assembled" source files. -->
               <p>
                  <termdef id="delimiting-token" term="delimiting terminal symbol">The <term>delimiting
            terminal symbols</term> are: <code>!</code>
                     <code>!=</code>
                     <code>#</code>
                     <code>$</code>
                     <code>(</code>
                     <code>)</code>
                     <code>*</code>
                     <code>*:</code>
                     <code>+</code>
                     <code>,</code>
                     <code>-</code>
                     <code>-&gt;</code>
                     <code>.</code>
                     <code>..</code>
                     <code>/</code>
                     <code>//</code>
                     <code>:</code>
                     <code>:*</code>
                     <code>::</code>
                     <code>:=</code>
                     <code>;</code>
                     <code>&lt;</code>
                     <code>&lt;&lt;</code>
                     <code>&lt;=</code>
                     <code>=</code>
                     <code>=!&gt;</code>
                     <code>=&gt;</code>
                     <code>=?&gt;</code>
                     <code>&gt;</code>
                     <code>&gt;=</code>
                     <code>&gt;&gt;</code>
                     <code>?</code>
                     <code>?[</code>
                     <code>@</code>
                     <code>[</code>
                     <code>]</code>
                     <code>`</code>
                     <code>``</code>
                     <code>{</code>
                     <code>{{</code>
                     <code>|</code>
                     <code>||</code>
                     <code>}</code>
                     <code>}}</code>
                     <code>×</code>
                     <code>÷</code>
                     <nt def="prod-xpath40-AposStringLiteral">AposStringLiteral<!--$idref_lang_part = xpath40- --></nt>
                     <nt def="prod-xpath40-BracedURILiteral">BracedURILiteral<!--$idref_lang_part = xpath40- --></nt>
                     <nt def="prod-xpath40-QuotStringLiteral">QuotStringLiteral<!--$idref_lang_part = xpath40- --></nt>
                     <nt def="prod-xpath40-StringLiteral">StringLiteral<!--$idref_lang_part = xpath40- --></nt>
                     <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$idref_lang_part = xpath40- --></nt>
                  </termdef>
               </p>
               <!-- The next paragraph is "filled in" by various stylesheets used to generate the "assembled" source files. -->
               <p>
                  <termdef id="non-delimiting-token" term="non-delimiting terminal symbol">The
            <term>non-delimiting terminal symbols</term> are: <code>ancestor</code>
                     <code>ancestor-or-self</code>
                     <code>and</code>
                     <code>array</code>
                     <code>as</code>
                     <code>at</code>
                     <code>attribute</code>
                     <code>cast</code>
                     <code>castable</code>
                     <code>child</code>
                     <code>comment</code>
                     <code>declare</code>
                     <code>default</code>
                     <code>descendant</code>
                     <code>descendant-or-self</code>
                     <code>div</code>
                     <code>document</code>
                     <code>document-node</code>
                     <code>element</code>
                     <code>else</code>
                     <code>empty-sequence</code>
                     <code>enum</code>
                     <code>eq</code>
                     <code>every</code>
                     <code>except</code>
                     <code>false</code>
                     <code>fn</code>
                     <code>following</code>
                     <code>following-or-self</code>
                     <code>following-sibling</code>
                     <code>following-sibling-or-self</code>
                     <code>follows</code>
                     <code>follows-or-is</code>
                     <code>for</code>
                     <code>function</code>
                     <code>ge</code>
                     <code>get</code>
                     <code>gnode</code>
                     <code>gt</code>
                     <code>idiv</code>
                     <code>if</code>
                     <code>in</code>
                     <code>instance</code>
                     <code>intersect</code>
                     <code>is</code>
                     <code>is-not</code>
                     <code>item</code>
                     <code>jnode</code>
                     <code>key</code>
                     <code>le</code>
                     <code>let</code>
                     <code>lt</code>
                     <code>map</code>
                     <code>member</code>
                     <code>mod</code>
                     <code>namespace</code>
                     <code>namespace-node</code>
                     <code>ne</code>
                     <code>node</code>
                     <code>of</code>
                     <code>or</code>
                     <code>otherwise</code>
                     <code>parent</code>
                     <code>precedes</code>
                     <code>precedes-or-is</code>
                     <code>preceding</code>
                     <code>preceding-or-self</code>
                     <code>preceding-sibling</code>
                     <code>preceding-sibling-or-self</code>
                     <code>processing-instruction</code>
                     <code>record</code>
                     <code>return</code>
                     <code>satisfies</code>
                     <code>schema-attribute</code>
                     <code>schema-element</code>
                     <code>self</code>
                     <code>some</code>
                     <code>text</code>
                     <code>then</code>
                     <code>to</code>
                     <code>treat</code>
                     <code>true</code>
                     <code>union</code>
                     <code>value</code>
                     <nt def="prod-xpath40-BinaryIntegerLiteral">BinaryIntegerLiteral<!--$idref_lang_part = xpath40- --></nt>
                     <nt def="prod-xpath40-DecimalLiteral">DecimalLiteral<!--$idref_lang_part = xpath40- --></nt>
                     <nt def="prod-xpath40-DoubleLiteral">DoubleLiteral<!--$idref_lang_part = xpath40- --></nt>
                     <nt def="prod-xpath40-HexIntegerLiteral">HexIntegerLiteral<!--$idref_lang_part = xpath40- --></nt>
                     <nt def="prod-xpath40-IntegerLiteral">IntegerLiteral<!--$idref_lang_part = xpath40- --></nt>
                     <nt def="prod-xpath40-NCName">NCName<!--$idref_lang_part = xpath40- --></nt>
                     <nt def="prod-xpath40-QName">QName<!--$idref_lang_part = xpath40- --></nt>
                  </termdef>
               </p>
               <p>
                  <termdef id="symbolseparators" term="symbol separators">
                     <termref def="Whitespace">Whitespace</termref> and <nt def="doc-xpath40-Comment">Comments<!--$spec = xpath40--></nt>
          function as <term>symbol separators</term>. 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 <loc xmlns:xlink="http://www.w3.org/1999/xlink"
                          href="#ws-explicit"
                          xlink:type="simple"
                          xlink:show="replace"
                          xlink:actuate="onRequest">/* ws: explicit */</loc>
          annotation in the EBNF, or by the <loc xmlns:xlink="http://www.w3.org/1999/xlink"
                          href="#parse-note-xml-version"
                          xlink:type="simple"
                          xlink:show="replace"
                          xlink:actuate="onRequest">/* xgc: xml-version
            */</loc> annotation.</termdef>
               </p>
               <p>
                  <phrase diff="add" at="2023-05-22">As a consequence of the longest token rule (see <specref ref="lexical-structure"/>), </phrase>
        one or more <termref def="symbolseparators">symbol separators</termref>
        are required between two consecutive terminal symbols
        <var>T</var> and <var>U</var> (where <var>T</var> precedes <var>U</var>) when any of the following is true:
      </p>
               <ulist>
                  <item>
                     <p>
                        <var>T</var> and <var>U</var> are both <termref def="non-delimiting-token">non-delimiting terminal symbols</termref>.</p>
                  </item>
                  <item>
                     <p>
                        <var>T</var> is a QName or an NCName and <var>U</var> is <code nobreak="false">"."</code> or <code nobreak="false">"-"</code>.</p>
                  </item>
                  <item>
                     <p>
                        <var>T</var> is a numeric literal and <var>U</var> is <code nobreak="false">"."</code>, or vice versa.</p>
                  </item>
               </ulist>
            </div3>
            <div3 id="id-eol-handling">
               <head>End-of-Line Handling</head>
               <p role="xpath">The host language must specify whether the XPath 4.0 processor normalizes all
        line breaks on input, before parsing, and if it does so, whether it uses the rules of
          <bibref ref="XML"/> or <bibref ref="XML1.1"/>. </p>
               <note role="xpath" diff="add" at="2023-05-22">
                  <p>XML-based host languages such as XSLT and XSD
      do not normalize line breaks at the XPath level, because it will already have been done by the host XML parser. 
      Use of character or entity references suppresses normalization of line breaks, so
      the string literal <code nobreak="false">&amp;#x0D;</code> written within an XSLT-hosted XPath expression
      represents a string containing a single <char>U+000D</char> character.</p>
               </note>
               <div4 id="id-xml10-eol-handling">
                  <head>XML 1.0 End-of-Line Handling</head>
                  <p>For <bibref ref="XML"/> processing, all of the following must be translated to a single
          <char>U+000A</char>:</p>
                  <olist>
                     <item>
                        <p>the two-character sequence <char>U+000D</char>, <char>U+000A</char>;</p>
                     </item>
                     <item>
                        <p>any <char>U+000D</char> character that is not immediately followed by <char>U+000A</char>.</p>
                     </item>
                  </olist>
               </div4>
               <div4 id="id-xml11-eol-handling">
                  <head>XML 1.1 End-of-Line Handling</head>
                  <p>For <bibref ref="XML1.1"/> processing, all of the following must be translated to a
          single <char>U+000A</char> character:</p>
                  <olist>
                     <item>
                        <p>the two-character sequence <char>U+000D</char>, <char>U+000A</char>;</p>
                     </item>
                     <item>
                        <p>the two-character sequence <char>U+000D</char>, <char>U+0085</char>;</p>
                     </item>
                     <item>
                        <p>the single character <char>U+0085</char>;</p>
                     </item>
                     <item>
                        <p>the single character <char>U+2028</char>;</p>
                     </item>
                     <item>
                        <p>any <char>U+000D</char> character that is not immediately followed by <char>U+000A</char> or <char>U+0085</char>.</p>
                     </item>
                  </olist>
               </div4>
            </div3>
            <div3 id="whitespace-rules">
               <head>Whitespace Rules</head>
               <div4 id="DefaultWhitespaceHandling">
                  <head>Default Whitespace Handling</head>
                  <p>
                     <termdef id="Whitespace" term="whitespace">A <term>whitespace</term> character is any of
            the characters defined by <xnt xmlns:xlink="http://www.w3.org/1999/xlink"
                             href="http://www.w3.org/TR/REC-xml/#NT-S"
                             xlink:type="simple">
              [http://www.w3.org/TR/REC-xml/#NT-S]</xnt>.</termdef>
                  </p>
                  <p>
                     <termdef term="ignorable whitespace" id="IgnorableWhitespace">
                        <term>Ignorable whitespace</term> consists of any <termref def="Whitespace">whitespace</termref> characters that may occur between <termref def="terminal">terminals</termref>, unless these characters occur in the context of a production
            marked with a <loc xmlns:xlink="http://www.w3.org/1999/xlink"
                             href="#ExplicitWhitespaceHandling"
                             xlink:type="simple"
                             xlink:show="replace"
                             xlink:actuate="onRequest"> ws:explicit</loc> annotation, in
            which case they can occur only where explicitly specified (see <specref ref="ExplicitWhitespaceHandling"/>).</termdef> Ignorable whitespace characters are not
          significant to the semantics of an expression. Whitespace is allowed before the first
          terminal and after the last terminal <phrase role="xpath">of an XPath expression</phrase>. Whitespace is allowed between any two <termref def="terminal">terminals</termref>. <nt def="doc-xpath40-Comment">Comments<!--$spec = xpath40--></nt> may also act as
          "whitespace" to prevent two adjacent terminals from being recognized as one. Some
          illustrative examples are as follows:</p>
                  <ulist>
                     <item>
                        <p>
                           <code nobreak="false">foo- foo</code> results in a syntax error. "foo-" would be recognized as a
              QName.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">foo -foo</code> is syntactically equivalent to <code role="parse-test" nobreak="false">foo - foo</code>, two QNames separated by a subtraction
              operator.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">foo(: This is a comment :)- foo</code> is syntactically
              equivalent to <code nobreak="false">foo - foo</code>. This is because the comment prevents the two
              adjacent terminals from being recognized as one.</p>
                     </item>
                     <item>
                        <p>
                           <code role="parse-test" nobreak="false">foo-foo</code> is syntactically equivalent to single QName.
              This is because "-" is a valid character in a QName. When used as an operator after
              the characters of a name, the "-" must be separated from the name, e.g. by using
              whitespace or parentheses.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">10div 3</code> results in a syntax error.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">10 div3</code> also results in a syntax error.</p>
                     </item>
                     <item>
                        <p>
                           <code nobreak="false">10div3</code> also results in a syntax error.</p>
                     </item>
                  </ulist>
               </div4>
               <div4 id="ExplicitWhitespaceHandling">
                  <head>Explicit Whitespace Handling</head>
                  <p>Explicit whitespace notation is specified with the EBNF productions, when it is different
          from the default rules, using the notation shown below. This notation is not inherited. In
          other words, if an EBNF rule is marked as /* ws: explicit */, the notation does not
          automatically apply to all the 'child' EBNF productions of that rule.</p>
                  <glist>
                     <gitem id="ws-explicit">
                        <label>ws: explicit</label>
                        <def>
                           <p>/* ws: explicit */ means that the EBNF notation explicitly notates, with
                  <code nobreak="false">S</code> or otherwise, where <termref def="Whitespace">whitespace
                  characters</termref> are allowed. In productions with the /* ws: explicit */
                  annotation, <specref ref="DefaultWhitespaceHandling"/> does not apply.
		  Comments are not allowed in these productions except where the <nt def="doc-xpath40-Comment">Comment<!--$spec = xpath40--></nt> non-terminal appears.
	      </p>
                        </def>
                     </gitem>
                  </glist>
               </div4>
            </div3>
         </div2>
         <div2 id="id-reserved-fn-names">
            <head>Reserved Function Names</head>
            <changes>
               <change issue="1208" PR="1212" date="2024-05-15">
          New keywords introducing item types, such as <code nobreak="false">record</code>, <code nobreak="false">item</code>, and <code nobreak="false">enum</code>,
            have been added to the list of reserved function names.
      </change>
            </changes>
            <p>The following names are not allowed as function names in an unprefixed form, because they
    can appear, followed by a left parenthesis, at the start of an XPath or XQuery expression that
    is not a function call.</p>
            <p>Names used in <nt def="doc-xpath40-TypeTest">NodeKindTests<!--$spec = xpath40--></nt>:</p>
            <slist>
               <sitem>attribute</sitem>
               <sitem>comment</sitem>
               <sitem>document-node</sitem>
               <sitem>element</sitem>
               <sitem>namespace-node</sitem>
               <sitem>node</sitem>
               <sitem>processing-instruction</sitem>
               <sitem>schema-attribute</sitem>
               <sitem>schema-element</sitem>
               <sitem>text</sitem>
            </slist>
            <p>Names used as syntactic keywords:</p>
            <slist>
               <sitem>array</sitem>
               <sitem>enum</sitem>
               <sitem>fn</sitem>
               <sitem>function</sitem>
               <sitem>gnode</sitem>
               <sitem>get</sitem>
               <sitem>if</sitem>
               <sitem>item</sitem>
               <sitem>jnode</sitem>
               <sitem>map</sitem>
               <sitem>record</sitem>
               <sitem>switch</sitem>
               <sitem>type</sitem>
               <sitem>typeswitch</sitem>
            </slist>
            <note role="xpath">
               <p> Although the keywords <code nobreak="false">switch</code> and <code nobreak="false">typeswitch</code> are not used in
        XPath, they are designated as reserved function names for compatibility with XQuery. </p>
            </note>
            <note>
               <p>As the language evolves in the future, it may become necessary to reserve additional
      names. Furthermore, use of common programming terms like <code nobreak="false">return</code> and
      <code nobreak="false">while</code> as function names may cause confusion even though they are not reserved. 
        The easiest way to avoid problems is to use an explicit namespace prefix in all calls 
        to user-defined functions.</p>
            </note>
         </div2>
         <div2 id="id-precedence-order">
            <head>Precedence Order (Non-Normative)</head>
            <p>The grammar in <specref ref="id-grammar"/> normatively defines built-in precedence among the
      operators of <phrase role="xpath">XPath</phrase>. These operators are summarized here to make clear the order of their
      precedence from lowest to highest. The associativity column indicates the order in which
      operators of equal precedence in an expression are applied (further details below).</p>
            <table role="medium">
               <tbody>
                  <tr>
                     <th rowspan="1" colspan="1">#</th>
                     <th rowspan="1" colspan="1">Operator</th>
                     <th rowspan="1" colspan="1">Associativity</th>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">1</td>
                     <td rowspan="1" colspan="1">
                        <nt def="doc-xpath40-Expr">, (comma)<!--$spec = xpath40--></nt>
                     </td>
                     <td rowspan="1" colspan="1">associative</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">2</td>
                     <td rowspan="1" colspan="1">
                        <phrase role="xpath">
                           <nt def="doc-xpath40-ForExpr">for<!--$spec = xpath40--></nt>,</phrase>
                        <phrase role="xpath">
                           <nt def="doc-xpath40-LetExpr">let<!--$spec = xpath40--></nt>,</phrase>
                        <nt def="doc-xpath40-QuantifiedExpr">some, every<!--$spec = xpath40--></nt>, 
            
            
            <nt def="doc-xpath40-IfExpr">if<!--$spec = xpath40--></nt>
                     </td>
                     <td rowspan="1" colspan="1">NA</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">3</td>
                     <td rowspan="1" colspan="1">
                        <nt def="doc-xpath40-OrExpr">or<!--$spec = xpath40--></nt>
                     </td>
                     <td rowspan="1" colspan="1">associative</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">4</td>
                     <td rowspan="1" colspan="1">
                        <nt def="prod-xpath40-AndExpr">and<!--$spec = xpath40--></nt>
                     </td>
                     <td rowspan="1" colspan="1">associative</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">5</td>
                     <td rowspan="1" colspan="1">
                        <nt def="prod-xpath40-ValueComp">eq, ne, lt, le, gt, ge<!--$spec = xpath40--></nt>, <nt def="prod-xpath40-GeneralComp">=, !=, &lt;,
              &lt;=, &gt;, &gt;=<!--$spec = xpath40--></nt>, <nt def="prod-xpath40-NodeComp">is, is-not, &lt;&lt;, &gt;&gt;, precedes, follows, precedes-or-is, follows-or-is<!--$spec = xpath40--></nt>
                     </td>
                     <td rowspan="1" colspan="1">NA</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">6</td>
                     <td rowspan="1" colspan="1">
                        <nt def="doc-xpath40-OtherwiseExpr">otherwise<!--$spec = xpath40--></nt>
                     </td>
                     <td rowspan="1" colspan="1">associative</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">7</td>
                     <td rowspan="1" colspan="1">
                        <nt def="doc-xpath40-StringConcatExpr">||<!--$spec = xpath40--></nt>
                     </td>
                     <td rowspan="1" colspan="1">associative</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">8</td>
                     <td rowspan="1" colspan="1">
                        <nt def="doc-xpath40-RangeExpr">to<!--$spec = xpath40--></nt>
                     </td>
                     <td rowspan="1" colspan="1">NA</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">9</td>
                     <td rowspan="1" colspan="1">
                        <nt def="doc-xpath40-AdditiveExpr">+, - (binary)<!--$spec = xpath40--></nt>
                     </td>
                     <td rowspan="1" colspan="1">left-to-right</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">10</td>
                     <td rowspan="1" colspan="1">
                        <nt def="prod-xpath40-MultiplicativeExpr">*, div, idiv, mod<!--$spec = xpath40--></nt>
                     </td>
                     <td rowspan="1" colspan="1">left-to-right</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">11</td>
                     <td rowspan="1" colspan="1">
                        <nt def="doc-xpath40-UnionExpr">union, |<!--$spec = xpath40--></nt>
                     </td>
                     <td rowspan="1" colspan="1">associative</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">12</td>
                     <td rowspan="1" colspan="1">
                        <nt def="prod-xpath40-IntersectExceptExpr">intersect, except<!--$spec = xpath40--></nt>
                     </td>
                     <td rowspan="1" colspan="1">left-to-right</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">13</td>
                     <td rowspan="1" colspan="1">
                        <nt def="doc-xpath40-InstanceofExpr">instance of<!--$spec = xpath40--></nt>
                     </td>
                     <td rowspan="1" colspan="1">NA</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">14</td>
                     <td rowspan="1" colspan="1">
                        <nt def="doc-xpath40-TreatExpr">treat as<!--$spec = xpath40--></nt>
                     </td>
                     <td rowspan="1" colspan="1">NA</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">15</td>
                     <td rowspan="1" colspan="1">
                        <nt def="doc-xpath40-CastableExpr">castable as<!--$spec = xpath40--></nt>
                     </td>
                     <td rowspan="1" colspan="1">NA</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">16</td>
                     <td rowspan="1" colspan="1">
                        <nt def="doc-xpath40-CastExpr">cast as<!--$spec = xpath40--></nt>
                     </td>
                     <td rowspan="1" colspan="1">NA</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">17</td>
                     <td rowspan="1" colspan="1">
                        <nt def="doc-xpath40-ArrowExpr">=&gt;, =!&gt;<!--$spec = xpath40--></nt>
                     </td>
                     <td rowspan="1" colspan="1">left-to-right</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">18</td>
                     <td rowspan="1" colspan="1">
                        <nt def="doc-xpath40-UnaryExpr">-, + (unary)<!--$spec = xpath40--></nt>
                     </td>
                     <td rowspan="1" colspan="1">right-to-left</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">19</td>
                     <td rowspan="1" colspan="1">
                        <nt def="doc-xpath40-SimpleMapExpr">!<!--$spec = xpath40--></nt>
                     </td>
                     <td rowspan="1" colspan="1">left-to-right</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">20</td>
                     <td rowspan="1" colspan="1">
                        <nt def="doc-xpath40-PathExpr">/, //<!--$spec = xpath40--></nt>
                     </td>
                     <td rowspan="1" colspan="1">left-to-right</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">21</td>
                     <td rowspan="1" colspan="1">
                        <nt def="doc-xpath40-Predicate">a[b]<!--$spec = xpath40--></nt>, <nt def="doc-xpath40-FilterExprAM">a?[b]<!--$spec = xpath40--></nt>, <nt def="prod-xpath40-Lookup">a?b, a??b<!--$spec = xpath40--></nt>,
            <nt def="doc-xpath40-DynamicFunctionCall">a(b)<!--$spec = xpath40--></nt>
                     </td>
                     <td rowspan="1" colspan="1">left-to-right</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">22</td>
                     <td rowspan="1" colspan="1">
                        <nt def="doc-xpath40-UnaryLookup">? (unary)<!--$spec = xpath40--></nt>
                     </td>
                     <td rowspan="1" colspan="1">NA</td>
                  </tr>
               </tbody>
            </table>
            <p>Entries in the <term>Associativity</term> column have the following meaning (where the symbol <code nobreak="false">⊙</code>
      represents any operator):</p>
            <ulist>
               <item>
                  <p>
                     <term>associative</term> means that the order of evaluation is immaterial: for example <code nobreak="false">a, b, c</code>
      can be evaluated either as <code nobreak="false">(a, b), c</code> or as <code nobreak="false">a, (b, c)</code>, producing the same
      result either way.</p>
               </item>
               <item>
                  <p>
                     <term>NA</term> indicates that it is not possible to write an expression of the form <code nobreak="false">a ⊙ b ⊙ c</code>
      for this particular operator: for example, the grammar does not allow <code nobreak="false">a = b = c</code>.</p>
               </item>
               <item>
                  <p>
                     <term>left-to-right</term> means that for expressions using these operators, 
      <code nobreak="false">a ⊙ b ⊙ c</code> is evaluated as <code nobreak="false">(a ⊙ b) ⊙ c</code>. As a special case, the operators <code nobreak="false">+</code>
      and <code nobreak="false">*</code> are associative provided they are not mixed with other operators of the same precedence.</p>
               </item>
               <item>
                  <p>
                     <term>right-to-left</term> is used only for unary operators, and indicates that <code nobreak="false">⊙ ⊙ a</code>
      is evaluated as <code nobreak="false">⊙ (⊙ a)</code>
                  </p>
               </item>
            </ulist>
            <p>These rules do not constrain the order in which the operands of an expression are evaluated (which might affect
    error behavior). See also <specref ref="errors"/>.</p>
            <note>
               <p>Parentheses can be used to override the operator precedence in the usual way. Square
        brackets in an expression such as <code nobreak="false">A[B]</code>
                  <code nobreak="false">A?[B]</code>or serve two roles: they act as an operator causing B to
        be evaluated once for each item in the value of A, and they act as parentheses enclosing the
        expression B.</p>
            </note>
         </div2>
      </div1>
      <div1 id="id-xp-context-components" role="xpath">
         <head>Context Components</head>
         <p>The tables in this
section describe the scope (range of applicability) of the various
components in a module's static context and dynamic context.</p>
         <div2 id="id-xp-static-context-components">
            <head>Static Context
Components</head>
            <p>The following table describes the components of
the <term>static context</term>. For each component, “global”
indicates that the value of the component applies throughout an XPath
expression, whereas “lexical” indicates that the value of the
component applies only within the subexpression in which it is
defined.</p>
            <table width="60%" border="1" role="small">
               <caption>Static Context Components</caption>
               <tbody>
                  <tr>
                     <th rowspan="1" colspan="1">Component</th>
                     <th rowspan="1" colspan="1">Scope</th>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">XPath 1.0 Compatibility Mode</td>
                     <td rowspan="1" colspan="1">global</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">Statically known namespaces</td>
                     <td rowspan="1" colspan="1">global</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">Default element/type namespace</td>
                     <td rowspan="1" colspan="1">global</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">Default function namespace</td>
                     <td rowspan="1" colspan="1">global</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">In-scope schema types</td>
                     <td rowspan="1" colspan="1">global</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">In-scope element declarations</td>
                     <td rowspan="1" colspan="1">global</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">In-scope attribute declarations</td>
                     <td rowspan="1" colspan="1">global</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">In-scope variables</td>
                     <td rowspan="1" colspan="1">lexical; for-expressions, let-expressions, and quantified expressions can bind new variables</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">Context value static type</td>
                     <td rowspan="1" colspan="1">lexical</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">Statically known function signatures</td>
                     <td rowspan="1" colspan="1">global</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">Statically known collations</td>
                     <td rowspan="1" colspan="1">global</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">Default collation</td>
                     <td rowspan="1" colspan="1">global</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">Base URI</td>
                     <td rowspan="1" colspan="1">global</td>
                  </tr>
               </tbody>
            </table>
         </div2>
         <div2 id="id-xp-evaluation-context-components">
            <head>Dynamic Context Components</head>
            <p>The following table describes how values are assigned to the various components of the
    <term>dynamic context</term>. All these components are initialized by mechanisms
    defined by the host language. For each component, “global” indicates that the value
    of the component remains constant throughout evaluation of the XPath expression,
    whereas “dynamic” indicates that the value of the component can be modified by the
    evaluation of subexpressions.</p>
            <table width="60%" border="1" role="small">
               <caption>Dynamic Context Components</caption>
               <tbody>
                  <tr>
                     <th rowspan="1" colspan="1">Component</th>
                     <th rowspan="1" colspan="1">Scope</th>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">Context value</td>
                     <td rowspan="1" colspan="1">dynamic; changes during evaluation of path expressions and predicates</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">Context position</td>
                     <td rowspan="1" colspan="1">dynamic; changes during evaluation of path expressions and predicates</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">Context size</td>
                     <td rowspan="1" colspan="1">dynamic; changes during evaluation of path expressions and predicates</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">Variable values</td>
                     <td rowspan="1" colspan="1">dynamic; for-expressions, let-expressions, and quantified expressions can bind new variables</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">Current date and time</td>
                     <td rowspan="1" colspan="1">global; must be initialized </td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">Implicit timezone</td>
                     <td rowspan="1" colspan="1">global; must be initialized </td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">Available documents</td>
                     <td rowspan="1" colspan="1">global; must be initialized </td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">Available node collections</td>
                     <td rowspan="1" colspan="1">global; must be initialized </td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">Default collection</td>
                     <td rowspan="1" colspan="1">global; overwriteable by implementation</td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">Available URI collections</td>
                     <td rowspan="1" colspan="1">global; must be initialized </td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">Default URI collection</td>
                     <td rowspan="1" colspan="1">global; overwriteable by implementation</td>
                  </tr>
               </tbody>
            </table>
         </div2>
      </div1>
      <div1 id="id-impl-defined-items">
         <head>Implementation-Defined Items</head>
         <p>The following items in this specification 
  are <termref def="dt-implementation-defined">implementation-defined</termref>:</p>
         <olist>
            <item>
               <p>The version of Unicode that is used to construct expressions.</p>
            </item>
            <item>
               <p>The <termref def="dt-static-collations">statically-known collations</termref>.</p>
            </item>
            <item>
               <p>The <termref def="dt-timezone">implicit timezone</termref>.</p>
            </item>
            <item>
               <p>The circumstances in which <termref def="dt-warning">warnings</termref> are raised, and the ways in which warnings are handled.</p>
            </item>
            <item>
               <p>The method by which errors are reported to the external processing environment.</p>
            </item>
            <item>
               <p>Which version of XML and XML Names (e.g. <bibref ref="XML"/> and <bibref ref="XMLNAMES"/> or <bibref ref="XML1.1"/> and <bibref ref="XMLNAMES11"/>) and which version of XML Schema (e.g. <bibref ref="XMLSchema10"/> or <bibref ref="XMLSchema11"/>) is used for the definitions of primitives such as characters and names, and for the definitions  of operations such as normalization of line endings and normalization of whitespace in attribute values. It is recommended that the latest applicable version be used (even if it is published later than this specification).</p>
            </item>
            <item>
               <p>How XDM instances are created from sources other than an Infoset or PSVI.</p>
            </item>
            <item role="xpath">
               <p>Whether the implementation supports the namespace axis.</p>
            </item>
            <item>
               <p>Whether the type system is based on <bibref ref="XMLSchema10"/> or <bibref ref="XMLSchema11"/>. An implementation that has based its type system on XML Schema 1.0 is not required to support the use of the <code nobreak="false">xs:dateTimeStamp</code> constructor or the use of <code nobreak="false">xs:dateTimeStamp</code> or <code nobreak="false">xs:error</code> as <nt def="prod-xpath40-TypeName">TypeName<!--$spec = xpath40--></nt> in any expression.</p>
            </item>
            <item>
               <p>The signatures of functions provided by the implementation or via an implementation-defined API (see <specref ref="static_context"/>).</p>
            </item>
            <item>
               <p>Any <termref def="dt-environment-variables">environment variables</termref> provided by the implementation.</p>
            </item>
            <item>
               <p>Any rules used for static typing (see <specref ref="id-static-analysis"/>).</p>
            </item>
            <item>
               <p>Any serialization parameters provided by the implementation</p>
            </item>
            <item>
               <p>What error, if any, is returned if an external function's implementation does not return the declared result type (see <specref ref="id-consistency-constraints"/>).</p>
            </item>
         </olist>
         <note>
            <p>Additional <termref def="dt-implementation-defined">implementation-defined</termref> 
  items are listed in <bibref ref="xpath-datamodel-40"/> and <bibref ref="xpath-functions-40"/>.</p>
         </note>
      </div1>
      <div1 id="id-references">
         <head>References</head>
         <div2 id="id-normative-references">
            <head>Normative References</head>
            <blist>
               <bibl xmlns:xlink="http://www.w3.org/1999/xlink"
                     id="RFC2119"
                     key="RFC2119"
                     xlink:type="simple"
                     xlink:show="replace"
                     xlink:actuate="onRequest">S. Bradner.
      <emph>Key Words for use in RFCs to Indicate Requirement Levels.</emph> IETF RFC 2119.
      See <loc href="http://www.ietf.org/rfc/rfc2119.txt"
                       xlink:type="simple"
                       xlink:show="replace"
                       xlink:actuate="onRequest">http://www.ietf.org/rfc/rfc2119.txt</loc>.</bibl>
               <bibl xmlns:xlink="http://www.w3.org/1999/xlink"
                     id="RFC3986"
                     key="RFC3986"
                     xlink:type="simple"
                     xlink:show="replace"
                     xlink:actuate="onRequest">T. Berners-Lee, R. Fielding, and
      L. Masinter.  <emph>Uniform Resource Identifiers (URI): Generic
      Syntax</emph>. IETF RFC 3986.
      See <loc href="http://www.ietf.org/rfc/rfc3986.txt"
                       xlink:type="simple"
                       xlink:show="replace"
                       xlink:actuate="onRequest">http://www.ietf.org/rfc/rfc3986.txt</loc>.</bibl>
               <bibl xmlns:xlink="http://www.w3.org/1999/xlink"
                     id="RFC3987"
                     key="RFC3987"
                     xlink:type="simple"
                     xlink:show="replace"
                     xlink:actuate="onRequest">M. Duerst and M. Suignard.
      <emph>Internationalized Resource Identifiers (IRIs)</emph>.
      IETF RFC 3987. See <loc href="http://www.ietf.org/rfc/rfc3987.txt"
                       xlink:type="simple"
                       xlink:show="replace"
                       xlink:actuate="onRequest">http://www.ietf.org/rfc/rfc3987.txt</loc>.</bibl>
               <bibl xmlns:xlink="http://www.w3.org/1999/xlink"
                     id="ISO10646"
                     key="ISO/IEC 10646"
                     xlink:type="simple"
                     xlink:show="replace"
                     xlink:actuate="onRequest">ISO (International Organization for Standardization).
      <emph>ISO/IEC 10646:2003. Information technology—Universal Multiple-Octet Coded Character Set (UCS)</emph>,
      as, from time to time, amended, replaced by a new edition, or expanded by the addition of new parts.
      [Geneva]: International Organization for Standardization.
      (See <loc href="http://www.iso.org"
                       xlink:type="simple"
                       xlink:show="replace"
                       xlink:actuate="onRequest">http://www.iso.org</loc> for the latest version.)</bibl>
               <bibl xmlns:xlink="http://www.w3.org/1999/xlink"
                     id="Unicode"
                     key="Unicode"
                     xlink:type="simple"
                     xlink:show="replace"
                     xlink:actuate="onRequest">The Unicode Consortium. <emph>The Unicode Standard.</emph>
      Reading, Mass.: Addison-Wesley, 2003, as updated from time to time by the publication of new versions.
      See <loc href="http://www.unicode.org/standard/versions/"
                       xlink:type="simple"
                       xlink:show="replace"
                       xlink:actuate="onRequest">http://www.unicode.org/standard/versions/</loc>
      for the latest version and additional information on versions of the standard and of the Unicode Character Database.
      The version of Unicode to be used is <termref def="dt-implementation-defined">implementation-defined</termref>,
      but implementations are recommended to use the latest Unicode version.</bibl>
               <bibl xmlns:xlink="http://www.w3.org/1999/xlink"
                     id="XML"
                     key="XML 1.0"
                     xlink:type="simple"
                     xlink:show="replace"
                     xlink:actuate="onRequest">World Wide Web Consortium.
      <emph>Extensible Markup Language (XML) 1.0.</emph>
      W3C Recommendation.
      See <loc href="http://www.w3.org/TR/REC-xml/"
                       xlink:type="simple"
                       xlink:show="replace"
                       xlink:actuate="onRequest">http://www.w3.org/TR/REC-xml/</loc>.
      The edition of XML 1.0 must be no earlier than the Third Edition;
      the edition used is <termref def="dt-implementation-defined">implementation-defined</termref>,
      but we recommend that implementations use the latest version.
</bibl>
               <bibl xmlns:xlink="http://www.w3.org/1999/xlink"
                     id="XML1.1"
                     key="XML 1.1"
                     xlink:type="simple"
                     xlink:show="replace"
                     xlink:actuate="onRequest">World Wide Web Consortium.
      <emph>Extensible Markup Language (XML) 1.1.</emph>
      W3C Recommendation.
      See <loc href="http://www.w3.org/TR/xml11/"
                       xlink:type="simple"
                       xlink:show="replace"
                       xlink:actuate="onRequest">http://www.w3.org/TR/xml11/</loc>
               </bibl>
               <bibl xmlns:xlink="http://www.w3.org/1999/xlink"
                     id="XMLBASE"
                     key="XML Base"
                     xlink:type="simple"
                     xlink:show="replace"
                     xlink:actuate="onRequest">World Wide Web Consortium.
      <emph>XML Base.</emph> W3C Recommendation. See
      <loc href="http://www.w3.org/TR/xmlbase/"
                       xlink:type="simple"
                       xlink:show="replace"
                       xlink:actuate="onRequest">http://www.w3.org/TR/xmlbase/</loc>
               </bibl>
               <bibl xmlns:xlink="http://www.w3.org/1999/xlink"
                     id="XMLNAMES"
                     key="XML Names"
                     xlink:type="simple"
                     xlink:show="replace"
                     xlink:actuate="onRequest">World Wide Web Consortium.
      <emph>Namespaces in XML.</emph> W3C Recommendation. See
      <loc href="http://www.w3.org/TR/REC-xml-names/"
                       xlink:type="simple"
                       xlink:show="replace"
                       xlink:actuate="onRequest">http://www.w3.org/TR/REC-xml-names/</loc>
               </bibl>
               <bibl xmlns:xlink="http://www.w3.org/1999/xlink"
                     id="XMLNAMES11"
                     key="XML Names 1.1"
                     xlink:type="simple"
                     xlink:show="replace"
                     xlink:actuate="onRequest">World Wide Web Consortium.
      <emph>Namespaces in XML 1.1.</emph> W3C Recommendation. See
      <loc href="http://www.w3.org/TR/xml-names11/"
                       xlink:type="simple"
                       xlink:show="replace"
                       xlink:actuate="onRequest">http://www.w3.org/TR/xml-names11/</loc>
               </bibl>
               <bibl xmlns:xlink="http://www.w3.org/1999/xlink"
                     id="XMLID"
                     key="XML ID"
                     xlink:type="simple"
                     xlink:show="replace"
                     xlink:actuate="onRequest">World Wide Web Consortium. <emph>xml:id Version 1.0.</emph>
      W3C Recommendation. See <loc href="http://www.w3.org/TR/xml-id/"
                       xlink:type="simple"
                       xlink:show="replace"
                       xlink:actuate="onRequest">http://www.w3.org/TR/xml-id/</loc>
               </bibl>
               <bibl xmlns:xlink="http://www.w3.org/1999/xlink"
                     id="XMLSchema10"
                     key="XML Schema 1.0"
                     xlink:type="simple"
                     xlink:show="replace"
                     xlink:actuate="onRequest">World Wide Web Consortium.
      <emph>XML Schema, Parts 0, 1, and 2 (Second Edition)</emph>. W3C Recommendation, 28 October 2004.
      See <loc href="http://www.w3.org/TR/xmlschema-0/"
                       xlink:type="simple"
                       xlink:show="replace"
                       xlink:actuate="onRequest">http://www.w3.org/TR/xmlschema-0/</loc>,
      <loc href="http://www.w3.org/TR/xmlschema-1/"
                       id="schema1"
                       xlink:type="simple"
                       xlink:show="replace"
                       xlink:actuate="onRequest">http://www.w3.org/TR/xmlschema-1/</loc>,
      and <loc href="http://www.w3.org/TR/xmlschema-2/"
                       id="schema2"
                       xlink:type="simple"
                       xlink:show="replace"
                       xlink:actuate="onRequest">http://www.w3.org/TR/xmlschema-2/</loc>.</bibl>
               <bibl xmlns:xlink="http://www.w3.org/1999/xlink"
                     id="XMLSchema11"
                     key="XML Schema 1.1"
                     xlink:type="simple"
                     xlink:show="replace"
                     xlink:actuate="onRequest">World Wide Web Consortium.
      <emph>XML Schema, Parts 1, and 2</emph>. W3C Recommendation 5 April 2012.
      See <loc href="http://www.w3.org/TR/xmlschema11-1/"
                       id="schema1-11"
                       xlink:type="simple"
                       xlink:show="replace"
                       xlink:actuate="onRequest">http://www.w3.org/TR/xmlschema11-1/</loc>,
      and <loc href="http://www.w3.org/TR/xmlschema11-2/"
                       id="schema2-11"
                       xlink:type="simple"
                       xlink:show="replace"
                       xlink:actuate="onRequest">http://www.w3.org/TR/xmlschema11-2/</loc>.</bibl>
               <bibl xmlns:xlink="http://www.w3.org/1999/xlink"
                     id="xpath-datamodel-40"
                     key="XDM 4.0"
                     xlink:type="simple"
                     xlink:show="replace"
                     xlink:actuate="onRequest"/>
               <bibl xmlns:xlink="http://www.w3.org/1999/xlink"
                     id="xpath-functions-40"
                     key="Functions and Operators 4.0"
                     xlink:type="simple"
                     xlink:show="replace"
                     xlink:actuate="onRequest"/>
               <bibl xmlns:xlink="http://www.w3.org/1999/xlink"
                     id="xpath-40"
                     key="XPath 4.0"
                     xlink:type="simple"
                     xlink:show="replace"
                     xlink:actuate="onRequest"/>
               <bibl xmlns:xlink="http://www.w3.org/1999/xlink"
                     id="xslt-xquery-serialization-40"
                     key="Serialization 4.0"
                     xlink:type="simple"
                     xlink:show="replace"
                     xlink:actuate="onRequest"/>
               <!--<bibl id="xquery-update-30" key="XQuery Update Facility 3.0" role="xquery"/>-->
            </blist>
         </div2>
         <div2 id="id-non-normative-references">
            <head>Non-normative References</head>
            <blist>
               <bibl xmlns:xlink="http://www.w3.org/1999/xlink"
                     id="xquery-31"
                     key="XQuery 3.1"
                     role="xpath"
                     xlink:type="simple"
                     xlink:show="replace"
                     xlink:actuate="onRequest"/>
               <bibl xmlns:xlink="http://www.w3.org/1999/xlink"
                     id="xquery-semantics"
                     key="XQuery 1.0 and XPath 2.0 Formal Semantics"
                     xlink:type="simple"
                     xlink:show="replace"
                     xlink:actuate="onRequest"/>
               <!--<bibl id="xqueryx-31" key="XQueryX 3.1" role="xquery"/>-->
               <bibl xmlns:xlink="http://www.w3.org/1999/xlink"
                     id="xslt-40"
                     key="XSLT 4.0"
                     xlink:type="simple"
                     xlink:show="replace"
                     xlink:actuate="onRequest"/>
               <bibl xmlns:xlink="http://www.w3.org/1999/xlink"
                     id="XINFO"
                     key="XML Infoset"
                     xlink:type="simple"
                     xlink:show="replace"
                     xlink:actuate="onRequest">World Wide Web
Consortium. <emph>XML Information Set (Second Edition).</emph> W3C Recommendation 4 February 2004. See
<loc href="http://www.w3.org/TR/xml-infoset/"
                       xlink:type="simple"
                       xlink:show="replace"
                       xlink:actuate="onRequest">http://www.w3.org/TR/xml-infoset/</loc>
               </bibl>
               <bibl xmlns:xlink="http://www.w3.org/1999/xlink"
                     key="XPath 1.0"
                     id="xpath"
                     xlink:type="simple"
                     xlink:show="replace"
                     xlink:actuate="onRequest"/>
               <bibl xmlns:xlink="http://www.w3.org/1999/xlink"
                     key="XPath 2.0"
                     id="xpath20"
                     xlink:type="simple"
                     xlink:show="replace"
                     xlink:actuate="onRequest"/>
               <bibl xmlns:xlink="http://www.w3.org/1999/xlink"
                     key="XPath 3.0"
                     id="xpath-30"
                     xlink:type="simple"
                     xlink:show="replace"
                     xlink:actuate="onRequest"/>
               <bibl xmlns:xlink="http://www.w3.org/1999/xlink"
                     id="XPTR"
                     key="XPointer"
                     xlink:type="simple"
                     xlink:show="replace"
                     xlink:actuate="onRequest">World Wide Web Consortium. <emph>XML
Pointer Language (XPointer).</emph> W3C Last Call Working Draft 8 January 2001.
See <loc href="http://www.w3.org/TR/WD-xptr"
                       xlink:type="simple"
                       xlink:show="replace"
                       xlink:actuate="onRequest">http://www.w3.org/TR/WD-xptr</loc>
               </bibl>
            </blist>
         </div2>
         <div2 id="id-background-material">
            <head>Background Material</head>
            <blist>
               <bibl xmlns:xlink="http://www.w3.org/1999/xlink"
                     id="CHARMOD"
                     key="Character Model"
                     xlink:type="simple"
                     xlink:show="replace"
                     xlink:actuate="onRequest">World Wide Web Consortium.
<emph>Character Model for the World Wide Web.</emph> W3C Working
Draft. See <loc href="http://www.w3.org/TR/charmod/"
                       xlink:type="simple"
                       xlink:show="replace"
                       xlink:actuate="onRequest">http://www.w3.org/TR/charmod/</loc>.</bibl>
               <bibl xmlns:xlink="http://www.w3.org/1999/xlink"
                     id="xslt"
                     key="XSL Transformations (XSLT) Version 1.0"
                     xlink:type="simple"
                     xlink:show="replace"
                     xlink:actuate="onRequest"/>
            </blist>
         </div2>
      </div1>
      <div1 id="id-errors">
         <head>Error Conditions</head>
         <note>
            <p>Historically, codes starting "XP" were for XPath errors, "XQ" for XQuery errors.
   This was followed by "ST" for static errors, "TY" for type errors, or "DY" for dynamic
   errors. Over time, some errors have been reclassified, but the error codes
   have been retained for compatibility reasons. Applications should therefore attach no
   significance to the choice of codes.</p>
         </note>
         <error-list>
            <error spec="XP" code="0001" class="ST" type="static">
               <p> It is a <termref def="dt-static-error">static error</termref> if analysis of an
            expression relies on some component of the <termref def="dt-static-context">static
               context</termref> that <phrase diff="del">has not been assigned a
               value</phrase>
                  <phrase diff="add">is <xtermref spec="DM40" ref="dt-absent"/>
                  </phrase>.</p>
            </error>
            <error spec="XP" code="0002" class="DY" type="type">
               <p>It is a <termref def="dt-type-error">type error</termref> if evaluation of an
            expression relies on some part of the <termref def="dt-dynamic-context">dynamic
               context</termref> that is <xtermref spec="DM40" ref="dt-absent"/>.</p>
               <note>
                  <p>In version 4.0 this has been reclassified as a type error rather than
         a dynamic error. This change allows a processor to report the error during static
         analysis where possible; for example if the body of a user-defined
         function is written as <code nobreak="false">fn($x) { @code }</code>.
         The error code is prefixed <code nobreak="false">XPDY</code> rather than <code nobreak="false">XPTY</code>
         for backwards compatibility reasons.</p>
               </note>
            </error>
            <error spec="XP" code="0003" class="ST" type="static">
               <p> It is a <termref def="dt-static-error">static error</termref> if an expression is not a
            valid instance of the grammar defined in <specref ref="id-grammar"/>.</p>
            </error>
            <error spec="XP" code="0004" class="TY" type="type">
               <p>It is a <termref def="dt-type-error">type error</termref> if, during the <termref def="dt-static-analysis">static analysis phase</termref>, an expression is found to
            have a <termref def="dt-static-type">static type</termref> that is not appropriate for
            the context in which the expression occurs, or during the <termref def="dt-dynamic-evaluation">dynamic evaluation phase</termref>, the <termref def="dt-dynamic-type">dynamic type</termref> of a value does not match a required
            type as specified by the matching rules in <specref ref="id-sequencetype-matching"/>.</p>
            </error>
            <!--<error spec="XP" code="0005" class="ST" type="static">
         <p> During the analysis phase, it is a <termref def="dt-static-error">static
               error</termref> if the <termref def="dt-static-type">static type</termref> assigned
            to an expression other than the expression <code>()</code> or <code>data(())</code> is
               <code>empty-sequence()</code>.</p>
      </error>-->
            <error spec="XP" code="0006" class="TY" type="type">
               <p>During the analysis phase, an expression is classified as <termref def="dt-implausible"/>
            if the inferred <termref def="dt-static-type">static type</termref>
                  <var>S</var> and
            the required type <var>R</var> are substantively disjoint; more specifically, if neither
            of the types is a subtype of the other, and if the only values
            that are instances of both types are one or more of: the empty sequence, the empty map, 
            and the empty array.</p>
            </error>
            <error spec="XP" code="0008" class="ST" type="static">
               <p> It is a <termref def="dt-static-error">static error</termref> if an expression refers
            to an element name, attribute name, schema type name, or variable name
            that is not defined in the <termref def="dt-static-context">static context</termref>,
            except for an ElementName in an <nt def="doc-xpath40-ElementNodeType"><!--$spec = xpath40--></nt> or an
            AttributeName in an <nt def="doc-xpath40-AttributeNodeType"><!--$spec = xpath40--></nt>.</p>
            </error>
            <error spec="XP" code="0010" class="ST" type="static" role="xpath">
               <p> An implementation that does not support the namespace axis must raise a <termref def="dt-static-error">static error</termref> if it encounters a reference to the
            namespace axis and XPath 1.0 compatibility mode is <code nobreak="false">false</code>. </p>
            </error>
            <!--
<error spec="XQ" role="xquery" code="0014" class="ST" type="static">
<p>(Not currently used.)</p>
</error>
-->
            <!--
<error spec="XQ" role="xquery" code="0015" class="ST" type="static">
<p>(Not currently used.)</p>
</error>
-->
            <!--<error spec="XQ" role="xquery" code="0016" class="ST" type="static">
         <p>An implementation that does not support the Module Feature raises a <termref
               def="dt-static-error">static error</termref> if it encounters a <termref
               def="dt-module-declaration">module declaration</termref> or a <termref
               def="dt-module-import">module import</termref>.</p>
      </error>-->
            <error spec="XP" code="0017" class="ST" type="static">
               <p>It is a <termref def="dt-static-error"/> if the <termref def="dt-expanded-qname"/>
            and number of arguments in a static function call do not match the name and
            <termref def="dt-arity-range"/> of a <termref def="dt-function-definition"/> in the
            <termref def="dt-static-context"/>, or if an argument keyword in the function call
            does not match a parameter name in that function definition, or if two arguments
            in the function call bind to the same parameter in the function definition.</p>
            </error>
            <error spec="XP" code="0018" class="TY" type="type">
               <p>It is a <termref def="dt-type-error">type error</termref> if the result of a path
            operator contains both nodes and non-nodes.</p>
            </error>
            <error spec="XP" code="0019" class="TY" type="type">
               <p> It is a <termref def="dt-type-error">type error</termref> if <code nobreak="false">E1</code> in a path
            expression <code nobreak="false">E1/E2</code> does not evaluate to a sequence of nodes.</p>
            </error>
            <error spec="XP" code="0020" class="TY" type="type">
               <p> It is a <termref def="dt-type-error">type error</termref> if, in an axis step, the
            context item is not a node.</p>
            </error>
            <error spec="XP" code="0021" class="ST" type="static">
               <p> It is a <termref def="dt-static-error">static error</termref> if two fields in a record declaration
            have the same name.</p>
            </error>
            <error spec="XP" code="0023" class="ST" type="static">
               <p> It is a <termref def="dt-static-error">static error</termref> if a recursive record type
            cannot be instantiated (typically because it contains a self-reference that is neither optional
            nor emptiable). Processors are not required to detect this error.</p>
            </error>
            <error spec="XQ" code="0024" class="TY" type="type">
               <p> It is a <termref def="dt-type-error">type error</termref> if the content sequence in an
            element constructor contains an attribute node following a node that is not an attribute
            node.</p>
            </error>
            <error spec="XQ" code="0025" class="DY" type="dynamic">
               <p> It is a <termref def="dt-dynamic-error">dynamic error</termref> if any attribute of a
            constructed element does not have a name that is distinct from the names of all other
            attributes of the constructed element.</p>
            </error>
            <error spec="XQ" code="0026" class="DY" type="dynamic">
               <p> It is a <termref def="dt-dynamic-error">dynamic error</termref> if the result of the
            content expression of a computed processing instruction constructor contains the string
               <code nobreak="false">"?&gt;"</code>.</p>
            </error>
            <!--
<error spec="XQ" role="xquery" code="0028" class="TY" type="type">
<p>
(Not currently used.)</p>
</error>
-->
            <!--
<error spec="XQ" code="0029" class="DY" type="dynamic" role="xquery">
<p>(Not currently used.)</p>
</error>
-->
            <error spec="XQ" code="0033" class="ST" type="static">
               <p>It is a <termref def="dt-static-error">static error</termref> if a module contains
            multiple bindings for the same namespace prefix.</p>
            </error>
            <!--
<error spec="XQ" role="xquery" code="0036" class="ST" type="type">
          <p diff="add">(Not currently used.)</p>
          <p diff="del">
            It is a <termref def="dt-static-error">static error</termref>
            to import a module if the
            <termref def="dt-issd">in-scope schema definitions</termref>
            of the importing module do not include all of the following:
          </p>
          <olist diff="del">
             <item>
                <p>An <termref def="dt-is-types">in-scope schema type</termref>
                   for each type name that appears:
                </p>
                <olist>
                   <item>
                      <p>in the type of a variable that is declared in the imported module
                         and referenced in the importing module, OR
                      </p>
                   </item><item>
                      <p>in a parameter-type or result-type of a function that is declared
                         in the imported module and referenced in the importing module.
                      </p>
                   </item>
                </olist>
             </item><item>
                <p>An <termref def="dt-is-elems">in-scope element declaration</termref>
                   for each element-name <code>EN</code> such that:
                </p>
                <olist>
                   <item>
                      <p><code>schema-element(EN)</code> appears in the declared
                         type of a variable
                         in the imported module, and that variable is referenced
                         in the importing module, OR
                      </p>
                   </item><item>
                      <p><code>schema-element(EN)</code> appears in a parameter-type or
                         result-type of a function declared in the imported module, and
                         that function is referenced in the importing module.
                      </p>
                   </item>
                </olist>
             </item><item>
                <p>An <termref def="dt-is-attrs">in-scope attribute declaration</termref>
                   for each attribute-name <code>AN</code> such that:
                </p>
                <olist>
                   <item>
                      <p><code>schema-attribute(AN)</code> appears in the declared
                         type of a variable
                         in the imported module, and that variable is referenced
                         in the importing module, OR
                      </p>
                   </item><item>
                      <p><code>schema-attribute(AN)</code> appears in a parameter-type
                         or result-type
                         of a function declared in the imported module, and that function
                         is referenced in the importing module.
                      </p>
                   </item>
                </olist>
             </item>
          </olist>
</error>
-->
            <!--
<error spec="XQ" role="xquery" code="0037" class="ST" type="static">
<p>(Not currently used.)</p>
</error>
-->
            <error spec="XQ" code="0039" class="ST" type="static">
               <p> It is a <termref def="dt-static-error">static error</termref> for 
            <phrase diff="add">an inline function expression</phrase> to have more than one
            parameter with the same name. </p>
            </error>
            <error spec="XQ" code="0041" class="DY" type="dynamic">
               <p> It is a <termref def="dt-dynamic-error">dynamic error</termref> if the value of the
            name expression in a computed processing instruction constructor cannot be cast to the
            type <code nobreak="false">xs:NCName</code>.</p>
            </error>
            <!--
<error spec="XQ" role="xquery" code="0042" class="ST" type="static">
<p>
(Not currently used.)</p>
</error>
-->
            <!--
<error spec="XQ" role="xquery" code="0043" class="ST" type="static">
<p>
(Not currently used.)</p>
</error>
-->
            <error spec="XQ" code="0044" class="DY" type="dynamic"><!-- <change diff="chg" at="XQ.E19"> -->
               <p>It is a <termref def="dt-dynamic-error">dynamic error</termref> the node-name of a node
            constructed by a computed attribute constructor has any of the following properties: </p>
               <ulist>
                  <item>
                     <p>Its namespace prefix is <code nobreak="false">xmlns</code>. </p>
                  </item>
                  <item>
                     <p>It has no namespace prefix and its local name is <code nobreak="false">xmlns</code>. </p>
                  </item>
                  <item>
                     <p>Its namespace URI is <code nobreak="false">http://www.w3.org/2000/xmlns/</code>. </p>
                  </item>
                  <item>
                     <p>Its namespace prefix is <code nobreak="false">xml</code> and its namespace URI is not
                     <code nobreak="false">http://www.w3.org/XML/1998/namespace</code>. </p>
                  </item>
                  <item>
                     <p>Its namespace prefix is other than <code nobreak="false">xml</code> and its namespace URI is
                     <code nobreak="false">http://www.w3.org/XML/1998/namespace</code>. </p>
                  </item>
               </ulist>
               <!-- </change> -->
            </error>
            <error spec="XQ" code="0046" class="ST" type="static">
               <p>An implementation <phrase role="xpath">MAY</phrase> raise a <termref def="dt-static-error">static
               error</termref> if the value of a <nt def="prod-xpath40-BracedURILiteral">BracedURILiteral<!--$spec = xpath40--></nt> is
            of nonzero length and is <phrase diff="del">not in the lexical space of
                  <code nobreak="false">xs:anyURI</code>
                  </phrase>
                  <phrase diff="add">neither an absolute URI nor a
               relative URI</phrase>.</p>
            </error>
            <error spec="XP" code="0050" class="DY" type="type">
               <p>It is a <termref def="dt-type-error"/> if the <termref def="dt-dynamic-type"/> of the operand of a <code nobreak="false">treat</code>
            expression does not match the <termref def="dt-sequence-type"/>
            designated by the <code nobreak="false">treat</code> expression.</p>
               <note>
                  <p>This error might also be raised by a
            path expression beginning with <code nobreak="false">/</code> or <code nobreak="false">//</code> if the context node
            is not in a tree that is rooted at a document node. This is because a leading
               <code nobreak="false">/</code> or <code nobreak="false">//</code> in a path expression is an abbreviation for an
            initial step that includes the clause <code nobreak="false">treat as document-node()</code>.</p>
               </note>
            </error>
            <error spec="XP" code="0051" class="ST" type="static">
               <p>It is a <termref def="dt-static-error">static error</termref> if an <termref def="dt-expanded-qname"/> used as an <nt def="doc-xpath40-ItemType">ItemType<!--$spec = xpath40--></nt>
               in a <nt def="doc-xpath40-SequenceType"><!--$spec = xpath40--></nt> is not defined
            in the <termref def="dt-static-context"/> either as a <termref def="dt-named-item-type"/>
            in the <termref def="dt-in-scope-named-item-types"/>,
            or as a <termref def="dt-generalized-atomic-type"/>
            in the <termref def="dt-is-types"/>.</p>
            </error>
            <error spec="XQ" code="0052" class="ST" type="static">
               <p>The type named in a cast or castable expression must be the name of a type defined in the <termref def="dt-is-types">in-scope
               schema types</termref>, and the<phrase diff="del" at="2015-07-07">
                     <code nobreak="false">{variety}</code> of the</phrase> type must be
               <code nobreak="false">simple</code>.</p>
            </error>
            <!--
<error spec="XQ" role="xquery" code="0053" class="ST" type="static">
<p>
(Not currently used.)</p>
</error>
-->
            <!--
<error spec="XQ" code="0056" class="ST" type="static" role="xquery">
<p>
(Not currently used.)</p>
</error>
-->
            <!--<error spec="XQ" code="0060" class="ST" type="static" role="xquery">
         <p> It is a <termref def="dt-static-error">static error</termref> if the name of a function
            in a function declaration is not in a namespace (<termref def="dt-expanded-qname"
               >expanded QName</termref> has a null namespace URI).</p>
      </error>-->
            <!--
<error spec="XQ" role="xquery" code="0062" class="DY" type="dynamic">
<p>(Not currently used.)</p>
</error>
-->
            <!--
<error spec="XQ" code="0063" class="ST" type="static" role="xquery">
<p>
(Not currently used.)</p>
</error>
-->
            <error spec="XQ" code="0064" class="DY" type="dynamic">
               <p> It is a <termref def="dt-dynamic-error">dynamic error</termref> if the value of the
            name expression in a computed processing instruction constructor is equal to
            <code nobreak="false">XML</code> (in any combination of upper and lower case).</p>
            </error>
            <error spec="XQ" code="0070" class="ST" type="static" diff="chg">
               <p>A namespace declaration must not define a binding for the prefix <code nobreak="false">xml</code>
         or <code nobreak="false">xmlns</code>, nor for the URI <code nobreak="false">http://www.w3.org/XML/1998/namespace</code>
         or <code nobreak="false">http://www.w3.org/2000/xmlns/</code>.</p>
            </error>
            <error spec="XQ" code="0072" class="DY" type="dynamic">
               <p> It is a <termref def="dt-dynamic-error">dynamic error</termref> if the result of the
            content expression of a computed comment constructor contains two adjacent hyphens or
            ends with a hyphen.</p>
            </error>
            <!--
<error spec="XQ" role="xquery" code="0073" class="ST" type="static">
<p diff="chg" at="XQ.E8">(Not currently used.)</p>
</error>
-->
            <error spec="XQ" code="0074" class="DY" type="dynamic">
               <p> It is a <termref def="dt-dynamic-error">dynamic error</termref> if the value of the
            name expression in a computed element or attribute constructor cannot be converted to an
               <termref def="dt-expanded-qname">expanded QName</termref> (for example, because it
            contains a namespace prefix not found in <termref def="dt-static-namespaces">statically
               known namespaces</termref>.)</p>
            </error>
            <!--
<error spec="XQ" role="xquery" code="0077" class="ST" type="static">
<p>
(Not currently used.)</p>
</error>
-->
            <!--
<error spec="XQ" role="xquery" code="0078" class="ST" type="static">
<p>
(Not currently used.)</p>
</error>
-->
            <error spec="XP" code="0080" class="ST" type="static">
               <p>It is a <termref def="dt-static-error">static error</termref> if the target type of a
               <code nobreak="false">cast</code> or <code nobreak="false">castable</code> expression is
               <code nobreak="false">xs:NOTATION</code>, <phrase diff="add">
                     <code nobreak="false">xs:anySimpleType</code>,</phrase> or
               <code nobreak="false">xs:anyAtomicType</code>.</p>
            </error>
            <error spec="XP" code="0081" class="ST" type="static">
               <p> It is a <termref def="dt-static-error">static error</termref> if a QName used in
               <phrase role="xpath">an expression</phrase>
            contains a namespace prefix that cannot be expanded into a namespace URI by using the
               <termref def="dt-static-namespaces">statically known namespaces</termref>.</p>
            </error>
            <!--
<error spec="XQ" role="xquery" code="0082" class="ST" type="static">
<p>(Not currently used.)</p>
</error>
-->
            <!--
<error spec="XP" code="0083" class="ST" type="static">
<p>
(Not currently used.)</p>
</error>
-->
            <error spec="XQ" code="0086" class="TY" type="type">
               <p> It is a <termref def="dt-type-error">type error</termref> if the typed value of a
            copied  attribute node is <termref def="dt-namespace-sensitive">namespace-sensitive</termref> .</p>
            </error>
            <error spec="XQ" role="xpath" code="0089" class="ST" type="static">
               <p> It is a <termref def="dt-static-error">static error</termref> if a variable bound in a
            <code nobreak="false">for</code> expression, and its
            associated positional variable, do not have distinct names (<termref def="dt-expanded-qname">expanded QNames</termref>).</p>
            </error>
            <error spec="XQ" code="0091" class="DY" type="dynamic">
               <p>An implementation <termref def="may">MAY</termref> raise a <termref def="dt-dynamic-error">dynamic error</termref> if an <code nobreak="false">xml:id</code> error, as
            defined in <bibref ref="XMLID"/>, is encountered during construction of an attribute
            named <code nobreak="false">xml:id</code>.</p>
            </error>
            <error spec="XQ" code="0092" class="DY" type="dynamic">
               <p>An implementation <termref def="may">MAY</termref> raise a <termref def="dt-dynamic-error">dynamic error</termref> if a constructed attribute named
               <code nobreak="false">xml:space</code> has a value other than <code nobreak="false">preserve</code> or
               <code nobreak="false">default</code>.</p>
            </error>
            <!--
<error spec="XQ" role="xquery" code="0093" class="ST" type="static">
<p>
It is a <termref def="dt-static-error">static
error</termref> to import a module M<sub>1</sub> if there exists a sequence of modules M<sub>1</sub> ... M<sub>i</sub> ... M<sub>1</sub> such that each module <termref def="dt-module-directly-depends">directly depends</termref> on the next module in the sequence (informally, if M<sub>1</sub> depends on itself through some chain of module dependencies.)</p>
</error>
-->
            <!--
<error spec="XQ" role="xquery" code="0095" class="DY" type="dynamic">
<p>
In the <code>group by</code> clause of a FLWOR expression, it is a <termref def="dt-dynamic-error">dynamic error</termref>
if the value bound to a grouping  variable consists of a sequence of more than one item.</p>
</error> -->
            <!-- ################ -->
            <error spec="XQ" code="0096" class="DY" type="dynamic"><!-- 	   <change diff="chg" at="XQ.E19"> -->
               <p>It is a <termref def="dt-dynamic-error">dynamic error</termref>
                  <phrase diff="add">if</phrase> the node-name of a node constructed by a computed element
            constructor has any of the following properties: </p>
               <ulist>
                  <item>
                     <p>Its namespace prefix is <code nobreak="false">xmlns</code>. </p>
                  </item>
                  <item>
                     <p>Its namespace URI is <code nobreak="false">http://www.w3.org/2000/xmlns/</code>. </p>
                  </item>
                  <item>
                     <p>Its namespace prefix is <code nobreak="false">xml</code> and its namespace URI is not
                     <code nobreak="false">http://www.w3.org/XML/1998/namespace</code>. </p>
                  </item>
                  <item>
                     <p>Its namespace prefix is other than <code nobreak="false">xml</code> and its namespace URI is
                     <code nobreak="false">http://www.w3.org/XML/1998/namespace</code>. </p>
                  </item>
               </ulist>
               <!--	    </change>          -->
            </error>
            <!--
<error  spec="XQ" role="xquery" code="0100" class="ST" type="static">
<p>(Not currently used.)
</p>
  <ulist>

  <item><p><termref
  def="id-static-decimal-separator">decimal-separator</termref></p></item>
  <item><p><termref
    def="id-static-decimal-format-grouping-separator">grouping-separator</termref></p></item>

    <item><p><termref
    def="id-static-decimal-format-percent">percent-sign</termref></p></item>

    <item><p><termref
    def="id-static-decimal-format-per-mille">per-mille-sign</termref></p></item>

    <item><p><termref
		 def="id-static-decimal-format-zero-digit">zero-digit</termref></p></item>

    <item><p><termref def="id-static-decimal-format-digit">digit-sign</termref></p></item>
    <item><p><termref def="id-static-decimal-format-pattern-separator">pattern-separator-sign</termref></p></item>
  </ulist>
</error>
-->
            <error spec="XQ" code="0101" class="DY" type="dynamic">
               <p>An error is raised if a computed namespace constructor attempts to do any of the
            following:</p>
               <ulist>
                  <item>
                     <p>Bind the prefix <code nobreak="false">xml</code> to some namespace URI other than
                     <code nobreak="false">http://www.w3.org/XML/1998/namespace</code>. </p>
                  </item>
                  <item>
                     <p>Bind a prefix other than <code nobreak="false">xml</code> to the namespace URI
                     <code nobreak="false">http://www.w3.org/XML/1998/namespace</code>. </p>
                  </item>
                  <item>
                     <p>Bind the prefix <code nobreak="false">xmlns</code> to any namespace URI. </p>
                  </item>
                  <item>
                     <p>Bind a prefix to the namespace URI <code nobreak="false">http://www.w3.org/2000/xmlns/</code>.
               </p>
                  </item>
                  <item>
                     <p diff="add">Bind any prefix (including the empty prefix) to a zero-length namespace
                  URI.</p>
                  </item>
               </ulist>
            </error>
            <error spec="XQ" code="0102" class="DY" type="type">
               <p> In an element constructor, if two or more namespace bindings in the in-scope bindings
            would have the same prefix, then an error is raised if they have different URIs; if they
            would have the same prefix and URI, duplicate bindings are ignored. </p>
               <p> If the name of an element in an element constructor is in no namespace, creating a
            default namespace for that element using a computed namespace constructor is an error.
         </p>
            </error>
            <error spec="XQ" code="0105" class="TY" type="type">
               <p> It is a <termref def="dt-type-error">type error</termref> if the content sequence of an
            element or document constructor contains a function item.</p>
            </error>
            <!-- ################ 0112 -->
            <error spec="XP" code="0117" class="TY" type="type"><!-- Bug 28588 -->
               <p>When applying the <termref def="dt-coercion-rules"/>, if an item is of type <code nobreak="false">xs:untypedAtomic</code> and the
            expected type is <termref def="dt-namespace-sensitive">namespace-sensitive</termref>, a
               <termref def="dt-type-error">type error</termref>
                  <errorref class="TY" code="0117"/> is raised. </p>
            </error>
            <!--
<error  spec="XQ" role="xquery" code="0121" class="ST" type="static">
<p>It is a static error if a feature specified in <code>prohibit-feature</code> is supported by the implementation.</p>
</error>
-->
            <!--
<error  spec="XQ" role="xquery" code="0124" class="ST" type="static" diff="del">
<p>
It is a static error if the name of a feature in
<code>require-feature</code> or <code>prohibit-feature</code> is not recognized by the implementation.
</p>
</error>
-->
            <!--
<error  spec="XQ" role="xquery" code="0127" class="ST" type="static" diff="add">
<p>
  It is a <termref def="dt-static-error">static error</termref> if a
  given feature is both required and prohibited, directly or indirectly, in a module.
</p>
</error>
-->
            <!--<error spec="XQ" role="xquery" code="0129" class="ST" type="static"  diff="del" at="2023-01-29">
         <p>An implementation that does not provide the Higher-Order Function Feature <termref
               def="must">MUST</termref> raise a static error <errorref class="ST" code="0129"/> if
            it encounters a <nt def="FunctionTest">FunctionTest</nt>, <termref
               def="dt-dynamic-function-invocation">dynamic function call</termref>, <termref
               def="dt-named-function-ref">named function reference</termref>, <termref
               def="dt-inline-func">inline function expression</termref>, or <termref
               def="dt-partial-function-application">partial function application</termref>. </p>
      </error>
-->
            <error spec="XP" code="0130" class="DY" type="dynamic">
               <p>An implementation-dependent limit has been exceeded.</p>
            </error>
            <!--
<error  spec="XQ" role="xquery" code="0132" class="ST" type="static">
<p>The <code>module</code> feature can only be required or prohibited in a main module, not in a library module.</p>
</error>
-->
            <!--
      <error spec="XP" code="0133" class="ST" type="static" diff="del">

         <p>It is a <termref def="dt-static-error">static error</termref>
            <errorref class="ST" code="0133"/> if the namespace URI for an EQName is
               <code>http://www.w3.org/2000/xmlns/</code>.</p>
      </error>
-->
            <error spec="XQ" code="0134" class="ST" type="static">
               <p>The namespace axis is not supported.</p>
            </error>
            <!-- DELETED
<error  spec="XP" role="xquery" code="0135" class="ST" type="static" diff="del">
<p> A processor may raise an error  <errorref code="0034" class="ST"/> if the modules of a query do not have the same version number.</p>
</error>
-->
            <!--  DELETED
      <error spec="XQ" code="0136" class="DY" type="dynamic">
         <p>A map key must be a single atomic item.</p>
      </error>
-->
            <error spec="XQ" code="0137" class="DY" type="dynamic">
               <p>No two keys in a map may have the  <termref def="dt-same-key">same key value</termref>.</p>
            </error>
            <!--  DELETED (bug 28689) 
      <error spec="XP" code="0138" class="DY" type="dynamic">
         <p>Position <code>n</code> does not exist in this array.</p>
      </error>


      <error spec="XP" code="0139" class="DY" type="dynamic">
         <p>The keys in a map constructor cannot contain both
         date/time values with a timezone and date/time values with no
         timezone. 
         </p>
      </error>
-->
            <error spec="XQ" code="0140" class="ST" type="static">
               <p> It is a <termref def="dt-static-error">static error</termref> if a named item type declaration 
            is recursive, unless it satisfies the conditions defined in <specref ref="id-recursive-record-tests"/>.</p>
            </error>
            <error spec="XP" code="0141" class="TY" type="type">
               <p>In a <code nobreak="false">for</code>
                  <phrase role="xpath">expression</phrase>,
         when the keyword <code nobreak="false">member</code> is present, the value of the binding collection
         must be a single array; and when either or both of the keywords <code nobreak="false">key</code> and <code nobreak="false">value</code>
         are present, the value of the binding collection must be a single map.</p>
            </error>
            <error spec="XP" code="0144" class="TY" type="type">
               <p>During the analysis phase, an axis step is classified as <termref def="dt-implausible"/>
            if the combination of the inferred context item type, the choice of axis, and the
            supplied node test, is such that the axis step will always return an empty sequence.</p>
            </error>
            <error spec="XP" code="0145" class="TY" type="type">
               <p>During the analysis phase, a unary or postfix lookup expression is classified as <termref def="dt-implausible"/>
            if the combination of the inferred type of the left-hand operand (or the context item type
            in the case of a unary expression) and the choice of key specifier is such that the lookup expression
            will always return an empty sequence.</p>
            </error>
            <!--<error spec="XP" code="0147" class="ST" type="static">
         <p>It is a <termref def="dt-static-error">static error</termref> if a type used as a member
         type in a <nt def="LocalUnionType">LocalUnionType</nt> is not a 
         <termref def="dt-generalized-atomic-type"/>.</p>
      </error>-->
            <!--<error spec="XQ" role="xquery" code="0150" class="ST" type="static">
         <p> It is a <termref def="dt-static-error">static error</termref> 
            if any of the parameters in a variadic function declaration 
            is declared as optional: that is, 
            if a function declaration is annotated as
            <code>%variadic</code> then none of its parameters may 
            contain a <nt def="ParamWithDefault">ParamWithDefault</nt>.</p>
      </error>-->
            <error spec="XP" code="0152" class="ST" type="static">
               <p>It is a <termref def="dt-static-error">static error</termref> 
            if a key type named in a <nt def="prod-xpath40-TypedMapType"><!--$spec = xpath40--></nt> is not a
            <termref def="dt-generalized-atomic-type"/>.</p>
            </error>
            <error spec="XP" code="0154" class="ST" type="static">
               <p>It is a <termref def="dt-static-error">static error</termref> 
            if a <nt def="prod-xpath40-URIQualifiedName">URIQualifiedName<!--$spec = xpath40--></nt> includes a prefix but no URI.</p>
            </error>
         </error-list>
      </div1>
      <inform-div1 id="id-glossary">
         <head>Glossary</head>
         <!-- This processing instruction automatically generates the glossary. -->
         <?glossary?>
      </inform-div1>
      <inform-div1 id="id-atomic-comparisons">
         <head>Atomic Comparisons: An Overview</head>
         <p>This appendix provides a non-normative summary of the various functions and operators used for comparison
    of atomic items, with some background on the history and rationale.</p>
         <p>In XPath 4.0 there are several ways of comparing two atomic items for equality or ordering.
    The rules for each are summarized in the following sections</p>
         <div2 id="value-comparisons-summary">
            <head>Value Comparisons</head>
            <p>For example <code nobreak="false">$A eq $B</code> or <code nobreak="false">$A lt $B</code>.</p>
            <p>Value comparisons were introduced in XPath 2.0 and XQuery 1.0. One of the aims was to make
          the comparison transitive (a precondition for a wide variety of optimizations), however in edge
          cases involving comparisons across different numeric types this was not entirely achieved.
          To fix this problem, the rules have changed in the 4.0 specification.</p>
            <p>With a value comparison, the rules are:</p>
            <ulist>
               <item>
                  <p>Each operand must either be a single atomic item, or an empty sequence.</p>
               </item>
               <item>
                  <p>If either operand is an empty sequence, the result is an empty sequence; in most
            contexts this has the same effect as returning false.</p>
               </item>
               <item>
                  <p>Strings are compared using the default collation from the static context
          of the expression.</p>
               </item>
               <item>
                  <p>Date and time values are compared after normalizing the timezone offset.
          If the timezone is absent, the implicit timezone from the dynamic evaluation context
          is used.</p>
               </item>
               <item>
                  <p>If nodes are supplied, they are atomized. In the absence of schema validation,
          the result of atomizing a node is an untyped atomic value, which is treated as a string.
          Comparison of a node to a value such as a number or a date therefore raises an error.</p>
               </item>
               <item>
                  <p>Numeric values of types <code nobreak="false">xs:integer</code>, <code nobreak="false">xs:decimal</code>, 
            or <code nobreak="false">xs:float</code> are mutually comparable. Except for the special values <code nobreak="false">NaN</code>
            and positive and negative infinity, both operands
            are converted to <code nobreak="false">xs:decimal</code>, using an implementation of <code nobreak="false">xs:decimal</code>
          that supports unlimited precision (or at least, sufficient precision to represent every
          datum in the <code nobreak="false">xs:double</code> value space losslessly), and the comparison then
          follows the normal mathematical principles.</p>
                  <note>
                     <p>This is a change from previous versions, where both values were converted
            to <code nobreak="false">xs:double</code>. The reason for the change is to make comparisons transitive,
            which is vital for operations such as sorting and grouping.</p>
                  </note>
               </item>
               <item>
                  <p>NaN is not equal to NaN; negative zero is equal to positive zero.</p>
               </item>
               <item>
                  <p>In 4.0, <code nobreak="false">xs:hexBinary</code> and <code nobreak="false">xs:base64Binary</code> values are mutually comparable:
            they are equal if they represent the same sequence of octets.</p>
               </item>
               <item>
                  <p>Comparing incompatible values (for example <code nobreak="false">xs:integer</code> and <code nobreak="false">xs:date</code>)
            raises an error.</p>
               </item>
            </ulist>
         </div2>
         <div2 id="general-comparisons-summary">
            <head>General Comparisons</head>
            <p>For example <code nobreak="false">$A = $B</code> or <code nobreak="false">$A &lt; $B</code>.</p>
            <p>These operators were introduced in XPath 1.0. The semantics were changed significantly in XPath 2.0, but the
          original semantics remain available when XPath 1.0 compatibility mode is enabled.</p>
            <p>The following rules are observed:</p>
            <ulist>
               <item>
                  <p>Either operand may be a sequence; the result is true if any pair of items from the
            two sequences have the required relationship (when compared using a value comparison,
            as described above). For equality tests, the result is reasonably
            intuitive, for example <code nobreak="false">(position() = 1 to 10)</code> is true if the value of 
            <code nobreak="false">position()</code> is equal to any of the values from 1 to 10 inclusive. For other
            operators, the result may be less obvious: for example <code nobreak="false">(position() &gt; 1 to 10)</code>
            has exactly the same meaning as <code nobreak="false">(position() &gt; 1)</code>.</p>
                  <p>In consequence, if either operand is an empty sequence, the result is false.</p>
               </item>
               <item>
                  <p>If nodes are supplied, they are atomized.</p>
               </item>
               <item>
                  <p>Untyped atomic items appearing in one operand are converted to the type of the
            other operand (if both operands are untyped atomic, they are compared as strings).
            As a result, the operator is not transitive: the untyped atomic items <code nobreak="false">"4.0"</code>
            and <code nobreak="false">"4"</code> are not equal to each other, but both compare equal to the integer value 
            <code nobreak="false">4</code>.</p>
               </item>
               <item>
                  <p>As with value comparisons, the result is context-sensitive. In particular, comparison of strings
            uses the default collation from the static context, while comparison of date/time values lacking
            a timezone takes the implicit timezone from the dynamic context.</p>
               </item>
               <item>
                  <p>Comparing incompatible values (for example <code nobreak="false">xs:integer</code> and <code nobreak="false">xs:date</code>)
            raises an error.</p>
               </item>
               <item>
                  <p>For version 4.0, two changes arise as a consequence of the changes
          to value comparisons, described above:</p>
                  <olist>
                     <item>
                        <p>
                           <code nobreak="false">xs:hexBinary</code> and <code nobreak="false">xs:base64Binary</code> values become 
                mutually comparable.</p>
                     </item>
                     <item>
                        <p>Comparison between mixed numeric types (for example <code nobreak="false">xs:decimal</code>
              and <code nobreak="false">xs:double</code>) now converts both values to <code nobreak="false">xs:decimal</code>
              rather than <code nobreak="false">xs:double</code>.</p>
                     </item>
                  </olist>
               </item>
               <item>
                  <p>To mitigate the compatibility impact of the above change, the rules for handling
            untyped atomic values have changed: for example, if <code nobreak="false">$a</code> is an untyped
            attribute node with the value <code nobreak="false">"8.95"</code>, then the comparison
            <code nobreak="false">$a = 8.95</code> remains true. This is because an untyped atomic value is
            now converted to the type of the other operand, which in this case is <code nobreak="false">xs:decimal</code>,
            and the two <code nobreak="false">xs:decimal</code> values compare equal.</p>
               </item>
            </ulist>
         </div2>
         <div2 id="deep-equal-summary">
            <head>fn:deep-equal</head>
            <p>For example, <code nobreak="false">deep-equal($A, $B)</code>
            </p>
            <p>As the name implies, the <code nobreak="false">deep-equal</code> function was introduced primarily for comparing nodes,
          or sequences of nodes; however in its simplest form it can also be used to compare two atomic items. The semantics
          of the comparison used by <code nobreak="false">deep-equal($A, $B)</code> are also invoked by a wide variety of other functions
          including <code nobreak="false">distinct-values</code>, <code nobreak="false">all-equal</code>, and <code nobreak="false">all-different</code>; it is also
          used to underpin grouping constructs in both XQuery 4.0 and XSLT 4.0.</p>
            <p>Some of the relevant rules are:</p>
            <ulist>
               <item>
                  <p>Because <code nobreak="false">deep-equal</code> is used to compare sequences, if one of the operands is an empty
            sequence the result is false; but if both operands are empty sequences, the result is true.</p>
               </item>
               <item>
                  <p>If nodes are supplied, they are not atomized; they are compared as nodes.</p>
               </item>
               <item>
                  <p>Strings can be compared using the default collation or using an explicitly specified collation;
            there are also options to compare after normalizing whitespace or Unicode.</p>
               </item>
               <item>
                  <p>Comparisons of dates and times lacking a timezone uses the implicit timezone from the dynamic
            context.</p>
               </item>
               <item>
                  <p>To ensure that every value is equal to itself, comparing NaN to NaN returns true.</p>
               </item>
               <item>
                  <p>In all other cases comparison between numeric values, including comparison of mixed
            types such as <code nobreak="false">xs:double</code> and <code nobreak="false">xs:decimal</code>, follows the same
            rules as for value comparisons using the <code nobreak="false">eq</code> operator.</p>
               </item>
               <item>
                  <p>
                     <code nobreak="false">xs:hexBinary</code> and <code nobreak="false">xs:base64Binary</code> values are mutually comparable:
            they are equal if they represent the same sequence of octets.</p>
               </item>
               <item>
                  <p>Comparing incompatible values (for example <code nobreak="false">xs:integer</code> and <code nobreak="false">xs:date</code>)
            returns false; it does not raise an error.</p>
               </item>
            </ulist>
         </div2>
         <div2 id="atomic-equal-summary">
            <head>fn:atomic-equal</head>
            <p>For example, <code nobreak="false">atomic-equal($A, $B)</code>
            </p>
            <p>This comparison operation was introduced in XPath 3.0 (and XQuery 3.0) for comparing keys in maps;
          the 4.0 specifications expose it directly as a function that can be called from user applications.
          The dominant requirements for keys in maps were that the comparison should be transitive, error-free, 
          and context-independent. The relevant rules are:</p>
            <ulist>
               <item>
                  <p>The type signature of the function ensures that it can only be used to compare
            single items; empty sequences do not arise.</p>
               </item>
               <item>
                  <p>If nodes are supplied, they are atomized.</p>
               </item>
               <item>
                  <p>Strings are compared codepoint-by-codepoint, without reference to any collation or
            normalization.</p>
               </item>
               <item>
                  <p>Dates and times lacking a timezone are never equal to dates and times that have a timezone.
            However, when comparing two dates or times that both have a timezone, the timezone is normalized.</p>
               </item>
               <item>
                  <p>Comparison of numeric values follows the same rules as <function>deep-equal</function>:
            NaN is considered equal to NaN, positive zero is equal to negative zero, 
            and numeric values of differing type are converted to <code nobreak="false">xs:decimal</code> 
            prior to comparison.</p>
               </item>
               <item>
                  <p>
                     <code nobreak="false">xs:hexBinary</code> and <code nobreak="false">xs:base64Binary</code> values are mutually comparable:
            they are equal if they represent the same sequence of octets. This represents
          an incompatibility with previous versions, in that an <code nobreak="false">xs:hexBinary</code> and <code nobreak="false">xs:base64Binary</code>
          value representing the same sequence of octets can no longer co-exist in the same map;
          they are considered to be duplicate keys.</p>
               </item>
               <item>
                  <p>Comparing incompatible values (for example <code nobreak="false">xs:integer</code> and <code nobreak="false">xs:date</code>)
            returns false; it does not raise an error.</p>
               </item>
            </ulist>
         </div2>
         <div2 id="fn-compare-summary">
            <head>fn:compare</head>
            <p>The function <function>fn:compare</function> was introduced in XPath 3.0 and XQuery 3.0 for comparing
    strings; in 4.0 it has been extended to handle other data types. Unlike <function>fn:deep-equal</function>
    and <code nobreak="false">fn:atomic-equal</code> it establishes the order relationship of two atomic items, rather than
    simply determining whether they are equal.</p>
            <p>Broadly speaking, the <function>fn:compare</function> function establishes the relationship between
    its first two operands in the same way as value comparisons using the <code nobreak="false">eq</code> and <code nobreak="false">lt</code>
    operators. The main differences are:</p>
            <olist>
               <item>
                  <p>
                     <function>fn:compare</function> allows a collation to be supplied explicitly, rather than
      relying on the static context.</p>
               </item>
               <item>
                  <p>
                     <function>fn:compare</function> treats <code nobreak="false">NaN</code> as equal to itself (and less than any
        other numeric value).</p>
               </item>
            </olist>
            <p>All other functions and operations that depend on sorting values (for example the <function>fn:sort</function>,
    <function>fn:sort-by</function>, and <function>fn:sort-with</function> functions, the <function>fn:min</function>
    and <function>fn:max</function> functions, <function>fn:highest</function> and <function>fn:lowest</function>,
    the <code nobreak="false">order by</code> clause in XQuery, and the <code nobreak="false">xsl:sort</code> and <code nobreak="false">xsl:merge</code> instructions
    in XSLT, are ultimately defined in terms of either <code nobreak="false">fn:compare</code> or the value comparison operators
    <code nobreak="false">eq</code> and <code nobreak="false">lt</code>.</p>
         </div2>
         <div2 id="comparison-methods-summary">
            <head>Summary of Atomic Comparison Methods</head>
            <p>The following table summarizes these differences for different ways of comparing values. For all these examples it is assumed that
      (a) the default collation is the HTML case-blind collation, (b) the implicit timezone is
      +01:00, and (c) nodes are untyped.</p>
            <table border="1" role="small">
               <thead>
                  <tr>
                     <th rowspan="1" colspan="1">
                        <code nobreak="false">$A</code>
                     </th>
                     <th rowspan="1" colspan="1">
                        <code nobreak="false">$B</code>
                     </th>
                     <th rowspan="1" colspan="1">
                        <code nobreak="false">$A = $B</code>
                     </th>
                     <th rowspan="1" colspan="1">
                        <code nobreak="false">$A eq $B</code>
                     </th>
                     <th rowspan="1" colspan="1">
                        <code nobreak="false">deep-equal(​$A, $B)</code>
                     </th>
                     <th rowspan="1" colspan="1">
                        <code nobreak="false">atomic-equal(​$A, $B)</code>
                     </th>
                     <th rowspan="1" colspan="1">
                        <code nobreak="false">compare(​$A, $B)</code>
                     </th>
                  </tr>
               </thead>
               <tbody>
                  <tr>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">()</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">()</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">false</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">()</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">error</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">()</code>
                        </p>
                     </td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">12</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">()</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">false</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">()</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">false</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">error</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">()</code>
                        </p>
                     </td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">(1,2)</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">(2,3)</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">error</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">false</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">error</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">error</code>
                        </p>
                     </td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">12</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">12e0</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">0</code>
                        </p>
                     </td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">0.2</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">0.2e0</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">false</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">false</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">false</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">false</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">-1</code>
                        </p>
                     </td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">NaN</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">NaN</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">false</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">false</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">0</code>
                        </p>
                     </td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">+0e0</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">-0e0</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">0</code>
                        </p>
                     </td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">"A"</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">"a"</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">false</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">0</code>
                        </p>
                     </td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">"A"</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">12</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">error</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">error</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">false</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">false</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">error</code>
                        </p>
                     </td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">&lt;a&gt;A&lt;/a&gt;</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">"A"</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">false</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">0</code>
                        </p>
                     </td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">&lt;a&gt;12&lt;/a&gt;</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">12</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">error</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">false</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">false</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">error</code>
                        </p>
                     </td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">xs:time(​'12:00:00Z')</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">xs:time(​'13:00:00+01:00')</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">0</code>
                        </p>
                     </td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">xs:time(​'12:00:00Z')</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">xs:time(​'13:00:00')</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">false</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">0</code>
                        </p>
                     </td>
                  </tr>
                  <tr>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">xs:hexBinary(​"0000")</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">xs:base64Binary(​"AAA=")</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">true</code>
                        </p>
                     </td>
                     <td rowspan="1" colspan="1">
                        <p>
                           <code nobreak="false">0</code>
                        </p>
                     </td>
                  </tr>
               </tbody>
            </table>
         </div2>
      </inform-div1>
      <inform-div1 id="id-incompatibilities">
         <head>Backwards Compatibility</head>
         <div2 id="id-incompatibilities-31">
            <head>Incompatibilities relative to XPath 3.1</head>
            <p>Comparisons between numeric values of different types (for example <code nobreak="false">xs:double</code>
    and <code nobreak="false">xs:decimal</code>) may give a different result, because the values will now be compared
    as decimals rather than as doubles. For example, the comparison <code nobreak="false">3.1 = 3.1e0</code> will now return
    false, because the exact value of the <code nobreak="false">xs:double</code> written as <code nobreak="false">3.1e0</code>
    is actually <code nobreak="false">3.100000000000000088817841970012523233890533447265625</code>. This change is made
    to ensure that comparison operations are fully transitive, which is a prerequisite for certain
    sorting and grouping algorithms.</p>
            <p>In <code nobreak="false">fn:format-integer</code>, certain formatting pictures using a circumflex as a grouping separator might
    be interpreted differently in 4.0: for example <code nobreak="false">format-integer(1234, "9^999")</code> would output <code nobreak="false">"1^234"</code>
      in 3.1, but will output <code nobreak="false">"1621"</code> (1234 in base 9) with 4.0. As a workaround, this can be rewritten as 
      <code nobreak="false">format-integer(1234, "0^000")</code>.</p>
            <p>In XPath 4.0, certain expressions are classified as <termref def="dt-implausible"/>: an example
    is <code nobreak="false">@code/text()</code>, which will always return an empty sequence. A processor may report
    a static error when such expressions are encountered; however, processors are <rfc2119>required</rfc2119>
    to provide a mode of operation in which such expressions are accepted, thus retaining backwards
    compatibility.</p>
            <p>In expressions that deliver a function item, notably partial function applications, named function references,
    and the <code nobreak="false">fn:function-lookup</code> function, errors may now be detected at the point where the function item
    is created when they were previously detected at the point where the function item was called. This was underspecified
    in previous versions. For example, the partial function application <code nobreak="false">contains(?, 42)</code> is now required to
    raise a type error (because the second argument should be a string, not an integer) at the point where the partial
    function application occurs, not at the point where the resulting function is called.</p>
            <p>As explained in <specref ref="id-function-coercion"/>, the fact that coercion rules are now applied
    to global variables and local variable bindings introduces an incompatibility in the case of variables
    whose value is a function item. Previously it was possible to supply a function item that accepted a wider
    range of argument values than those declared in the variable's type declaration; this is no longer the case.</p>
            <p>Use of an unprefixed function name in a function declaration has a different meaning from XQuery 3.1. In
    3.1 and previous versions, this declared a function in the <termref def="dt-default-function-namespace"/>
    (which would cause an error unless the default function namespace was explicitly set to something other than
    the <code nobreak="false">fn</code> namespace). In XQuery 4.0, the function name will be in no namespace. The distinction will rarely
    be noticed, because an unprefixed function name in a call of such a function will still work in the same way.
    It could make a difference, however, if a function call uses a prefixed name in which the prefix is explicitly
    bound to the default function namespace.</p>
         </div2>
         <div2 id="id-incompatibilities-30">
            <head>Incompatibilities relative to XPath 3.0</head>
            <p>The following names are now reserved, and cannot appear as function names (see <specref ref="id-reserved-fn-names"/>):</p>
            <ulist>
               <item>
                  <p>
                     <code nobreak="false">map</code>
                  </p>
               </item>
               <item>
                  <p>
                     <code nobreak="false">array</code>
                  </p>
               </item>
            </ulist>
         </div2>
         <div2 id="id-incompatibilities-10">
            <head>Incompatibilities relative to XPath <phrase role="xpath">2.0</phrase>
            </head>
            <p>The following names are now reserved, and cannot appear as function names (see <specref ref="id-reserved-fn-names"/>):</p>
            <ulist>
               <item>
                  <p>
                     <code nobreak="false">function</code>
                  </p>
               </item>
               <item>
                  <p>
                     <code nobreak="false">namespace-node</code>
                  </p>
               </item>
               <item>
                  <p>
                     <code nobreak="false">switch</code>
                  </p>
               </item>
            </ulist>
            <p>If <code nobreak="false">U</code> is a union type with <code nobreak="false">T</code> as one of its members,
  and if <code nobreak="false">E</code> is an element with <code nobreak="false">T</code> as its type annotation,
  the expression <code role="parse-test" nobreak="false">E instance of element(*, U)</code>
  returns <code nobreak="false">true</code> in both XPath 3.0 and 3.1.
  In <phrase role="xpath">XPath 2.0</phrase>,
  it returns <code nobreak="false">false</code>.</p>
            <note>
               <p>This is not an incompatibility with XPath 3.0.
 It should be included in XPath 3.0 as an incompatibility with
 <phrase role="xpath">XPath 2.0</phrase>,
 but it was discovered after publication.</p>
            </note>
         </div2>
         <div2 role="xpath" id="id-backwards-compatibility">
            <head>Incompatibilities relative to XPath 1.0</head>
            <p>This appendix provides a summary of the areas of incompatibility between XPath 4.0 and
            <bibref ref="xpath"/>. In each of these cases, an XPath 4.0 processor is compatible
        with an XPath 2.0, 3.0, or 3.1 processor.</p>
            <p>Three separate cases are considered:</p>
            <olist>
               <item>
                  <p>Incompatibilities that exist when source documents have no schema, and when running
                with XPath 1.0 compatibility mode set to <code nobreak="false">true</code>. This specification has been designed
                to reduce the number of incompatibilities in this situation to an absolute minimum,
                but some differences remain and are listed individually.</p>
               </item>
               <item>
                  <p>Incompatibilities that arise when XPath 1.0 compatibility mode is set to <code nobreak="false">false</code>. In
                this case, the number of expressions where compatibility is lost is rather
                greater.</p>
               </item>
               <item>
                  <p>Incompatibilities that arise when the source document is processed using a schema
                (whether or not XPath 1.0 compatibility mode is set to <code nobreak="false">true</code>). Processing the
                document with a schema changes the way that the values of nodes are interpreted, and
                this can cause an XPath expression to return different results.</p>
               </item>
            </olist>
            <div3 id="id-incompat-in-true-mode">
               <head>Incompatibilities when Compatibility Mode is true</head>
               <p>The list below contains all known areas, within the scope of this specification, where an
            XPath 4.0 processor running with compatibility mode set to <code nobreak="false">true</code> will produce different
            results from an XPath 1.0 processor evaluating the same expression, assuming that the
            expression was valid in XPath 1.0, and that the nodes in the source document have no
            type annotations other than <code nobreak="false">xs:untyped</code> and
            <code nobreak="false">xs:untypedAtomic</code>.</p>
               <p>Incompatibilities in the behavior of individual functions are not listed here, but are
            included in an appendix of <bibref ref="xpath-functions-40"/>.</p>
               <p>Since both XPath 1.0 and <phrase diff="chg" at="bug28782">XPath 4.0</phrase> leave some aspects of the specification
            implementation-defined, there may be incompatibilities in the behavior of a particular
            implementation that are outside the scope of this specification. Equally, some aspects
            of the behavior of XPath are defined by the host language.</p>
               <olist>
                  <item>
                     <p>Consecutive comparison operators such as <code nobreak="false">A &lt; B &lt; C</code> were
                    supported in XPath 1.0, but are not permitted by the <phrase diff="chg" at="bug28782">XPath 4.0</phrase> grammar. In most
                    cases such comparisons in XPath 1.0 did not have the intuitive meaning, so it is
                    unlikely that they have been widely used in practice. If such a construct is
                    found, an <phrase diff="chg" at="bug28782">XPath 4.0</phrase> processor will report a syntax error, and the construct can
                    be rewritten as <code role="parse-test" nobreak="false">(A &lt; B) &lt; C</code>
                     </p>
                  </item>
                  <item>
                     <p>When converting strings to numbers (either explicitly when using the
                        <code nobreak="false">number</code> function, or implicitly say on a function call), certain
                    strings that converted to the special value <code nobreak="false">NaN</code> under XPath 1.0
                    will convert to values other than <code nobreak="false">NaN</code> under <phrase diff="chg" at="bug28782">XPath 4.0</phrase>. These
                    include any number written with a leading <code nobreak="false">+</code> sign, any number in
                    exponential floating point notation (for example <code nobreak="false">1.0e+9</code>), and the
                    strings <code nobreak="false">INF</code> and <code nobreak="false">-INF</code>.</p>
                     <p>Furthermore, the strings <code nobreak="false">Infinity</code> and <code nobreak="false">-Infinity</code>, which
                    were accepted by XPath 1.0 as representations of the floating-point values
                    positive and negative infinity, are no longer recognized. They are converted to
                        <code nobreak="false">NaN</code> when running under <phrase diff="chg" at="bug28782">XPath 4.0</phrase> with compatibility mode set to
                    <code nobreak="false">true</code>, and cause a dynamic error when compatibility mode is set to <code nobreak="false">false</code>.</p>
                  </item>
                  <item>
                     <p>
                        <phrase diff="chg" at="bug28782">XPath 4.0</phrase> does not allow a token starting with a letter to follow immediately
                    after a numeric literal, without intervening whitespace. For example,
                        <code nobreak="false">10div 3</code> was permitted in XPath 1.0, but in <phrase diff="chg" at="bug28782">XPath 4.0</phrase> must be
                    written as <code nobreak="false">10 div 3</code>.</p>
                  </item>
                  <item>
                     <p>The namespace axis is deprecated as of XPath 2.0. Implementations may support the
                    namespace axis for backward compatibility with XPath 1.0, but they are not
                    required to do so. (XSLT 2.0 requires that if XPath backwards compatibility mode
                    is supported, then the namespace axis must also be supported; but other host
                    languages may define the conformance rules differently.)</p>
                  </item>
                  <item>
                     <p>In XPath 1.0, the expression <code nobreak="false">-x|y</code> parsed as <code nobreak="false">-(x|y)</code>, and
                    returned the negation of the numeric value of the first node in the union of
                        <code nobreak="false">x</code> and <code nobreak="false">y</code>. In <phrase diff="chg" at="bug28782">XPath 4.0</phrase>, this expression parses as
                        <code nobreak="false">(-x)|y</code>. When XPath 1.0 Compatibility Mode is true, this will
                    always cause a type error.</p>
                  </item>
                  <item>
                     <p>The rules for converting numbers to strings have changed. These may affect the
                    way numbers are displayed in the output of a stylesheet. For numbers whose
                    absolute value is in the range <code nobreak="false">1E-6</code> to <code nobreak="false">1E+6</code>, the
                    result should be the same, but outside this range, scientific format is used for
                    non-integral <code nobreak="false">xs:float</code> and <code nobreak="false">xs:double</code> values.</p>
                  </item>
                  <item>
                     <p>If one operand in a general comparison is a single atomic item of type
                        <code nobreak="false">xs:boolean</code>, the other operand is converted to
                        <code nobreak="false">xs:boolean</code> when XPath 1.0 compatibility mode is set to <code nobreak="false">true</code>. In
                    XPath 1.0, if neither operand of a comparison operation using the &lt;, &lt;=,
                    &gt; or &gt;= operator was a node set, both operands were converted to numbers.
                    The result of the expression <code nobreak="false">true() &gt; number('0.5')</code> is therefore
                    <code nobreak="false">true</code> in XPath 1.0, but is <code nobreak="false">false</code> in <phrase diff="chg" at="bug28782">XPath 4.0</phrase> even when compatibility mode is set
                    to <code nobreak="false">true</code>.</p>
                  </item>
                  <item>
                     <p>In <phrase diff="chg" at="bug28782">XPath 4.0</phrase>, a type error is raised if the PITarget specified in a SequenceType
                    of form <code nobreak="false">processing-instruction(PITarget)</code> is not a valid NCName. In
                    XPath 1.0, this condition was not treated as an error.</p>
                  </item>
               </olist>
            </div3>
            <div3 id="id-incompat-in-false-mode">
               <head>Incompatibilities when Compatibility Mode is <code nobreak="false">false</code>
               </head>
               <p>Even when the setting of the XPath 1.0 compatibility mode is <code nobreak="false">false</code>, many XPath
            expressions will still produce the same results under XPath 4.0 as under XPath 1.0. The
            exceptions are described in this section.</p>
               <p>In all cases it is assumed that the expression in question was valid under XPath 1.0,
            that XPath 1.0 compatibility mode is <code nobreak="false">false</code>, and that all elements and attributes are
            annotated with the types <code nobreak="false">xs:untyped</code> and <code nobreak="false">xs:untypedAtomic</code>
            respectively.</p>
               <p>In the description below, the terms <emph>node-set</emph> and <emph>number</emph> are
            used with their XPath 1.0 meanings, that is, to describe expressions which according to
            the rules of XPath 1.0 would have generated a node-set or a number respectively.</p>
               <olist>
                  <item>
                     <p>When a node-set containing more than one node is supplied as an argument to a
                    function or operator that expects a single node or value, the XPath 1.0 rule was
                    that all nodes after the first were discarded. Under XPath 4.0, a type error
                    occurs if there is more than one node. The XPath 1.0 behavior can always be
                    restored by using the predicate <code nobreak="false">[1]</code> to explicitly select the first
                    node in the node-set.</p>
                  </item>
                  <item>
                     <p>In XPath 1.0, the <code nobreak="false">&lt;</code> and <code nobreak="false">&gt;</code> operators, when applied
                    to two strings, attempted to convert both the strings to numbers and then made a
                    numeric comparison between the results. In XPath 4.0, these operators perform a
                    string comparison using the default collating sequence. (If either value is
                    numeric, however, the results are compatible with XPath 1.0)</p>
                  </item>
                  <item>
                     <p>When an empty node-set is supplied as an argument to a function or operator that
                    expects a number, the value is no longer converted implicitly to <code nobreak="false">NaN</code>. The XPath
                    1.0 behavior can always be restored by using the <code nobreak="false">number</code> function to
                    perform an explicit conversion.</p>
                  </item>
                  <item>
                     <p>More generally, the supplied arguments to a function or operator are no longer
                    implicitly converted to the required type, except in the case where the supplied
                    argument is of type <code nobreak="false">xs:untypedAtomic</code> (which will commonly be the
                    case when a node in a schemaless document is supplied as the argument). For
                    example, the function call <code role="parse-test" nobreak="false">substring-before(10 div 3,
                        ".")</code> raises a type error under XPath 4.0, because the arguments to
                    the <code nobreak="false">substring-before</code> function must be strings rather than numbers.
                    The XPath 1.0 behavior can be restored by performing an explicit conversion to
                    the required type using a constructor function or cast.</p>
                  </item>
                  <item>
                     <p>The rules for comparing a node-set to a boolean have changed. In XPath 1.0, an
                    expression such as <code role="parse-test" nobreak="false">$node-set = true()</code> was
                    evaluated by converting the node-set to a boolean and then performing a boolean
                    comparison: so this expression would return <code nobreak="false">true</code> if
                        <code nobreak="false">$node-set</code> was non-empty. In XPath 4.0, this expression is
                    handled in the same way as other comparisons between a sequence and a singleton:
                    it is <code nobreak="false">true</code> if <code nobreak="false">$node-set</code> contains at least one node
                    whose value, after atomization and conversion to a boolean using the casting
                    rules, is <code nobreak="false">true</code>.</p>
                     <p>This means that if <code nobreak="false">$node-set</code> is empty, the result under XPath 4.0
                    will be <code nobreak="false">false</code> regardless of the value of the boolean operand, and
                    regardless of which operator is used. If <code nobreak="false">$node-set</code> is non-empty,
                    then in most cases the comparison with a boolean is likely to fail, giving a
                    dynamic error. But if a node has the value <code nobreak="false">"0"</code>, <code nobreak="false">"1"</code>,
                    <code nobreak="false">"true"</code>, or <code nobreak="false">"false"</code>, evaluation of the expression
                    may succeed.</p>
                  </item>
                  <item>
                     <p>Comparisons of a number to a boolean, a number to a string, or a string to a
                    boolean are not allowed in XPath 4.0: they result in a type error. In XPath 1.0
                    such comparisons were allowed, and were handled by converting one of the
                    operands to the type of the other. So for example in XPath 1.0
                    <code role="parse-test" nobreak="false">4 = true()</code> returned <code nobreak="false">true</code>;
                    <code role="parse-test" nobreak="false">4 ="+4"</code> returned <code nobreak="false">false</code>
                    (because the string <code nobreak="false">"+4"</code> converts to <code nobreak="false">NaN</code>),
                    and <code nobreak="false">false = "false"</code> returned <code nobreak="false">false</code> (because the
                    string <code nobreak="false">"false"</code> converts to the boolean <code nobreak="false">true</code>). In XPath
                    3.0 all these comparisons are type errors.</p>
                  </item>
                  <item>
                     <p>Additional numeric types have been introduced, with the effect that arithmetic
                    may now be done as an integer, decimal, or single- or double-precision floating
                    point calculation where previously it was always performed as double-precision
                    floating point. The result of the <code nobreak="false">div</code> operator when dividing two
                    integers is now a value of type decimal rather than double. The expression <code role="parse-test" nobreak="false">10 div 0</code> raises an error rather than returning
                    positive infinity.</p>
                  </item>
                  <item>
                     <p>The rules for converting strings to numbers have changed. The implicit conversion
                    that occurs when passing an <code nobreak="false">xs:untypedAtomic</code> value as an argument
                    to a function that expects a number no longer converts unrecognized strings to
                    the value <code nobreak="false">NaN</code>; instead, it reports a dynamic error. This is in
                    addition to the differences that apply when backwards compatibility mode is set
                    to <code nobreak="false">true</code>.</p>
                  </item>
                  <item>
                     <p>Many operations in XPath 4.0 produce an empty sequence as their result when one
                    of the arguments or operands is an empty sequence. Where the operation expects a
                    string, an empty sequence is usually considered equivalent to a zero-length
                    string, which is compatible with the XPath 1.0 behavior. Where the operation
                    expects a number, however, the result is not the same. For example, if
                        <code nobreak="false">@width</code> returns an empty sequence, then in XPath 1.0 the result
                    of <code role="parse-test" nobreak="false">@width+1</code> was <code nobreak="false">NaN</code>, while with
                    XPath 4.0 it is <code nobreak="false">()</code>. This has the effect that a filter expression
                    such as <code role="parse-test" nobreak="false">item[@width+1 != 2]</code> will select items
                    having no <code nobreak="false">width</code> attribute under XPath 1.0, and will not select them
                    under XPath 4.0.</p>
                  </item>
                  <item>
                     <p>The typed value of a comment node, processing instruction node, or namespace node
                    under XPath 4.0 is of type <code nobreak="false">xs:string</code>, not
                        <code nobreak="false">xs:untypedAtomic</code>. This means that no implicit conversions are
                    applied if the value is used in a context where a number is expected. If a
                    processing-instruction node is used as an operand of an arithmetic operator, for
                    example, XPath 1.0 would attempt to convert the string value of the node to a
                    number (and deliver <code nobreak="false">NaN</code> if unsuccessful), while XPath 4.0 will
                    report a type error.</p>
                  </item>
                  <item>
                     <p>In XPath 1.0, it was defined that with an expression of the form <code nobreak="false">A and
                        B</code>, B would not be evaluated if A was false. Similarly in the case of
                        <code nobreak="false">A or B</code>, B would not be evaluated if A was true. This is no
                    longer guaranteed with XPath 4.0: the implementation is free to evaluate the two
                    operands in either order or in parallel. This change has been made to give more
                    scope for optimization in situations where XPath expressions are evaluated
                    against large data collections supported by indexes. Implementations may choose
                    to retain backwards compatibility in this area, but they are not obliged to do
                    so.</p>
                  </item>
                  <item>
                     <p>In XPath 1.0, the expression <code nobreak="false">-x|y</code> parsed as <code nobreak="false">-(x|y)</code>, and
                    returned the negation of the numeric value of the first node in the union of
                        <code nobreak="false">x</code> and <code nobreak="false">y</code>. In XPath 4.0, this expression parses as
                        <code nobreak="false">(-x)|y</code>. When XPath 1.0 Compatibility Mode is false, this will
                    cause a type error, except in the situation where <code nobreak="false">x</code> evaluates to an
                    empty sequence. In that situation, XPath 4.0 will return the value of
                        <code nobreak="false">y</code>, whereas XPath 1.0 returned the negation of the numeric value
                    of <code nobreak="false">y</code>.</p>
                  </item>
               </olist>
            </div3>
            <div3 id="id-incompat-when-using-schema">
               <head>Incompatibilities when using a Schema</head>
               <p>An XPath expression applied to a document that has been processed against a schema will
            not always give the same results as the same expression applied to the same document in
            the absence of a schema. Since schema processing had no effect on the result of an XPath
            1.0 expression, this may give rise to further incompatibilities. This section gives a
            few examples of the differences that can arise.</p>
               <p>Suppose that the context node is an element node derived from the following markup:
                <code nobreak="false">&lt;background color="red green blue"/&gt;</code>. In XPath 1.0, the predicate
                <code nobreak="false">[@color="blue"]</code> would return <code nobreak="false">false</code>. In XPath 4.0, if the
                <code nobreak="false">color</code> attribute is defined in a schema to be of type
                <code nobreak="false">xs:NMTOKENS</code>, the same predicate will return <code nobreak="false">true</code>.</p>
               <p>Similarly, consider the expression <code role="parse-test" nobreak="false">@birth &lt; @death</code>
            applied to the element <code nobreak="false">&lt;person birth="1901-06-06"
                death="1991-05-09"/&gt;</code>. With XPath 1.0, this expression would return <code nobreak="false">false</code>,
            because both attributes are converted to numbers, which returns <code nobreak="false">NaN</code> in each
            case. With XPath 4.0, in the presence of a schema that annotates these attributes as
            dates, the expression returns <code nobreak="false">true</code>.</p>
               <p>Once schema validation is applied, elements and attributes cannot be used as operands and
            arguments of expressions that expect a different data type. For example, it is no longer
            possible to apply the <code nobreak="false">substring</code> function to a date to extract the year
            component, or to a number to extract the integer part. Similarly, if an attribute is
            annotated as a boolean then it is not possible to compare it with the strings
                <code nobreak="false">"true"</code> or <code nobreak="false">"false"</code>. All such operations lead to type
            errors. The remedy when such errors occur is to introduce an explicit conversion, or to
            do the computation in a different way. For example, <code role="parse-test" nobreak="false">substring-after(@temperature, "-")</code> might be rewritten as <code role="parse-test" nobreak="false">abs(@temperature)</code>.</p>
               <p>In the case of an XPath 4.0 implementation that provides the static typing feature, many
            further type errors will be reported in respect of expressions that worked under XPath
            1.0. For example, an expression such as <code role="parse-test" nobreak="false">round(../@price)</code>
            might lead to a static type error because the processor cannot infer statically that
                <code role="parse-test" nobreak="false">../@price</code> is guaranteed to be numeric.</p>
               <p>Schema validation will in many cases perform whitespace normalization on the contents of
            elements (depending on their type). This will change the result of operations such as
            the <code nobreak="false">string-length</code> function.</p>
               <p>Schema validation augments the data model by adding default values for omitted attributes
            and empty elements.</p>
            </div3>
         </div2>
      </inform-div1>
      <inform-div1 id="id-revision-log" diff="chg" at="2022-11-16">
         <head>Change Log</head>
         <?change-log?>
      </inform-div1>
   </back>
</spec>
