Added more info about the $xml-string parameter.

xquery version "3.0";

(:
 : Copyright 2006-2010 The FLWOR Foundation.
 :
 : Licensed under the Apache License, Version 2.0 (the "License");
 : you may not use this file except in compliance with the License.
 : You may obtain a copy of the License at
 :
 : http://www.apache.org/licenses/LICENSE-2.0
 :
 : Unless required by applicable law or agreed to in writing, software
 : distributed under the License is distributed on an "AS IS" BASIS,
 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 : See the License for the specific language governing permissions and
 : limitations under the License.
:)

(:~
 :

 : This module provides functions for reading XML files from string inputs.
 : It allows reading of well-formed XML documents as well as well-formed
 : external parsed entities, described by
 : XML 1.0 Well-Formed
 : Parsed Entities. The functions can also perform Schema and DTD
 : validation of the input documents.
 :

 :
 :
The following example parses a sequence of XML elements and returns
 : them in a streaming fashion - each at a time:

 :
 :

 : import module namespace x = "http://www.zorba-xquery.com/modules/xml";
 : import schema namespace opt = "http://www.zorba-xquery.com/modules/xml-options";
 : x:parse(
 :   "<from1>Jani</from1><from2>Jani</from2><from3>Jani</from3>",
 :   <opt:options>
 :     <opt:parse-external-parsed-entity/>
 :   </opt:options>
 : )
 :

 :
 :
Another useful option allows to skip an arbitrary number of levels
 : before returning a sequence of nodes as shown in the following example:

 :
 :

 : import module namespace x = "http://www.zorba-xquery.com/modules/xml";
 : import schema namespace opt = "http://www.zorba-xquery.com/modules/xml-options";
 : x:parse(
 :   "<root>
 :     <from1>Jani1</from1>
 :     <from2>Jani2</from2>
 :     <from3>Jani3</from3>
 :   </root>",
 :   <opt:options>
 :     <opt:parse-external-parsed-entity opt:skip-root-nodes="1"/>
 :   </opt:options>
 : )
 :

 :
 : @see XML 1.0 Well-Formed
 : Parsed Entities
 : @see
 : fn:parse-xml() function in XPath and XQuery Functions and Operators 3.0
 : @see LibXml2 parser
 :
 : @author Nicolae Brinza, Juan Zacarias
 : @project data processing/data converters
 :
 :)
module namespace x = "http://www.zorba-xquery.com/modules/xml";
import module namespace schema = "http://www.zorba-xquery.com/modules/schema";

import schema namespace parse-xml-options = "http://www.zorba-xquery.com/modules/xml-options";
import schema namespace canonicalize-xml-options = "http://www.zorba-xquery.com/modules/xml-canonicalize-options";

declare namespace zerr = "http://www.zorba-xquery.com/errors";
declare namespace err = "http://www.w3.org/xqt-errors";

declare namespace ver = "http://www.zorba-xquery.com/options/versioning";
declare option ver:module-version "2.1";

(:~
 : A function to parse XML files and fragments (i.e.
 : external general parsed
 : entities). The functions takes two arguments: the first one is the
 : string to be parsed and the second argument is an <options/> element that
 : passes a list of options to the parsing function. They are described below.
 : The options element must conform to the xml-options:options element type
 : from the xml-options.xsd schema. Some of these
 : will be passed to the underlying library (LibXml2) and further documentation
 : for them can be found at
 : LibXml2 parser.
 :
 : The list of available options:
 :
 :

 :

 : <base-uri/> - the element must have a "value" attribute, which will provide
 : the baseURI that will be used as the baseURI for every node returned by this
 : function.
 :

 :
 :

 : <no-error/> - if present, the option will disable fatal error processing. Any
 : failure to parse or validate the input in the requested manner will result
 : in the function returning an empty sequence and no error will raised.
 :

 :
 :

 : <schema-validate/> - if present, it will request that the input string be Schema
 : validated. The element accepts an attribute named "mode" which can have two
 : values: "strict and "lax". Enabling the option will produce a result that is
 : equivalent to processing the input with the option disabled, and then copying
 : the result using the XQuery "validate strict|lax" expression. This option can not
 : be used together with either the <DTD-validate/> or the <parse-external-parsed-entity/>
 : option. Doing so will raise a zerr:ZXQD0003 error.
 :

 :
 :

 : <DTD-validate/> - the option will enable the DTD-based validation. If this
 : option is enabled and the input references a DTD, then the input must be a
 : well-formed and DTD-valid XML document. The <DTD-load/> option must be used for
 : external DTD files to be loaded. If the option is enabled and the input does
 : not reference a DTD then the option is ignored. If the option is disabled, the
 : input is not required to reference a DTD and if it does reference a DTD then
 : the DTD is ignored for validation purposes. This option can not
 : be used together with either the <schema-validate/> or the <parse-external-parsed-entity>
 : option. Doing so will raise a zerr:ZXQD0003 error.
 :

 :
 :

 : <DTD-load/> - if present, it will enable loading of external DTD files.
 :

 :
 :

 : <default-DTD-attributes/> - if present, it will enable the default DTD attributes.
 :

 :
 :

 : <parse-external-parsed-entity/> - if present, it will enable the processing of XML
 : external entities. If the option
 : is enabled, the input must conform to the syntax extParsedEnt (production
 : [78] in XML 1.0, see
 : Well-Formed Parsed Entities). In addition, by default a DOCTYPE declaration is allowed,
 : as described by the [28] doctypedecl production, see
 : Document Type Definition. A parameter is available to forbid the appearance of the DOCTYPE.
 :
 : The result of the function call is a list
 : of nodes corresponding to the top-level components of the content of the
 : external entity: that is, elements, processing instructions, comments, and
 : text nodes. CDATA sections and character references are expanded, and
 : adjacent characters are merged so the result contains no adjacent text
 : nodes. If the option is disabled, the input must be a well-formed XML
 : document conforming to the Document production
 : (production [1] in XML 1.0).
 : This option can not be used together with either the <schema-validate/> or the <DTD-validate/>
 : option. Doing so will raise a zerr:ZXQD0003 error.
 : The <parse-external-parsed-entity/> option has three parameters, given by attributes. The first
 : attribute is "skip-root-nodes" and it can have a non-negative value. Specifying the paramter
 : tells the parser to skip the given number of root nodes and return only their children. E.g.
 : skip-root-nodes="1" is equivalent to parse-xml($xml-string)/node()/node() . skip-root-nodes="2" is equivalent
 : to parse-xml($xml-string)/node()/node()/node() , etc. The second attribute is "skip-top-level-text-nodes" with a
 : boolean value. Specifying "true" will tell the parser to skip top level text nodes, returning
 : only the top level elements, comments, PIs, etc. This parameter works in combination with
 : the "skip-root-nodes" paramter, thus top level text nodes are skipped after "skip-root-nodes" has
 : been applied. The third paramter is "error-on-doctype" and will generate an error if a DOCTYPE
 : declaration appears in the input, which by default is allowed.
 :

 :
 :

 : <substitute-entities/> - if present, it will enable the XML entities substitutions.
 :

 :
 :

 : <remove-redundant-ns/> - if present, the parser will remove redundant namespaces declarations.
 :

 :
 :

 : <no-CDATA/> - if present, the parser will merge CDATA nodes as text nodes.
 :

 :
 :

 : <xinclude-substitutions/> - if present, it will enable the XInclude substitutions.
 :

 :
 :

 : <no-xinclude-nodes/> - if present, the parser will not generate XInclude START/END nodes.
 :

 :
 :

 :
 :

 : An example that sets the base-uri of the parsed external entities:
 :

 :

 :   import module namespace x = "http://www.zorba-xquery.com/modules/xml";
 :   import schema namespace opt = "http://www.zorba-xquery.com/modules/xml-options";
 :   x:parse("<from1>Jani</from1><from2>Jani</from2><from3>Jani</from3>",
 :     <opt:options>
 :       <opt:base-uri opt:value="urn:test"/>
 :       <opt:parse-external-parsed-entity/>
 :     </opt:options>
 :   )
 :

 :
 : @param $xml-string The string that holds the XML to be parsed. If empty,
 :                    the function will return an empty sequence
 : @param $options The options for the parsing
 : @return The parsed XML as a document node or a list of nodes, or an empty
 :         sequence.
 :
 : @error zerr:ZXQD0003 The error will be raised if the options to the function
 :                     are inconsistent.
 :
 : @error err:FODC0006 The error will be raised if the input string is not a
 :                     valid XML document or fragment (external general parsed
 :                     entity) or if DTD validation was enabled and the
 :                     document has not passed it.
 :
 : @error err:XQDY0027 The error will be raised if schema validation was enabled
 :                     and the input document has not passed it or if the parsing options are not
 :                     conformant to the xml-options.xsd schema.
 :
 :
 :
 : @example test/rbkt/Queries/zorba/parsing_and_serializing/parse-xml-fragment-03.xq
 : @example test/rbkt/Queries/zorba/parsing_and_serializing/parse-xml-fragment-01.xq
 : @example test/rbkt/Queries/zorba/parsing_and_serializing/parse-xml-fragment-07.xq
 :
 :)
declare function x:parse(
  $xml-string as xs:string?,
  $options as element(parse-xml-options:options)?) as node()* external;

(:~
 :

 : Note: this function is included for backwards compatibility purposes. It
 : is recommended that you use the x:parse() function instead.
 :

 :
 : A function to parse XML files and fragments (i.e.
 : external general parsed
 : entities). The functions takes two arguments: the first one is the
 : string to be parsed and the second argument is a flags string
 : (eEdDsSlLwWfF]*(;[\p{L}]*)?) selecting the options described below.
 :

 :

 :
 : The convention for the flags is that a lower-case letter enables
 : an option and the corresponding upper-case letter disables it; specifying
 : both is an error; specifying neither leaves it implementation-defined
 : whether the option is enabled or disabled. Specifying the same option twice
 : is not an error, but specifying inconsistent options (for example "eE") is
 : a dynamic error. The options are:
 :
 :

 :

 : eE - enables or disables processing of XML external entities. If the option
 : is enabled, the input must conform to the syntax extParsedEnt (production
 : [78] in XML 1.0, see
 : Well-Formed Parsed Entities). The result of the function call is a list
 : of nodes corresponding to the top-level components of the content of the
 : external entity: that is, elements, processing instructions, comments, and
 : text nodes. CDATA sections and character references are expanded, and
 : adjacent characters are merged so the result contains no adjacent text
 : nodes. If this option is enabled, none of the options d, s, or l may be
 : enabled. If the option is disabled, the input must be a well-formed XML
 : document conforming to the Document production
 : (production [1] in XML 1.0).
 :

 :
 :

 : dD - enables or disables DTD-based validation. If this option is enabled and
 : the input references a DTD, then the input must be a well-formed and
 : DTD-valid XML document. If the option is enabled and the input does not
 : reference a DTD then the option is ignored. If the option is disabled, the
 : input is not required to reference a DTD and if it does reference a DTD then
 : the DTD is ignored for validation purposes (though it will still be read for
 : purposes such as expanding entity references and identifying ID attributes).
 :

 :
 :

 : sS - enables or disables strict XSD-based validation. If this option is
 : enabled, the result is equivalent to processing the input with the option
 : disabled, and then copying the result using the XQuery "validate strict"
 : expression.
 :

 :
 :

 : lL - enables or disables lax XSD-based validation. If this option is enabled,
 : the result is equivalent to processing the input with the option disabled,
 : and then copying the result using the XQuery "validate lax " expression.
 :

 :
 :

 : wW - enables or disables whitespace stripping. If the option is enabled,
 : any whitespace-only text nodes that remain after any DTD-based or XSD-based
 : processing are stripped from the input; if it is disabled, such
 : whitespace-only text nodes are retained.
 :

 :
 :

 : fF - enables or disables fatal error processing. If fatal error processing
 : is enabled, then any failure to parse the input in the manner requested
 : results in a dynamic error. If fatal error processing is disabled, then any
 : failure to parse the input (and also, in the case of fn:doc, a failure to
 : obtain the input by dereferencing the supplied URI) results in the function
 : returning an empty sequence and raising no error.
 :

 :

 :
 : @param $xml-string The string that holds the XML to be parsed. If empty,
 :                    the function will return an empty sequence
 : @param $options The options for the parsing
 : @return The parsed XML as a document node or a list of nodes, or an empty
 :         sequence.
 :
 : @error zerr:ZXQD0003 The error will be raised if the options to the function
 :                     are inconsistent.
 :
 : @error err:FODC0006 The error will be raised if the input string is not a
 :                     valid XML document or fragment (external general parsed
 :                     entity) or if DTD validation was enabled and the
 :                     document has not passed it.
 :
 : @error err:XQDY0027 The error will be raised if schema validation was enabled
 :                     and the input document has not passed it.
 :
 : @deprecated
 :
 :)
declare function x:parse-xml-fragment(
  $xml-string as xs:string?,
  $options as xs:string) as node()*
{
  let $new_options := <parse-xml-options:options>{
      if (contains($options, "e"))
        then <parse-xml-options:parse-external-parsed-entity/> else (),
      if (contains($options, "d"))
        then <parse-xml-options:DTD-validate/> else (),
      if (contains($options, "s"))
        then <parse-xml-options:schema-validate parse-xml-options:mode="strict"/>
        else (),
      if (contains($options, "l"))
        then <parse-xml-options:schema-validate parse-xml-options:mode="lax"/>
        else (),
      (: TODO: uncomment once the strip-boundary-space option is implemented
      if (contains($options, "w"))
        then <parse-xml-options:strip-boundary-space/> else (), :)
      if (contains($options, "f"))
        then <parse-xml-options:no-error/> else ()
    }</parse-xml-options:options>
  return
    x:parse($xml-string, $new_options)
};

(:~
 :

 : Note: this function is included for backwards compatibility purposes. It
 : is recommended that you use the x:parse() function instead.
 :

 :
 : A function to parse XML files and fragments. The behavior is the
 : same as the parse-xml-fragment with two arguments.
 :
 : @param $xml-string The string that holds the XML to be parsed. If empty,
 :                    the function will return an empty sequence
 : @param $base-uri The baseURI that will be used as the baseURI for every
 :                    node returned by this function.
 : @param $options The options for the parsing (see parse-xml-fragment#2)
 : @return The parsed XML as a document node or a list of nodes, or an empty
 :         sequence.
 :
 : @error zerr:ZXQD0003 The error will be raised if the options to the function
 :                     are inconsistent.
 :
 : @error err:FODC0006 The error will be raised if the input string is not a
 :                     valid XML document or fragment (external general parsed
 :                     entity) or if DTD validation was enabled and the
 :                     document has not passed it.
 :
 : @error err:XQDY0027 The error will be raised if schema validation was enabled
 :                     and the input document has not passed it.
 :
 : @error err:FODC0007 This error will be raised if $base-uri parameter passed
 :                     to the function is not a valid absolute URI.
 :
 : @deprecated
 :
 :)
declare function x:parse-xml-fragment(
  $xml-string as xs:string?,
  $base-uri as xs:string,
  $options as xs:string) as node()*
{
    let $new_options := <parse-xml-options:options>{
      if (contains($options, "e"))
        then <parse-xml-options:parse-external-parsed-entity/> else (),
      if (contains($options, "d"))
        then <parse-xml-options:DTD-validate/> else (),
      if (contains($options, "s"))
        then <parse-xml-options:schema-validate parse-xml-options:mode="strict"/>
        else (),
      if (contains($options, "l"))
        then <parse-xml-options:schema-validate parse-xml-options:mode="lax"/>
        else (),
      (: TODO: uncomment once the strip-boundary-space option is implemented
      if (contains($options, "w"))
        then <parse-xml-options:strip-boundary-space/> else (), :)
      if (contains($options, "f"))
        then <parse-xml-options:no-error/> else (),
      <parse-xml-options:base-uri>{
        attribute{xs:QName("parse-xml-options:value")}{$base-uri}}
      </parse-xml-options:base-uri>
    }</parse-xml-options:options>
  return
    x:parse($xml-string, $new_options)
};

(:~
 : A function to canonicalize the given XML string, that is, transform
 : it into Canonical XML as defined by Canonical XML.
 :
 :
Note: This function is not streamable, if a streamable string is used
 : as input for the function it will be materialized.
 :
 : @param $xml-string a string representation of a well formed XML to canonicalize. XML fragments are not allowed.
 :
 : @return the canonicalized XML string.
 :
 : @error err:CANO0001 invalid input.
 :)
declare function x:canonicalize(
  $xml-string as xs:string
  ) as xs:string external;

(:~
 : A function to canonicalize the given XML string, that is, transform
 : it into Canonical XML as defined by Canonical XML.
 :
This version of the function allows specifying certain options to be
 : used when initially parsing the XML string. These options correspond
 : to the similarly-named options in the
 : LibXMl2 parser, as documented at
 : LibXML: Enum xmlParserOption
 :
 :
Note: This function is not streamable, if a streamable string is used
 : as input for the function it will be materialized.
 :
 : @param $xml-string a string representation of a well formed XML to canonicalize. XML fragments are not allowed.
 : @param $options an XML containg options for the canonicalize function.
 :

 : <options xmlns="http://www.zorba-xquery.com/modules/xml-canonicalize-options">
 :   <xml-parse-dtdload/>
 :   <xml-parse-dtdattr/>
 :   <xml-parse-dtdvalid/>
 :   <xml-parse-noblanks/>
 :   <xml-parse-nonet/>
 :   <xml-parse-nsclean/>
 :   <xml-parse-nocdata/>
 : </options>
 :

 : @return the canonicalized XML string.
 :
 : @error err:CANO0001 invalid input.
 :)
declare function x:canonicalize(
  $xml-string as xs:string,
  $options    as element(canonicalize-xml-options:options)
  ) as xs:string
{
  let $canonicalize-options :=
    if ( schema:is-validated( $options ) )
      then $options
      else validate { $options }
  return x:canonicalize-options-impl( $xml-string , $canonicalize-options )
};

declare %private function x:canonicalize-options-impl(
  $xml-string as xs:string,
  $options    as element()
  ) as xs:string external;

xquery version "3.0";

(:
 : Copyright 2006-2010 The FLWOR Foundation.
 :
 : Licensed under the Apache License, Version 2.0 (the "License");
 : you may not use this file except in compliance with the License.
 : You may obtain a copy of the License at
 :
 : http://www.apache.org/licenses/LICENSE-2.0
 :
 : Unless required by applicable law or agreed to in writing, software
 : distributed under the License is distributed on an "AS IS" BASIS,
 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 : See the License for the specific language governing permissions and
 : limitations under the License.
:)

(:~
 :

 : This module provides functions for reading XML files from string inputs.
 : It allows reading of well-formed XML documents as well as well-formed
 : external parsed entities, described by
 : XML 1.0 Well-Formed
 : Parsed Entities. The functions can also perform Schema and DTD
 : validation of the input documents.
 :

 :
 :
The following example parses a sequence of XML elements and returns
 : them in a streaming fashion - each at a time:

 :
 :

 : import module namespace x = "http://www.zorba-xquery.com/modules/xml";
 : import schema namespace opt = "http://www.zorba-xquery.com/modules/xml-options";
 : x:parse(
 :   "<from1>Jani</from1><from2>Jani</from2><from3>Jani</from3>",
 :   <opt:options>
 :     <opt:parse-external-parsed-entity/>
 :   </opt:options>
 : )
 :

 :
 :
Another useful option allows to skip an arbitrary number of levels
 : before returning a sequence of nodes as shown in the following example:

 :
 :

 : import module namespace x = "http://www.zorba-xquery.com/modules/xml";
 : import schema namespace opt = "http://www.zorba-xquery.com/modules/xml-options";
 : x:parse(
 :   "<root>
 :     <from1>Jani1</from1>
 :     <from2>Jani2</from2>
 :     <from3>Jani3</from3>
 :   </root>",
 :   <opt:options>
 :     <opt:parse-external-parsed-entity opt:skip-root-nodes="1"/>
 :   </opt:options>
 : )
 :

 :
 : @see XML 1.0 Well-Formed
 : Parsed Entities
 : @see
 : fn:parse-xml() function in XPath and XQuery Functions and Operators 3.0
 : @see LibXml2 parser
 :
 : @author Nicolae Brinza, Juan Zacarias
 : @project data processing/data converters
 :
 :)
module namespace x = "http://www.zorba-xquery.com/modules/xml";
import module namespace schema = "http://www.zorba-xquery.com/modules/schema";

import schema namespace parse-xml-options = "http://www.zorba-xquery.com/modules/xml-options";
import schema namespace canonicalize-xml-options = "http://www.zorba-xquery.com/modules/xml-canonicalize-options";

declare namespace zerr = "http://www.zorba-xquery.com/errors";
declare namespace err = "http://www.w3.org/xqt-errors";

declare namespace ver = "http://www.zorba-xquery.com/options/versioning";
declare option ver:module-version "2.1";

(:~
 : A function to parse XML files and fragments (i.e.
 : external general parsed
 : entities). The functions takes two arguments: the first one is the
 : string to be parsed and the second argument is an <options/> element that
 : passes a list of options to the parsing function. They are described below.
 : The options element must conform to the xml-options:options element type
 : from the xml-options.xsd schema. Some of these
 : will be passed to the underlying library (LibXml2) and further documentation
 : for them can be found at
 : LibXml2 parser.
 :
 : The list of available options:
 :
 :

 :

 : <base-uri/> - the element must have a "value" attribute, which will provide
 : the baseURI that will be used as the baseURI for every node returned by this
 : function.
 :

 :
 :

 : <no-error/> - if present, the option will disable fatal error processing. Any
 : failure to parse or validate the input in the requested manner will result
 : in the function returning an empty sequence and no error will raised.
 :

 :
 :

 : <schema-validate/> - if present, it will request that the input string be Schema
 : validated. The element accepts an attribute named "mode" which can have two
 : values: "strict and "lax". Enabling the option will produce a result that is
 : equivalent to processing the input with the option disabled, and then copying
 : the result using the XQuery "validate strict|lax" expression. This option can not
 : be used together with either the <DTD-validate/> or the <parse-external-parsed-entity/>
 : option. Doing so will raise a zerr:ZXQD0003 error.
 :

 :
 :

 : <DTD-validate/> - the option will enable the DTD-based validation. If this
 : option is enabled and the input references a DTD, then the input must be a
 : well-formed and DTD-valid XML document. The <DTD-load/> option must be used for
 : external DTD files to be loaded. If the option is enabled and the input does
 : not reference a DTD then the option is ignored. If the option is disabled, the
 : input is not required to reference a DTD and if it does reference a DTD then
 : the DTD is ignored for validation purposes. This option can not
 : be used together with either the <schema-validate/> or the <parse-external-parsed-entity>
 : option. Doing so will raise a zerr:ZXQD0003 error.
 :

 :
 :

 : <DTD-load/> - if present, it will enable loading of external DTD files.
 :

 :
 :

 : <default-DTD-attributes/> - if present, it will enable the default DTD attributes.
 :

 :
 :

 : <parse-external-parsed-entity/> - if present, it will enable the processing of XML
 : external entities. If the option
 : is enabled, the input must conform to the syntax extParsedEnt (production
 : [78] in XML 1.0, see
 : Well-Formed Parsed Entities). In addition, by default a DOCTYPE declaration is allowed,
 : as described by the [28] doctypedecl production, see
 : Document Type Definition. A parameter is available to forbid the appearance of the DOCTYPE.
 :
 : The result of the function call is a list
 : of nodes corresponding to the top-level components of the content of the
 : external entity: that is, elements, processing instructions, comments, and
 : text nodes. CDATA sections and character references are expanded, and
 : adjacent characters are merged so the result contains no adjacent text
 : nodes. If the option is disabled, the input must be a well-formed XML
 : document conforming to the Document production
 : (production [1] in XML 1.0).
 : This option can not be used together with either the <schema-validate/> or the <DTD-validate/>
 : option. Doing so will raise a zerr:ZXQD0003 error.
 : The <parse-external-parsed-entity/> option has three parameters, given by attributes. The first
 : attribute is "skip-root-nodes" and it can have a non-negative value. Specifying the paramter
 : tells the parser to skip the given number of root nodes and return only their children. E.g.
 : skip-root-nodes="1" is equivalent to parse-xml($xml-string)/node()/node() . skip-root-nodes="2" is equivalent
 : to parse-xml($xml-string)/node()/node()/node() , etc. The second attribute is "skip-top-level-text-nodes" with a
 : boolean value. Specifying "true" will tell the parser to skip top level text nodes, returning
 : only the top level elements, comments, PIs, etc. This parameter works in combination with
 : the "skip-root-nodes" paramter, thus top level text nodes are skipped after "skip-root-nodes" has
 : been applied. The third paramter is "error-on-doctype" and will generate an error if a DOCTYPE
 : declaration appears in the input, which by default is allowed.
 :

 :
 :

 : <substitute-entities/> - if present, it will enable the XML entities substitutions.
 :

 :
 :

 : <remove-redundant-ns/> - if present, the parser will remove redundant namespaces declarations.
 :

 :
 :

 : <no-CDATA/> - if present, the parser will merge CDATA nodes as text nodes.
 :

 :
 :

 : <xinclude-substitutions/> - if present, it will enable the XInclude substitutions.
 :

 :
 :

 : <no-xinclude-nodes/> - if present, the parser will not generate XInclude START/END nodes.
 :

 :
 :

 :
 :

 : An example that sets the base-uri of the parsed external entities:
 :

 :

 :   import module namespace x = "http://www.zorba-xquery.com/modules/xml";
 :   import schema namespace opt = "http://www.zorba-xquery.com/modules/xml-options";
 :   x:parse("<from1>Jani</from1><from2>Jani</from2><from3>Jani</from3>",
 :     <opt:options>
 :       <opt:base-uri opt:value="urn:test"/>
 :       <opt:parse-external-parsed-entity/>
 :     </opt:options>
 :   )
 :

 :
 : @param $xml-string The string that holds the XML to be parsed. If empty,
 :                    the function will return an empty sequence
 : @param $options The options for the parsing
 : @return The parsed XML as a document node or a list of nodes, or an empty
 :         sequence.
 :
 : @error zerr:ZXQD0003 The error will be raised if the options to the function
 :                     are inconsistent.
 :
 : @error err:FODC0006 The error will be raised if the input string is not a
 :                     valid XML document or fragment (external general parsed
 :                     entity) or if DTD validation was enabled and the
 :                     document has not passed it.
 :
 : @error err:XQDY0027 The error will be raised if schema validation was enabled
 :                     and the input document has not passed it or if the parsing options are not
 :                     conformant to the xml-options.xsd schema.
 :
 :
 :
 : @example test/rbkt/Queries/zorba/parsing_and_serializing/parse-xml-fragment-03.xq
 : @example test/rbkt/Queries/zorba/parsing_and_serializing/parse-xml-fragment-01.xq
 : @example test/rbkt/Queries/zorba/parsing_and_serializing/parse-xml-fragment-07.xq
 :
 :)
declare function x:parse(
  $xml-string as xs:string?,
  $options as element(parse-xml-options:options)?) as node()* external;

(:~
 :

 : Note: this function is included for backwards compatibility purposes. It
 : is recommended that you use the x:parse() function instead.
 :

 :
 : A function to parse XML files and fragments (i.e.
 : external general parsed
 : entities). The functions takes two arguments: the first one is the
 : string to be parsed and the second argument is a flags string
 : (eEdDsSlLwWfF]*(;[\p{L}]*)?) selecting the options described below.
 :

 :

 :
 : The convention for the flags is that a lower-case letter enables
 : an option and the corresponding upper-case letter disables it; specifying
 : both is an error; specifying neither leaves it implementation-defined
 : whether the option is enabled or disabled. Specifying the same option twice
 : is not an error, but specifying inconsistent options (for example "eE") is
 : a dynamic error. The options are:
 :
 :

 :

 : eE - enables or disables processing of XML external entities. If the option
 : is enabled, the input must conform to the syntax extParsedEnt (production
 : [78] in XML 1.0, see
 : Well-Formed Parsed Entities). The result of the function call is a list
 : of nodes corresponding to the top-level components of the content of the
 : external entity: that is, elements, processing instructions, comments, and
 : text nodes. CDATA sections and character references are expanded, and
 : adjacent characters are merged so the result contains no adjacent text
 : nodes. If this option is enabled, none of the options d, s, or l may be
 : enabled. If the option is disabled, the input must be a well-formed XML
 : document conforming to the Document production
 : (production [1] in XML 1.0).
 :

 :
 :

 : dD - enables or disables DTD-based validation. If this option is enabled and
 : the input references a DTD, then the input must be a well-formed and
 : DTD-valid XML document. If the option is enabled and the input does not
 : reference a DTD then the option is ignored. If the option is disabled, the
 : input is not required to reference a DTD and if it does reference a DTD then
 : the DTD is ignored for validation purposes (though it will still be read for
 : purposes such as expanding entity references and identifying ID attributes).
 :

 :
 :

 : sS - enables or disables strict XSD-based validation. If this option is
 : enabled, the result is equivalent to processing the input with the option
 : disabled, and then copying the result using the XQuery "validate strict"
 : expression.
 :

 :
 :

 : lL - enables or disables lax XSD-based validation. If this option is enabled,
 : the result is equivalent to processing the input with the option disabled,
 : and then copying the result using the XQuery "validate lax " expression.
 :

 :
 :

 : wW - enables or disables whitespace stripping. If the option is enabled,
 : any whitespace-only text nodes that remain after any DTD-based or XSD-based
 : processing are stripped from the input; if it is disabled, such
 : whitespace-only text nodes are retained.
 :

 :
 :

 : fF - enables or disables fatal error processing. If fatal error processing
 : is enabled, then any failure to parse the input in the manner requested
 : results in a dynamic error. If fatal error processing is disabled, then any
 : failure to parse the input (and also, in the case of fn:doc, a failure to
 : obtain the input by dereferencing the supplied URI) results in the function
 : returning an empty sequence and raising no error.
 :

 :

 :
 : @param $xml-string The string that holds the XML to be parsed. If empty,
 :                    the function will return an empty sequence
 : @param $options The options for the parsing
 : @return The parsed XML as a document node or a list of nodes, or an empty
 :         sequence.
 :
 : @error zerr:ZXQD0003 The error will be raised if the options to the function
 :                     are inconsistent.
 :
 : @error err:FODC0006 The error will be raised if the input string is not a
 :                     valid XML document or fragment (external general parsed
 :                     entity) or if DTD validation was enabled and the
 :                     document has not passed it.
 :
 : @error err:XQDY0027 The error will be raised if schema validation was enabled
 :                     and the input document has not passed it.
 :
 : @deprecated
 :
 :)
declare function x:parse-xml-fragment(
  $xml-string as xs:string?,
  $options as xs:string) as node()*
{
  let $new_options := <parse-xml-options:options>{
      if (contains($options, "e"))
        then <parse-xml-options:parse-external-parsed-entity/> else (),
      if (contains($options, "d"))
        then <parse-xml-options:DTD-validate/> else (),
      if (contains($options, "s"))
        then <parse-xml-options:schema-validate parse-xml-options:mode="strict"/>
        else (),
      if (contains($options, "l"))
        then <parse-xml-options:schema-validate parse-xml-options:mode="lax"/>
        else (),
      (: TODO: uncomment once the strip-boundary-space option is implemented
      if (contains($options, "w"))
        then <parse-xml-options:strip-boundary-space/> else (), :)
      if (contains($options, "f"))
        then <parse-xml-options:no-error/> else ()
    }</parse-xml-options:options>
  return
    x:parse($xml-string, $new_options)
};

(:~
 :

 : Note: this function is included for backwards compatibility purposes. It
 : is recommended that you use the x:parse() function instead.
 :

 :
 : A function to parse XML files and fragments. The behavior is the
 : same as the parse-xml-fragment with two arguments.
 :
 : @param $xml-string The string that holds the XML to be parsed. If empty,
 :                    the function will return an empty sequence
 : @param $base-uri The baseURI that will be used as the baseURI for every
 :                    node returned by this function.
 : @param $options The options for the parsing (see parse-xml-fragment#2)
 : @return The parsed XML as a document node or a list of nodes, or an empty
 :         sequence.
 :
 : @error zerr:ZXQD0003 The error will be raised if the options to the function
 :                     are inconsistent.
 :
 : @error err:FODC0006 The error will be raised if the input string is not a
 :                     valid XML document or fragment (external general parsed
 :                     entity) or if DTD validation was enabled and the
 :                     document has not passed it.
 :
 : @error err:XQDY0027 The error will be raised if schema validation was enabled
 :                     and the input document has not passed it.
 :
 : @error err:FODC0007 This error will be raised if $base-uri parameter passed
 :                     to the function is not a valid absolute URI.
 :
 : @deprecated
 :
 :)
declare function x:parse-xml-fragment(
  $xml-string as xs:string?,
  $base-uri as xs:string,
  $options as xs:string) as node()*
{
    let $new_options := <parse-xml-options:options>{
      if (contains($options, "e"))
        then <parse-xml-options:parse-external-parsed-entity/> else (),
      if (contains($options, "d"))
        then <parse-xml-options:DTD-validate/> else (),
      if (contains($options, "s"))
        then <parse-xml-options:schema-validate parse-xml-options:mode="strict"/>
        else (),
      if (contains($options, "l"))
        then <parse-xml-options:schema-validate parse-xml-options:mode="lax"/>
        else (),
      (: TODO: uncomment once the strip-boundary-space option is implemented
      if (contains($options, "w"))
        then <parse-xml-options:strip-boundary-space/> else (), :)
      if (contains($options, "f"))
        then <parse-xml-options:no-error/> else (),
      <parse-xml-options:base-uri>{
        attribute{xs:QName("parse-xml-options:value")}{$base-uri}}
      </parse-xml-options:base-uri>
    }</parse-xml-options:options>
  return
    x:parse($xml-string, $new_options)
};

(:~
 : A function to canonicalize the given XML string, that is, transform
 : it into Canonical XML as defined by Canonical XML.
 :
 :
Note: This function is not streamable, if a streamable string is used
 : as input for the function it will be materialized.
 :
 : @param $xml-string an XML string to canonicalize.
 :
 : @return the canonicalized XML string.
 :
 : @error err:CANO0001 invalid input.
 :)
declare function x:canonicalize(
  $xml-string as xs:string
  ) as xs:string external;

(:~
 : A function to canonicalize the given XML string, that is, transform
 : it into Canonical XML as defined by Canonical XML.
 :
This version of the function allows specifying certain options to be
 : used when initially parsing the XML string. These options correspond
 : to the similarly-named options in the
 : LibXMl2 parser, as documented at
 : LibXML: Enum xmlParserOption
 :
 :
Note: This function is not streamable, if a streamable string is used
 : as input for the function it will be materialized.
 :
 : @param $xml-string an XML string to canonicalize.
 : @param $options an XML containg options for the canonicalize function.
 :

 : <options xmlns="http://www.zorba-xquery.com/modules/xml-canonicalize-options">
 :   <xml-parse-dtdload/>
 :   <xml-parse-dtdattr/>
 :   <xml-parse-dtdvalid/>
 :   <xml-parse-noblanks/>
 :   <xml-parse-nonet/>
 :   <xml-parse-nsclean/>
 :   <xml-parse-nocdata/>
 : </options>
 :

 : @return the canonicalized XML string.
 :
 : @error err:CANO0001 invalid input.
 :)
declare function x:canonicalize(
  $xml-string as xs:string,
  $options as element(canonicalize-xml-options:options)
  ) as xs:string
{
  let $canonicalize-options :=
    if ( schema:is-validated( $options ) )
      then $options
      else validate { $options }
  return x:canonicalize-options-impl( $xml-string , $canonicalize-options )
};

declare %private function x:canonicalize-options-impl(
  $xml-string as xs:string,
  $options as element()
  ) as xs:string external;


Begin adding BaseX WebSocket module updates.

xquery version "1.0";
(:~
 : BaseX default static context.
 :
 : @see https://www.w3.org/TR/xquery/#id-basics
 : @see https://www.w3.org/TR/xquery/#id-default-namespace
 : @see http://docs.basex.org/wiki/Module_Library
 :)

declare default element namespace "";
declare default function namespace "http://www.w3.org/2005/xpath-functions"; (: = 'fn:' :)

(: XQuery 1.0 :)
declare namespace xml = "http://www.w3.org/XML/1998/namespace";
declare namespace xs = "http://www.w3.org/2001/XMLSchema";
declare namespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
declare namespace fn = "http://www.w3.org/2005/xpath-functions";
declare namespace local = "http://www.w3.org/2005/xquery-local-functions";

(: XQuery 3.0 :)
declare namespace math = "http://www.w3.org/2005/xpath-functions/math";

(: XQuery 3.1 :)
declare namespace map = "http://www.w3.org/2005/xpath-functions/map";
declare namespace array = "http://www.w3.org/2005/xpath-functions/array";

(: BaseX prior to 7.0 :)
declare namespace db = "http://basex.org/modules/db";
declare namespace file = "http://expath.org/ns/file";
declare namespace ft = "http://basex.org/modules/ft";
declare namespace hof = "http://basex.org/modules/hof";
declare namespace xslt = "http://basex.org/modules/xslt";
declare namespace zip = "http://expath.org/ns/zip";

(: BaseX 7.0 :)
declare namespace crypto = "http://expath.org/ns/crypto";
declare namespace json = "http://basex.org/modules/json";
declare namespace sql = "http://basex.org/modules/sql";

(: BaseX 7.1 :)
declare namespace http = "http://expath.org/ns/http-client";
declare namespace index = "http://basex.org/modules/index";
declare namespace repo = "http://basex.org/modules/repo";

(: BaseX 7.3 :)
declare namespace archive = "http://basex.org/modules/archive";
declare namespace client = "http://basex.org/modules/client";
declare namespace convert = "http://basex.org/modules/convert";
declare namespace hash = "http://basex.org/modules/hash";
declare namespace out = "http://basex.org/modules/out";
declare namespace proc = "http://basex.org/modules/proc";
declare namespace prof = "http://basex.org/modules/prof";
declare namespace validate = "http://basex.org/modules/validate";
declare namespace xquery = "http://basex.org/modules/xquery";

(: BaseX 7.5 :)
declare namespace admin = "http://basex.org/modules/admin";
declare namespace random = "http://basex.org/modules/random";

(: BaseX 7.6 :)
declare namespace fetch = "http://basex.org/modules/fetch";
declare namespace html = "http://basex.org/modules/html";

(: BaseX 7.7 :)
declare namespace inspect = "http://basex.org/modules/inspect";
declare namespace stream = "http://basex.org/modules/stream";
declare namespace unit = "http://basex.org/modules/unit";

(: BaseX 7.7.2 :)
declare namespace csv = "http://basex.org/modules/csv";

(: BaseX 7.8 :)
declare namespace bin = "http://expath.org/ns/binary";

(: BaseX 8.0 :)
declare namespace user = "http://basex.org/modules/user";

(: BaseX 8.1 :)
declare namespace web = "http://basex.org/modules/web";

(: BaseX 8.3 :)
declare namespace strings = "http://basex.org/modules/strings";

(: BaseX 8.5 :)
declare namespace jobs = "http://basex.org/modules/jobs";
declare namespace util = "http://basex.org/modules/util";

(: BaseX 9.0 :)
declare namespace lazy = "http://basex.org/modules/lazy";
declare namespace update = "http://basex.org/modules/update";

(: BaseX 9.1 :)
declare namespace ws = "http://basex.org/modules/ws";

()

xquery version "1.0";
(:~
 : BaseX default static context.
 :
 : @see https://www.w3.org/TR/xquery/#id-basics
 : @see https://www.w3.org/TR/xquery/#id-default-namespace
 : @see http://docs.basex.org/wiki/Module_Library
 :)

declare default element namespace "";
declare default function namespace "http://www.w3.org/2005/xpath-functions"; (: = 'fn:' :)

(: XQuery 1.0 :)
declare namespace xml = "http://www.w3.org/XML/1998/namespace";
declare namespace xs = "http://www.w3.org/2001/XMLSchema";
declare namespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
declare namespace fn = "http://www.w3.org/2005/xpath-functions";
declare namespace local = "http://www.w3.org/2005/xquery-local-functions";

(: XQuery 3.0 :)
declare namespace math = "http://www.w3.org/2005/xpath-functions/math";

(: XQuery 3.1 :)
declare namespace map = "http://www.w3.org/2005/xpath-functions/map";
declare namespace array = "http://www.w3.org/2005/xpath-functions/array";

(: BaseX prior to 7.0 :)
declare namespace db = "http://basex.org/modules/db";
declare namespace file = "http://expath.org/ns/file";
declare namespace ft = "http://basex.org/modules/ft";
declare namespace hof = "http://basex.org/modules/hof";
declare namespace xslt = "http://basex.org/modules/xslt";
declare namespace zip = "http://expath.org/ns/zip";

(: BaseX 7.0 :)
declare namespace crypto = "http://expath.org/ns/crypto";
declare namespace json = "http://basex.org/modules/json";
declare namespace sql = "http://basex.org/modules/sql";

(: BaseX 7.1 :)
declare namespace http = "http://expath.org/ns/http-client";
declare namespace index = "http://basex.org/modules/index";
declare namespace repo = "http://basex.org/modules/repo";

(: BaseX 7.3 :)
declare namespace archive = "http://basex.org/modules/archive";
declare namespace client = "http://basex.org/modules/client";
declare namespace convert = "http://basex.org/modules/convert";
declare namespace hash = "http://basex.org/modules/hash";
declare namespace out = "http://basex.org/modules/out";
declare namespace proc = "http://basex.org/modules/proc";
declare namespace prof = "http://basex.org/modules/prof";
declare namespace validate = "http://basex.org/modules/validate";
declare namespace xquery = "http://basex.org/modules/xquery";

(: BaseX 7.5 :)
declare namespace admin = "http://basex.org/modules/admin";
declare namespace random = "http://basex.org/modules/random";

(: BaseX 7.6 :)
declare namespace fetch = "http://basex.org/modules/fetch";
declare namespace html = "http://basex.org/modules/html";

(: BaseX 7.7 :)
declare namespace inspect = "http://basex.org/modules/inspect";
declare namespace stream = "http://basex.org/modules/stream";
declare namespace unit = "http://basex.org/modules/unit";

(: BaseX 7.7.2 :)
declare namespace csv = "http://basex.org/modules/csv";

(: BaseX 7.8 :)
declare namespace bin = "http://expath.org/ns/binary";

(: BaseX 8.0 :)
declare namespace user = "http://basex.org/modules/user";

(: BaseX 8.1 :)
declare namespace web = "http://basex.org/modules/web";

(: BaseX 8.3 :)
declare namespace strings = "http://basex.org/modules/strings";

(: BaseX 8.5 :)
declare namespace jobs = "http://basex.org/modules/jobs";
declare namespace util = "http://basex.org/modules/util";

(: BaseX 9.0 :)
declare namespace lazy = "http://basex.org/modules/lazy";
declare namespace update = "http://basex.org/modules/update";

()


test for full text tokenization on typed nodes

import module namespace cdml = "http://www.zorba-xquery.com/modules/store/static/collections/dml";

import schema namespace kml = "http://earth.google.com/kml/2.1" at "kml21.xsd";

import module namespace kml-data = "http://www.mykml/data" at "sc1_ex1.xqlib";

for $placemark in cdml:collection(xs:QName("kml-data:placemarks"))
where $placemark/kml:description contains text "Elephants"
return
  $placemark/kml:name/text()

import module namespace cdml = "http://www.zorba-xquery.com/modules/store/static/collections/dml";

import schema namespace kml = "http://earth.google.com/kml/2.1" at "kml21.xsd";

import module namespace kml-data = "http://www.mykml/data" at "sc1_ex1.xqlib";

for $placemark in cdml:collection(xs:QName("kml-data:placemarks"))
where contains($placemark/kml:description, "Elephants")
return
  $placemark/kml:name/text()


Fixes tests failing if system language it not english

xquery version "3.0";

module namespace fd="http://exist-db.org/xquery/test/format-dates";

declare namespace test="http://exist-db.org/xquery/xqsuite";

declare
    %test:args("2012-06-26")
    %test:assertEquals("26.6.2012")
    %test:args("2012-06-01")
    %test:assertEquals("1.6.2012")
function fd:simple-date($date as xs:date) {
    format-date($date, "[D].[M].[Y]")
};

declare
    %test:args("2012-06-26")
    %test:assertEquals("26.06.2012")
    %test:args("2012-06-01")
    %test:assertEquals("01.06.2012")
function fd:simple-format($date as xs:date) {
    format-date($date, "[D00].[M01].[Y0]")
};

declare
    %test:args("2012-06-26")
    %test:assertEquals("26.6.2012")
    %test:args("2012-06-01")
    %test:assertEquals("1.6.2012")
function fd:format-month-numeric-width($date as xs:date) {
    format-date($date, "[D,1-2].[M,*-*].[Y,*]")
};

declare
    %test:args("2012-06-26")
    %test:assertEquals("26 JUN 2012")
    %test:args("1970-10-07")
    %test:assertEquals("07 OCT 1970")
function fd:format-month-string-width-caps($date as xs:date) {
    format-date($date, "[D01] [MN,*-3] [Y0001]", "en", (), ())
};

declare
    %test:args("2012-06-26")
    %test:assertEquals("26 Jun 2012")
    %test:args("1970-10-07")
    %test:assertEquals("07 Oct 1970")
function fd:format-month-string-width-title($date as xs:date) {
    format-date($date, "[D01] [MNn,*-3] [Y0001]", "en", (), ())
};

declare
    %test:args("2012-06-26")
    %test:assertEquals("Tuesday, June 26, 2012")
    %test:args("1970-10-07")
    %test:assertEquals("Wednesday, October 7, 1970")
function fd:format-names($date as xs:date) {
    format-date($date, "[FNn], [MNn] [D], [Y]", "en", (), ())
};

declare
    %test:args("2012-06-26")
    %test:assertEquals("Tue Jun 26 2012")
    %test:args("1970-10-07")
    %test:assertEquals("Wed Oct 7 1970")
function fd:format-names-width($date as xs:date) {
    format-date($date, "[FNn,*-3] [MNn,*-3] [D] [Y]", "en", (), ())
};

declare
    %test:args("2012-06-26")
    %test:assertEquals("Tuesday, June 26th, 2012")
    %test:args("2012-06-01")
    %test:assertEquals("Friday, June 1st, 2012")
    %test:args("2012-06-02")
    %test:assertEquals("Saturday, June 2nd, 2012")
    %test:args("2012-06-03")
    %test:assertEquals("Sunday, June 3rd, 2012")
function fd:format-ordinal($date as xs:date) {
    format-date($date, "[FNn], [MNn] [D0o], [Y]", "en", (), ())
};

declare
    %test:args("2002-12-31")
    %test:assertEquals("[2002-12-31]")
function fd:format-square-brackets($date as xs:date) {
    format-date($date, "[[[Y0001]-[M01]-[D01]]]")
};

declare
    %test:args("2012-06-26T23:14:22.566+02:00")
    %test:assertEquals("11:14 pm on Tuesday, June 26th, 2012")
function fd:format-dateTime($date as xs:dateTime) {
    format-dateTime($date, "[h00]:[m00] [P] on [FNn], [MNn] [D1o], [Y]", "en", (), ())
};

declare
    %test:args("2012-06-26+02:00")
    %test:assertEquals("20120626GMT+02:00")
function fd:format-date-z($date as xs:date) {
    format-date($date, "[Y0001][M01][D01][z]")
};

declare
    %test:args("2012-06-26+02:00")
    %test:assertEquals("20120626+02:00")
function fd:format-date-Z($date as xs:date) {
    format-date($date, "[Y0001][M01][D01][Z]")
};

declare
    %test:args("2012-06-26T23:14:22.566+02:00")
    %test:assertEquals("20120626231422GMT+02:00")
function fd:format-dateTime-z($date as xs:dateTime) {
    format-dateTime($date, "[Y0001][M01][D01][H01][m01][s01][z]")
};

declare
    %test:args("2012-06-26T12:00:00.000-10:00")
    %test:assertEquals("GMT-10:00")
function fd:format-dateTime-z-negative-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[z]")
};

declare
    %test:args("2012-06-26T12:00:00.000-05:00")
    %test:assertEquals("GMT-05:00")
function fd:format-dateTime-z-negative-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[z]")
};

declare
    %test:args("2012-06-26T12:00:00.000+00:00")
    %test:assertEquals("GMT+00:00")
function fd:format-dateTime-z-zero($date as xs:dateTime) {
    format-dateTime($date, "[z]")
};

declare
    %test:args("2012-06-26T12:00:00.000+05:30")
    %test:assertEquals("GMT+05:30")
function fd:format-dateTime-z-positive-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[z]")
};

declare
    %test:args("2012-06-26T12:00:00.000+13:00")
    %test:assertEquals("GMT+13:00")
function fd:format-dateTime-z-positive-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[z]")
};

declare
    %test:args("2012-06-26T23:14:22.566+02:00")
    %test:assertEquals("20120626231422+02:00")
function fd:format-dateTime-Z($date as xs:dateTime) {
    format-dateTime($date, "[Y0001][M01][D01][H01][m01][s01][Z]")
};

declare
    %test:args("2012-06-26T12:00:00.000-10:00")
    %test:assertEquals("-10:00")
function fd:format-dateTime-Z-negative-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z]")
};

declare
    %test:args("2012-06-26T12:00:00.000-05:00")
    %test:assertEquals("-05:00")
function fd:format-dateTime-Z-negative-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z]")
};

declare
    %test:args("2012-06-26T12:00:00.000+00:00")
    %test:assertEquals("+00:00")
function fd:format-dateTime-Z-zero($date as xs:dateTime) {
    format-dateTime($date, "[Z]")
};

declare
    %test:args("2012-06-26T12:00:00.000+05:30")
    %test:assertEquals("+05:30")
function fd:format-dateTime-Z-positive-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z]")
};

declare
    %test:args("2012-06-26T12:00:00.000+13:00")
    %test:assertEquals("+13:00")
function fd:format-dateTime-Z-positive-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z]")
};

declare
    %test:args("2012-06-26T23:14:22.566")
    %test:assertEquals("20120626231422")
function fd:format-dateTime-no-tz-z($date as xs:dateTime) {
    format-dateTime($date, "[Y0001][M01][D01][H01][m01][s01][z]")
};

declare
    %test:args("2012-06-26T23:14:22.566")
    %test:assertEquals("20120626231422")
function fd:format-dateTime-no-tz-Z($date as xs:dateTime) {
    format-dateTime($date, "[Y0001][M01][D01][H01][m01][s01][Z]")
};

declare
    %test:args("2012-06-26T12:00:00.000-10:00")
    %test:assertEquals("-10")
function fd:format-dateTime-Z0-negative-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z0]")
};

declare
    %test:args("2012-06-26T12:00:00.000-05:00")
    %test:assertEquals("-5")
function fd:format-dateTime-Z0-negative-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z0]")
};

declare
    %test:args("2012-06-26T12:00:00.000+00:00")
    %test:assertEquals("+0")
function fd:format-dateTime-Z0-zero($date as xs:dateTime) {
    format-dateTime($date, "[Z0]")
};

declare
    %test:args("2012-06-26T12:00:00.000+05:30")
    %test:assertEquals("+5:30")
function fd:format-dateTime-Z0-positive-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z0]")
};

declare
    %test:args("2012-06-26T12:00:00.000+13:00")
    %test:assertEquals("+13")
function fd:format-dateTime-Z0-positive-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z0]")
};

declare
    %test:args("2012-06-26T12:00:00.000-10:00")
    %test:assertEquals("-10:00")
function fd:format-dateTime-Z0-00-negative-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z0:00]")
};

declare
    %test:args("2012-06-26T12:00:00.000-05:00")
    %test:assertEquals("-5:00")
function fd:format-dateTime-Z0-00-negative-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z0:00]")
};

declare
    %test:args("2012-06-26T12:00:00.000+00:00")
    %test:assertEquals("+0:00")
function fd:format-dateTime-Z0-00-zero($date as xs:dateTime) {
    format-dateTime($date, "[Z0:00]")
};

declare
    %test:args("2012-06-26T12:00:00.000+05:30")
    %test:assertEquals("+5:30")
function fd:format-dateTime-Z0-00-positive-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z0:00]")
};

declare
    %test:args("2012-06-26T12:00:00.000+13:00")
    %test:assertEquals("+13:00")
function fd:format-dateTime-Z0-00-positive-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z0:00]")
};

declare
    %test:args("2012-06-26T12:00:00.000-10:00")
    %test:assertEquals("-10:00")
function fd:format-dateTime-Z00-00-negative-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z00:00]")
};

declare
    %test:args("2012-06-26T12:00:00.000-05:00")
    %test:assertEquals("-05:00")
function fd:format-dateTime-Z00-00-negative-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z00:00]")
};

declare
    %test:args("2012-06-26T12:00:00.000+00:00")
    %test:assertEquals("+00:00")
function fd:format-dateTime-Z00-00-zero($date as xs:dateTime) {
    format-dateTime($date, "[Z00:00]")
};

declare
    %test:args("2012-06-26T12:00:00.000+05:30")
    %test:assertEquals("+05:30")
function fd:format-dateTime-Z00-00-positive-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z00:00]")
};

declare
    %test:args("2012-06-26T12:00:00.000+13:00")
    %test:assertEquals("+13:00")
function fd:format-dateTime-Z00-00-positive-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z00:00]")
};

declare
    %test:args("2012-06-26T12:00:00.000-10:00")
    %test:assertEquals("-1000")
function fd:format-dateTime-Z0000-negative-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z0000]")
};

declare
    %test:args("2012-06-26T12:00:00.000-05:00")
    %test:assertEquals("-0500")
function fd:format-dateTime-Z0000-negative-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z0000]")
};

declare
    %test:args("2012-06-26T12:00:00.000+00:00")
    %test:assertEquals("+0000")
function fd:format-dateTime-Z0000-zero($date as xs:dateTime) {
    format-dateTime($date, "[Z0000]")
};

declare
    %test:args("2012-06-26T12:00:00.000+05:30")
    %test:assertEquals("+0530")
function fd:format-dateTime-Z0000-positive-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z0000]")
};

declare
    %test:args("2012-06-26T12:00:00.000+13:00")
    %test:assertEquals("+1300")
function fd:format-dateTime-Z0000-positive-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z0000]")
};

declare
    %test:args("2012-06-26T12:00:00.000-10:00")
    %test:assertEquals("-10:00")
function fd:format-dateTime-Z00-00t-negative-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z00:00t]")
};

declare
    %test:args("2012-06-26T12:00:00.000-05:00")
    %test:assertEquals("-05:00")
function fd:format-dateTime-Z00-00t-negative-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z00:00t]")
};

declare
    %test:args("2012-06-26T12:00:00.000+00:00")
    %test:assertEquals("Z")
function fd:format-dateTime-Z00-00t-zero($date as xs:dateTime) {
    format-dateTime($date, "[Z00:00t]")
};

declare
    %test:args("2012-06-26T12:00:00.000+05:30")
    %test:assertEquals("+05:30")
function fd:format-dateTime-Z00-00t-positive-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z00:00t]")
};

declare
    %test:args("2012-06-26T12:00:00.000+13:00")
    %test:assertEquals("+13:00")
function fd:format-dateTime-Z00-00t-positive-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z00:00t]")
};

declare
    %test:args("2012-06-26T12:00:00.000-10:00")
    %test:assertEquals("W")
function fd:format-dateTime-ZZ-negative-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[ZZ]")
};

declare
    %test:args("2012-06-26T12:00:00.000-05:00")
    %test:assertEquals("R")
function fd:format-dateTime-ZZ-negative-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[ZZ]")
};

declare
    %test:args("2012-06-26T12:00:00.000+00:00")
    %test:assertEquals("Z")
function fd:format-dateTime-ZZ-zero($date as xs:dateTime) {
    format-dateTime($date, "[ZZ]")
};

declare
    %test:args("2012-06-26T12:00:00.000+05:30")
    %test:assertEquals("+05:30")
function fd:format-dateTime-ZZ-positive-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[ZZ]")
};

declare
    %test:args("2012-06-26T12:00:00.000+13:00")
    %test:assertEquals("+13:00")
function fd:format-dateTime-ZZ-positive-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[ZZ]")
};

declare
    %test:pending("[ZN] is not yet supported")
    %test:args("2012-06-26T12:00:00.000-10:00")
    %test:assertEquals("HST")
function fd:format-dateTime-ZN-negative-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[ZN]", (), (), "us")
};

declare
    %test:pending("[ZN] is not yet supported")
    %test:args("2012-06-26T12:00:00.000-05:00")
    %test:assertEquals("EST")
function fd:format-dateTime-ZN-negative-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[ZN]", (), (), "us")
};

declare
    %test:pending("[ZN] is not yet supported")
    %test:args("2012-06-26T12:00:00.000+00:00")
    %test:assertEquals("GMT")
function fd:format-dateTime-ZN-zero($date as xs:dateTime) {
    format-dateTime($date, "[ZN]", (), (), "us")
};

declare
    %test:pending("[ZN] is not yet supported")
    %test:args("2012-06-26T12:00:00.000+05:30")
    %test:assertEquals("IST")
function fd:format-dateTime-ZN-positive-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[ZN]", (), (), "us")
};

declare
    %test:pending("[ZN] is not yet supported")
    %test:args("2012-06-26T12:00:00.000+13:00")
    %test:assertEquals("+13:00")
function fd:format-dateTime-ZN-positive-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[ZN]", (), (), "us")
};

declare
    %test:pending("[ZN] is not yet supported")
    %test:args("2012-06-26T12:00:00.000-10:00")
    %test:assertEquals("06:00 EST")
function fd:format-dateTime-ZN-NY-negative-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[H00]:[M00] [ZN]", (), (), "America/New_York")
};

declare
    %test:pending("[ZN] is not yet supported")
    %test:args("2012-06-26T12:00:00.000-05:00")
    %test:assertEquals("12:00 EST")
function fd:format-dateTime-ZN-NY-negative-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[H00]:[M00] [ZN]", (), (), "America/New_York")
};

declare
    %test:pending("[ZN] is not yet supported")
    %test:args("2012-06-26T12:00:00.000+00:00")
    %test:assertEquals("07:00 EST")
function fd:format-dateTime-ZN-NY-zero($date as xs:dateTime) {
    format-dateTime($date, "[H00]:[M00] [ZN]", (), (), "America/New_York")
};

declare
    %test:pending("[ZN] is not yet supported")
    %test:args("2012-06-26T12:00:00.000+05:30")
    %test:assertEquals("01:30 EST")
function fd:format-dateTime-ZN-NY-positive-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[H00]:[M00] [ZN]", (), (), "America/New_York")
};

declare
    %test:pending("[ZN] is not yet supported")
    %test:args("2012-06-26T12:00:00.000+13:00")
    %test:assertEquals("18:00 EST")
function fd:format-dateTime-ZN-NY-positive-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[H00]:[M00] [ZN]", (), (), "America/New_York")
};

declare
    %test:args("17:45:50")
    %test:assertEquals("17:45:50")
    %test:args("09:45:50")
    %test:assertEquals("09:45:50")
function fd:simple-time($time as xs:time) {
    format-time($time, "[H00]:[m00]:[s]")
};

declare
    %test:args("17:45:50")
    %test:assertEquals("05:45 pm")
    %test:args("09:45:50")
    %test:assertEquals("09:45 am")
function fd:time-am-pm($time as xs:time) {
    format-time($time, "[h00]:[m00] [P]")
};

declare
    %test:assertError
function fd:date-format-in-format-time() {
    format-time(current-time(), "[Y]")
};

declare
    %test:assertError
function fd:time-format-in-format-date() {
    format-date(current-dateTime(), "[H]")
};

declare
    %test:args("2012-06-27Z")
    %test:assertEquals("Mittwoch, 27. Juni 2012")
    %test:args("1970-10-07Z")
    %test:assertEquals("Mittwoch, 7. Oktober 1970")
function fd:language-de($date as xs:date) {
    format-date($date, "[FNn], [D1o] [MNn] [Y]", "de", (), ())
};

declare
    %test:args("2012-06-01Z")
    %test:assertEquals("пятница, 1 июня 2012")
    %test:args("1970-10-07Z")
    %test:assertEquals("среда, 7 октября 1970")
function fd:language-ru($date as xs:date) {
    format-date($date, "[FNn], [D1o] [MNn] [Y]", "ru", (), ())
};

declare
%test:args("2012-06-01Z")
%test:assertEquals("vendredi, 1er juin 2012")
%test:args("1970-10-07Z")
%test:assertEquals("mercredi, 7 octobre 1970")
function fd:language-fr($date as xs:date) {
    format-date($date, "[FNn], [D1o] [MNn] [Y]", "fr", (), ())
};

declare
    %test:args("2018-05-21Z")
    %test:assertEquals("Monday")
    %test:args("2018-05-22Z")
    %test:assertEquals("Tuesday")
    %test:args("2018-05-23Z")
    %test:assertEquals("Wednesday")
    %test:args("2018-05-24Z")
    %test:assertEquals("Thursday")
    %test:args("2018-05-25Z")
    %test:assertEquals("Friday")
    %test:args("2018-05-26Z")
    %test:assertEquals("Saturday")
    %test:args("2018-05-27Z")
    %test:assertEquals("Sunday")
function fd:written-day-en($date-str as xs:string) {
    format-date(xs:date($date-str), "[FNn]", "en", (), ())
};

xquery version "3.0";

module namespace fd="http://exist-db.org/xquery/test/format-dates";

declare namespace test="http://exist-db.org/xquery/xqsuite";

declare
    %test:args("2012-06-26")
    %test:assertEquals("26.6.2012")
    %test:args("2012-06-01")
    %test:assertEquals("1.6.2012")
function fd:simple-date($date as xs:date) {
    format-date($date, "[D].[M].[Y]")
};

declare
    %test:args("2012-06-26")
    %test:assertEquals("26.06.2012")
    %test:args("2012-06-01")
    %test:assertEquals("01.06.2012")
function fd:simple-format($date as xs:date) {
    format-date($date, "[D00].[M01].[Y0]")
};

declare
    %test:args("2012-06-26")
    %test:assertEquals("26.6.2012")
    %test:args("2012-06-01")
    %test:assertEquals("1.6.2012")
function fd:format-month-numeric-width($date as xs:date) {
    format-date($date, "[D,1-2].[M,*-*].[Y,*]")
};

declare
    %test:args("2012-06-26")
    %test:assertEquals("26 JUN 2012")
    %test:args("1970-10-07")
    %test:assertEquals("07 OCT 1970")
function fd:format-month-string-width-caps($date as xs:date) {
    format-date($date, "[D01] [MN,*-3] [Y0001]")
};

declare
    %test:args("2012-06-26")
    %test:assertEquals("26 Jun 2012")
    %test:args("1970-10-07")
    %test:assertEquals("07 Oct 1970")
function fd:format-month-string-width-title($date as xs:date) {
    format-date($date, "[D01] [MNn,*-3] [Y0001]")
};

declare
    %test:args("2012-06-26")
    %test:assertEquals("Tuesday, June 26, 2012")
    %test:args("1970-10-07")
    %test:assertEquals("Wednesday, October 7, 1970")
function fd:format-names($date as xs:date) {
    format-date($date, "[FNn], [MNn] [D], [Y]")
};

declare
    %test:args("2012-06-26")
    %test:assertEquals("Tue Jun 26 2012")
    %test:args("1970-10-07")
    %test:assertEquals("Wed Oct 7 1970")
function fd:format-names-width($date as xs:date) {
    format-date($date, "[FNn,*-3] [MNn,*-3] [D] [Y]")
};

declare
    %test:args("2012-06-26")
    %test:assertEquals("Tuesday, June 26th, 2012")
    %test:args("2012-06-01")
    %test:assertEquals("Friday, June 1st, 2012")
    %test:args("2012-06-02")
    %test:assertEquals("Saturday, June 2nd, 2012")
    %test:args("2012-06-03")
    %test:assertEquals("Sunday, June 3rd, 2012")
function fd:format-ordinal($date as xs:date) {
    format-date($date, "[FNn], [MNn] [D0o], [Y]")
};

declare
    %test:args("2002-12-31")
    %test:assertEquals("[2002-12-31]")
function fd:format-square-brackets($date as xs:date) {
    format-date($date, "[[[Y0001]-[M01]-[D01]]]")
};

declare
    %test:args("2012-06-26T23:14:22.566+02:00")
    %test:assertEquals("11:14 pm on Tuesday, June 26th, 2012")
function fd:format-dateTime($date as xs:dateTime) {
    format-dateTime($date, "[h00]:[m00] [P] on [FNn], [MNn] [D1o], [Y]")
};

declare
    %test:args("2012-06-26+02:00")
    %test:assertEquals("20120626GMT+02:00")
function fd:format-date-z($date as xs:date) {
    format-date($date, "[Y0001][M01][D01][z]")
};

declare
    %test:args("2012-06-26+02:00")
    %test:assertEquals("20120626+02:00")
function fd:format-date-Z($date as xs:date) {
    format-date($date, "[Y0001][M01][D01][Z]")
};

declare
    %test:args("2012-06-26T23:14:22.566+02:00")
    %test:assertEquals("20120626231422GMT+02:00")
function fd:format-dateTime-z($date as xs:dateTime) {
    format-dateTime($date, "[Y0001][M01][D01][H01][m01][s01][z]")
};

declare
    %test:args("2012-06-26T12:00:00.000-10:00")
    %test:assertEquals("GMT-10:00")
function fd:format-dateTime-z-negative-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[z]")
};

declare
    %test:args("2012-06-26T12:00:00.000-05:00")
    %test:assertEquals("GMT-05:00")
function fd:format-dateTime-z-negative-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[z]")
};

declare
    %test:args("2012-06-26T12:00:00.000+00:00")
    %test:assertEquals("GMT+00:00")
function fd:format-dateTime-z-zero($date as xs:dateTime) {
    format-dateTime($date, "[z]")
};

declare
    %test:args("2012-06-26T12:00:00.000+05:30")
    %test:assertEquals("GMT+05:30")
function fd:format-dateTime-z-positive-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[z]")
};

declare
    %test:args("2012-06-26T12:00:00.000+13:00")
    %test:assertEquals("GMT+13:00")
function fd:format-dateTime-z-positive-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[z]")
};

declare
    %test:args("2012-06-26T23:14:22.566+02:00")
    %test:assertEquals("20120626231422+02:00")
function fd:format-dateTime-Z($date as xs:dateTime) {
    format-dateTime($date, "[Y0001][M01][D01][H01][m01][s01][Z]")
};

declare
    %test:args("2012-06-26T12:00:00.000-10:00")
    %test:assertEquals("-10:00")
function fd:format-dateTime-Z-negative-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z]")
};

declare
    %test:args("2012-06-26T12:00:00.000-05:00")
    %test:assertEquals("-05:00")
function fd:format-dateTime-Z-negative-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z]")
};

declare
    %test:args("2012-06-26T12:00:00.000+00:00")
    %test:assertEquals("+00:00")
function fd:format-dateTime-Z-zero($date as xs:dateTime) {
    format-dateTime($date, "[Z]")
};

declare
    %test:args("2012-06-26T12:00:00.000+05:30")
    %test:assertEquals("+05:30")
function fd:format-dateTime-Z-positive-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z]")
};

declare
    %test:args("2012-06-26T12:00:00.000+13:00")
    %test:assertEquals("+13:00")
function fd:format-dateTime-Z-positive-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z]")
};

declare
    %test:args("2012-06-26T23:14:22.566")
    %test:assertEquals("20120626231422")
function fd:format-dateTime-no-tz-z($date as xs:dateTime) {
    format-dateTime($date, "[Y0001][M01][D01][H01][m01][s01][z]")
};

declare
    %test:args("2012-06-26T23:14:22.566")
    %test:assertEquals("20120626231422")
function fd:format-dateTime-no-tz-Z($date as xs:dateTime) {
    format-dateTime($date, "[Y0001][M01][D01][H01][m01][s01][Z]")
};

declare
    %test:args("2012-06-26T12:00:00.000-10:00")
    %test:assertEquals("-10")
function fd:format-dateTime-Z0-negative-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z0]")
};

declare
    %test:args("2012-06-26T12:00:00.000-05:00")
    %test:assertEquals("-5")
function fd:format-dateTime-Z0-negative-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z0]")
};

declare
    %test:args("2012-06-26T12:00:00.000+00:00")
    %test:assertEquals("+0")
function fd:format-dateTime-Z0-zero($date as xs:dateTime) {
    format-dateTime($date, "[Z0]")
};

declare
    %test:args("2012-06-26T12:00:00.000+05:30")
    %test:assertEquals("+5:30")
function fd:format-dateTime-Z0-positive-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z0]")
};

declare
    %test:args("2012-06-26T12:00:00.000+13:00")
    %test:assertEquals("+13")
function fd:format-dateTime-Z0-positive-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z0]")
};

declare
    %test:args("2012-06-26T12:00:00.000-10:00")
    %test:assertEquals("-10:00")
function fd:format-dateTime-Z0-00-negative-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z0:00]")
};

declare
    %test:args("2012-06-26T12:00:00.000-05:00")
    %test:assertEquals("-5:00")
function fd:format-dateTime-Z0-00-negative-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z0:00]")
};

declare
    %test:args("2012-06-26T12:00:00.000+00:00")
    %test:assertEquals("+0:00")
function fd:format-dateTime-Z0-00-zero($date as xs:dateTime) {
    format-dateTime($date, "[Z0:00]")
};

declare
    %test:args("2012-06-26T12:00:00.000+05:30")
    %test:assertEquals("+5:30")
function fd:format-dateTime-Z0-00-positive-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z0:00]")
};

declare
    %test:args("2012-06-26T12:00:00.000+13:00")
    %test:assertEquals("+13:00")
function fd:format-dateTime-Z0-00-positive-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z0:00]")
};

declare
    %test:args("2012-06-26T12:00:00.000-10:00")
    %test:assertEquals("-10:00")
function fd:format-dateTime-Z00-00-negative-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z00:00]")
};

declare
    %test:args("2012-06-26T12:00:00.000-05:00")
    %test:assertEquals("-05:00")
function fd:format-dateTime-Z00-00-negative-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z00:00]")
};

declare
    %test:args("2012-06-26T12:00:00.000+00:00")
    %test:assertEquals("+00:00")
function fd:format-dateTime-Z00-00-zero($date as xs:dateTime) {
    format-dateTime($date, "[Z00:00]")
};

declare
    %test:args("2012-06-26T12:00:00.000+05:30")
    %test:assertEquals("+05:30")
function fd:format-dateTime-Z00-00-positive-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z00:00]")
};

declare
    %test:args("2012-06-26T12:00:00.000+13:00")
    %test:assertEquals("+13:00")
function fd:format-dateTime-Z00-00-positive-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z00:00]")
};

declare
    %test:args("2012-06-26T12:00:00.000-10:00")
    %test:assertEquals("-1000")
function fd:format-dateTime-Z0000-negative-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z0000]")
};

declare
    %test:args("2012-06-26T12:00:00.000-05:00")
    %test:assertEquals("-0500")
function fd:format-dateTime-Z0000-negative-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z0000]")
};

declare
    %test:args("2012-06-26T12:00:00.000+00:00")
    %test:assertEquals("+0000")
function fd:format-dateTime-Z0000-zero($date as xs:dateTime) {
    format-dateTime($date, "[Z0000]")
};

declare
    %test:args("2012-06-26T12:00:00.000+05:30")
    %test:assertEquals("+0530")
function fd:format-dateTime-Z0000-positive-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z0000]")
};

declare
    %test:args("2012-06-26T12:00:00.000+13:00")
    %test:assertEquals("+1300")
function fd:format-dateTime-Z0000-positive-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z0000]")
};

declare
    %test:args("2012-06-26T12:00:00.000-10:00")
    %test:assertEquals("-10:00")
function fd:format-dateTime-Z00-00t-negative-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z00:00t]")
};

declare
    %test:args("2012-06-26T12:00:00.000-05:00")
    %test:assertEquals("-05:00")
function fd:format-dateTime-Z00-00t-negative-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z00:00t]")
};

declare
    %test:args("2012-06-26T12:00:00.000+00:00")
    %test:assertEquals("Z")
function fd:format-dateTime-Z00-00t-zero($date as xs:dateTime) {
    format-dateTime($date, "[Z00:00t]")
};

declare
    %test:args("2012-06-26T12:00:00.000+05:30")
    %test:assertEquals("+05:30")
function fd:format-dateTime-Z00-00t-positive-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z00:00t]")
};

declare
    %test:args("2012-06-26T12:00:00.000+13:00")
    %test:assertEquals("+13:00")
function fd:format-dateTime-Z00-00t-positive-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[Z00:00t]")
};

declare
    %test:args("2012-06-26T12:00:00.000-10:00")
    %test:assertEquals("W")
function fd:format-dateTime-ZZ-negative-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[ZZ]")
};

declare
    %test:args("2012-06-26T12:00:00.000-05:00")
    %test:assertEquals("R")
function fd:format-dateTime-ZZ-negative-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[ZZ]")
};

declare
    %test:args("2012-06-26T12:00:00.000+00:00")
    %test:assertEquals("Z")
function fd:format-dateTime-ZZ-zero($date as xs:dateTime) {
    format-dateTime($date, "[ZZ]")
};

declare
    %test:args("2012-06-26T12:00:00.000+05:30")
    %test:assertEquals("+05:30")
function fd:format-dateTime-ZZ-positive-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[ZZ]")
};

declare
    %test:args("2012-06-26T12:00:00.000+13:00")
    %test:assertEquals("+13:00")
function fd:format-dateTime-ZZ-positive-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[ZZ]")
};

declare
    %test:pending("[ZN] is not yet supported")
    %test:args("2012-06-26T12:00:00.000-10:00")
    %test:assertEquals("HST")
function fd:format-dateTime-ZN-negative-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[ZN]", (), (), "us")
};

declare
    %test:pending("[ZN] is not yet supported")
    %test:args("2012-06-26T12:00:00.000-05:00")
    %test:assertEquals("EST")
function fd:format-dateTime-ZN-negative-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[ZN]", (), (), "us")
};

declare
    %test:pending("[ZN] is not yet supported")
    %test:args("2012-06-26T12:00:00.000+00:00")
    %test:assertEquals("GMT")
function fd:format-dateTime-ZN-zero($date as xs:dateTime) {
    format-dateTime($date, "[ZN]", (), (), "us")
};

declare
    %test:pending("[ZN] is not yet supported")
    %test:args("2012-06-26T12:00:00.000+05:30")
    %test:assertEquals("IST")
function fd:format-dateTime-ZN-positive-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[ZN]", (), (), "us")
};

declare
    %test:pending("[ZN] is not yet supported")
    %test:args("2012-06-26T12:00:00.000+13:00")
    %test:assertEquals("+13:00")
function fd:format-dateTime-ZN-positive-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[ZN]", (), (), "us")
};

declare
    %test:pending("[ZN] is not yet supported")
    %test:args("2012-06-26T12:00:00.000-10:00")
    %test:assertEquals("06:00 EST")
function fd:format-dateTime-ZN-NY-negative-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[H00]:[M00] [ZN]", (), (), "America/New_York")
};

declare
    %test:pending("[ZN] is not yet supported")
    %test:args("2012-06-26T12:00:00.000-05:00")
    %test:assertEquals("12:00 EST")
function fd:format-dateTime-ZN-NY-negative-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[H00]:[M00] [ZN]", (), (), "America/New_York")
};

declare
    %test:pending("[ZN] is not yet supported")
    %test:args("2012-06-26T12:00:00.000+00:00")
    %test:assertEquals("07:00 EST")
function fd:format-dateTime-ZN-NY-zero($date as xs:dateTime) {
    format-dateTime($date, "[H00]:[M00] [ZN]", (), (), "America/New_York")
};

declare
    %test:pending("[ZN] is not yet supported")
    %test:args("2012-06-26T12:00:00.000+05:30")
    %test:assertEquals("01:30 EST")
function fd:format-dateTime-ZN-NY-positive-single-digit($date as xs:dateTime) {
    format-dateTime($date, "[H00]:[M00] [ZN]", (), (), "America/New_York")
};

declare
    %test:pending("[ZN] is not yet supported")
    %test:args("2012-06-26T12:00:00.000+13:00")
    %test:assertEquals("18:00 EST")
function fd:format-dateTime-ZN-NY-positive-double-digit($date as xs:dateTime) {
    format-dateTime($date, "[H00]:[M00] [ZN]", (), (), "America/New_York")
};

declare
    %test:args("17:45:50")
    %test:assertEquals("17:45:50")
    %test:args("09:45:50")
    %test:assertEquals("09:45:50")
function fd:simple-time($time as xs:time) {
    format-time($time, "[H00]:[m00]:[s]")
};

declare
    %test:args("17:45:50")
    %test:assertEquals("05:45 pm")
    %test:args("09:45:50")
    %test:assertEquals("09:45 am")
function fd:time-am-pm($time as xs:time) {
    format-time($time, "[h00]:[m00] [P]")
};

declare
    %test:assertError
function fd:date-format-in-format-time() {
    format-time(current-time(), "[Y]")
};

declare
    %test:assertError
function fd:time-format-in-format-date() {
    format-date(current-dateTime(), "[H]")
};

declare
    %test:args("2012-06-27Z")
    %test:assertEquals("Mittwoch, 27. Juni 2012")
    %test:args("1970-10-07Z")
    %test:assertEquals("Mittwoch, 7. Oktober 1970")
function fd:language-de($date as xs:date) {
    format-date($date, "[FNn], [D1o] [MNn] [Y]", "de", (), ())
};

declare
    %test:args("2012-06-01Z")
    %test:assertEquals("пятница, 1 июня 2012")
    %test:args("1970-10-07Z")
    %test:assertEquals("среда, 7 октября 1970")
function fd:language-ru($date as xs:date) {
    format-date($date, "[FNn], [D1o] [MNn] [Y]", "ru", (), ())
};

declare
%test:args("2012-06-01Z")
%test:assertEquals("vendredi, 1er juin 2012")
%test:args("1970-10-07Z")
%test:assertEquals("mercredi, 7 octobre 1970")
function fd:language-fr($date as xs:date) {
    format-date($date, "[FNn], [D1o] [MNn] [Y]", "fr", (), ())
};

declare
    %test:args("2018-05-21Z")
    %test:assertEquals("Monday")
    %test:args("2018-05-22Z")
    %test:assertEquals("Tuesday")
    %test:args("2018-05-23Z")
    %test:assertEquals("Wednesday")
    %test:args("2018-05-24Z")
    %test:assertEquals("Thursday")
    %test:args("2018-05-25Z")
    %test:assertEquals("Friday")
    %test:args("2018-05-26Z")
    %test:assertEquals("Saturday")
    %test:args("2018-05-27Z")
    %test:assertEquals("Sunday")
function fd:written-day-en($date-str as xs:string) {
    format-date(xs:date($date-str), "[FNn]", "en", (), ())
};


Reformat the array built-in function definitions.

xquery version "3.1";
(:~
 : XPath and XQuery Functions and Operators: Functions that Operate on Arrays
 :
 : @see https://www.w3.org/TR/2017/REC-xpath-functions-31-20170321/
 : @see https://qt4cg.org/branch/master/xpath-functions-40/Overview.html
 :
 : This software includes material copied from or derived from the XPath and
 : XQuery Functions and Operators 3.1 specifications. Copyright © 2017 W3C®
 : (MIT, ERCIM, Keio, Beihang).
 :)
module namespace array = "http://www.w3.org/2005/xpath-functions/array";

declare namespace a = "http://reecedunn.co.uk/xquery/annotations";
declare namespace o = "http://reecedunn.co.uk/xquery/options";

declare option o:requires "xpath-functions/3.1";

declare %a:since("xpath-functions", "3.1-20170321") function array:append(
  $array as array(*),
  $appendage as item()*
) as array(*) external;

declare %a:since("xpath-functions", "3.1-20170321") function array:filter(
  $array as array(*),
  $function as function(item()*) as xs:boolean
) as array(*) external;

declare %a:since("xpath-functions", "3.1-20170321") function array:flatten(
  $input as item()*
) as item()* external;

declare %a:since("xpath-functions", "3.1-20170321") function array:fold-left(
  $array as array(*),
  $zero as item()*,
  $function as function(item()*, item()*) as item()*
) as item()* external;

declare %a:since("xpath-functions", "3.1-20170321") function array:fold-right(
  $array as array(*),
  $zero as item()*,
  $function as function(item()*, item()*) as item()*
) as item()* external;

declare %a:since("xpath-functions", "3.1-20170321") function array:for-each(
  $array as array(*),
  $action as function(item()*) as item()*
) as array(*) external;

declare %a:since("xpath-functions", "3.1-20170321") function array:for-each-pair(
  $array1 as array(*),
  $array2 as array(*),
  $function as function(item()*, item()*) as item()*
) as array(*) external;

declare %a:since("xpath-functions", "3.1-20170321") function array:get(
  $array as array(*),
  $position as xs:integer
) as item()* external;

declare %a:since("xpath-functions", "3.1-20170321") function array:head(
  $array as array(*)
) as item()* external;

declare %a:since("xpath-functions", "3.1-20170321") function array:insert-before(
  $array as array(*),
  $position as xs:integer,
  $member as item()*
) as array(*) external;

declare %a:since("xpath-functions", "3.1-20170321") function array:join(
  $arrays as array(*)*
) as array(*) external;

declare %a:since("xpath-functions", "4.0-20210113") function array:partition(
  $input as item()*,
  $break-when as function(item()*, item()) as xs:boolean
) as array(*)+ external;

declare %a:since("xpath-functions", "3.1-20170321") function array:put(
  $array as array(*),
  $position as xs:integer,
  $member as item()*
) as array(*) external;

declare %a:since("xpath-functions", "3.1-20170321") function array:remove(
  $array as array(*),
  $positions as xs:integer*
) as array(*) external;

declare %a:since("xpath-functions", "4.0-20210113") function array:replace(
  $array as array(*),
  $position as xs:integer,
  $action as function(item()*) as item()*
) as array(*) external;

declare %a:since("xpath-functions", "3.1-20170321") function array:reverse(
  $array as array(*)
) as array(*) external;

declare %a:since("xpath-functions", "3.1-20170321") function array:size(
  $array as array(*)
) as xs:integer external;

declare %a:since("xpath-functions", "4.0-20210113") function array:slice(
  $input as array(*),
  $start as xs:integer?,
  $end as xs:integer?,
  $step as xs:integer?
) as array(*) external;

declare %a:since("xpath-functions", "3.1-20170321") function array:sort(
  $array as array(*)
) as array(*) external;

declare %a:since("xpath-functions", "3.1-20170321") function array:sort(
  $array as array(*),
  $collation as xs:string?
) as array(*) external;

declare %a:since("xpath-functions", "3.1-20170321") function array:sort(
  $array as array(*),
  $collation as xs:string?,
  $key as function(item()*) as xs:anyAtomicType*
) as array(*) external;

declare %a:since("xpath-functions", "3.1-20170321") function array:subarray(
  $array as array(*),
  $start as xs:integer
) as array(*) external;

declare %a:since("xpath-functions", "3.1-20170321") function array:subarray(
  $array as array(*),
  $start as xs:integer,
  $length as xs:integer
) as array(*) external;

declare %a:since("xpath-functions", "3.1-20170321") function array:tail(
  $array as array(*)
) as array(*) external;

xquery version "3.1";
(:~
 : XPath and XQuery Functions and Operators: Functions that Operate on Arrays
 :
 : @see https://www.w3.org/TR/2017/REC-xpath-functions-31-20170321/
 : @see https://qt4cg.org/branch/master/xpath-functions-40/Overview.html
 :
 : This software includes material copied from or derived from the XPath and
 : XQuery Functions and Operators 3.1 specifications. Copyright © 2017 W3C®
 : (MIT, ERCIM, Keio, Beihang).
 :)
module namespace array = "http://www.w3.org/2005/xpath-functions/array";

declare namespace a = "http://reecedunn.co.uk/xquery/annotations";
declare namespace o = "http://reecedunn.co.uk/xquery/options";

declare option o:requires "xpath-functions/3.1";

declare %a:since("xpath-functions", "3.1-20170321") function array:append($array as array(*), $appendage as item()*) as array(*) external;
declare %a:since("xpath-functions", "3.1-20170321") function array:filter($array as array(*), $function as function(item()*) as xs:boolean) as array(*) external;
declare %a:since("xpath-functions", "3.1-20170321") function array:flatten($input as item()*) as item()* external;
declare %a:since("xpath-functions", "3.1-20170321") function array:fold-left($array as array(*), $zero as item()*, $function as function(item()*, item()*) as item()*) as item()* external;
declare %a:since("xpath-functions", "3.1-20170321") function array:fold-right($array as array(*), $zero as item()*, $function as function(item()*, item()*) as item()*) as item()* external;
declare %a:since("xpath-functions", "3.1-20170321") function array:for-each($array as array(*), $action as function(item()*) as item()*) as array(*) external;
declare %a:since("xpath-functions", "3.1-20170321") function array:for-each-pair($array1 as array(*), $array2 as array(*), $function as function(item()*, item()*) as item()*) as array(*) external;
declare %a:since("xpath-functions", "3.1-20170321") function array:get($array as array(*), $position as xs:integer) as item()* external;
declare %a:since("xpath-functions", "3.1-20170321") function array:head($array as array(*)) as item()* external;
declare %a:since("xpath-functions", "3.1-20170321") function array:insert-before($array as array(*), $position as xs:integer, $member as item()*) as array(*) external;
declare %a:since("xpath-functions", "3.1-20170321") function array:join($arrays as array(*)*) as array(*) external;
declare %a:since("xpath-functions", "4.0-20210113") function array:partition($input as item()*, $break-when as function(item()*, item()) as xs:boolean) as array(*)+ external;
declare %a:since("xpath-functions", "3.1-20170321") function array:put($array as array(*), $position as xs:integer, $member as item()*) as array(*) external;
declare %a:since("xpath-functions", "3.1-20170321") function array:remove($array as array(*), $positions as xs:integer*) as array(*) external;
declare %a:since("xpath-functions", "4.0-20210113") function array:replace($array as array(*), $position as xs:integer, $action as function(item()*) as item()*) as array(*) external;
declare %a:since("xpath-functions", "3.1-20170321") function array:reverse($array as array(*)) as array(*) external;
declare %a:since("xpath-functions", "3.1-20170321") function array:size($array as array(*)) as xs:integer external;
declare %a:since("xpath-functions", "4.0-20210113") function array:slice($input as array(*), $start as xs:integer?, $end as xs:integer?, $step as xs:integer?) as array(*) external;
declare %a:since("xpath-functions", "3.1-20170321") function array:sort($array as array(*)) as array(*) external;
declare %a:since("xpath-functions", "3.1-20170321") function array:sort($array as array(*), $collation as xs:string?) as array(*) external;
declare %a:since("xpath-functions", "3.1-20170321") function array:sort($array as array(*), $collation as xs:string?, $key as function(item()*) as xs:anyAtomicType*) as array(*) external;
declare %a:since("xpath-functions", "3.1-20170321") function array:subarray($array as array(*), $start as xs:integer) as array(*) external;
declare %a:since("xpath-functions", "3.1-20170321") function array:subarray($array as array(*), $start as xs:integer, $length as xs:integer) as array(*) external;
declare %a:since("xpath-functions", "3.1-20170321") function array:tail($array as array(*)) as array(*) external;