added missing import stmt

added missing import stmt

(:~
: This is the Care Services Discovery stored query registry
: @version 1.0
: @see https://github.com/openhie/openinfoman
:
:)
module namespace csd_mcs = "https://github.com/openhie/openinfoman/csd_mcs";
import module namespace csd_webconf =  "https://github.com/openhie/openinfoman/csd_webconf";
import module namespace csd_lsc = "https://github.com/openhie/openinfoman/csd_lsc" ;
import module namespace csd_psd = "https://github.com/openhie/openinfoman/csd_psd" ;
import module namespace csd_dm = "https://github.com/openhie/openinfoman/csd_dm" ;

declare namespace csd = "urn:ihe:iti:csd:2013";
declare default element  namespace   "urn:ihe:iti:csd:2013";

declare variable $csd_mcs:merged_services_doc := 'merged_services.xml';

declare function csd_mcs:store_exists() {
  db:is-xml($csd_webconf:db, $csd_mcs:merged_services_doc)
};

declare updating function csd_mcs:init_store() {
  db:add($csd_webconf:db, csd_dm:blank_directory(), $csd_mcs:merged_services_doc)
};

(:
: Merges together all documents registered with the document manager
:)
declare updating function csd_mcs:merge($dest,$sources) {

  (: Merges together all cached documents only
  for $name in csd_psd:registered_directories($db)
  return csd_lsc:refresh_doc(db:open($db,$csd_mcs:merged_services_doc),csd_lsc:get_cache($db,$name))
  :)
  let $dest_doc := csd_dm:open_document($dest)
  return
    if (exists($dest_doc))
    then
      for $name in $sources
      return if ($name != $dest) then
	csd_lsc:refresh_doc($dest_doc, csd_dm:open_document($name))
      else ()
    else ()

};

declare function csd_mcs:get() {
  db:open($csd_webconf:db,$csd_mcs:merged_services_doc)
};

declare updating function csd_mcs:empty() {
  db:replace($csd_webcond:db, $csd_mcs:merged_services_doc, csd_dm:blank_directory())
};

declare function csd_mcs:get_merge_doc_name() {
  let $name := 'merged_remote_services'
  return $name
};

(:~
: This is the Care Services Discovery stored query registry
: @version 1.0
: @see https://github.com/openhie/openinfoman
:
:)
module namespace csd_mcs = "https://github.com/openhie/openinfoman/csd_mcs";
import module namespace csd_lsc = "https://github.com/openhie/openinfoman/csd_lsc" ;
import module namespace csd_psd = "https://github.com/openhie/openinfoman/csd_psd" ;
import module namespace csd_dm = "https://github.com/openhie/openinfoman/csd_dm" ;

declare namespace csd = "urn:ihe:iti:csd:2013";
declare default element  namespace   "urn:ihe:iti:csd:2013";

declare variable $csd_mcs:merged_services_doc := 'merged_services.xml';

declare function csd_mcs:store_exists() {
  db:is-xml($csd_webconf:db, $csd_mcs:merged_services_doc)
};

declare updating function csd_mcs:init_store() {
  db:add($csd_webconf:db, csd_dm:blank_directory(), $csd_mcs:merged_services_doc)
};

(:
: Merges together all documents registered with the document manager
:)
declare updating function csd_mcs:merge($dest,$sources) {

  (: Merges together all cached documents only
  for $name in csd_psd:registered_directories($db)
  return csd_lsc:refresh_doc(db:open($db,$csd_mcs:merged_services_doc),csd_lsc:get_cache($db,$name))
  :)
  let $dest_doc := csd_dm:open_document($dest)
  return
    if (exists($dest_doc))
    then
      for $name in $sources
      return if ($name != $dest) then
	csd_lsc:refresh_doc($dest_doc, csd_dm:open_document($name))
      else ()
    else ()

};

declare function csd_mcs:get() {
  db:open($csd_webconf:db,$csd_mcs:merged_services_doc)
};

declare updating function csd_mcs:empty() {
  db:replace($csd_webcond:db, $csd_mcs:merged_services_doc, csd_dm:blank_directory())
};

declare function csd_mcs:get_merge_doc_name() {
  let $name := 'merged_remote_services'
  return $name
};


Initial handle remote attributes.

Initial handle remote attributes.

xquery version "3.1" encoding "UTF-8";

declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare namespace map = "http://www.w3.org/2005/xpath-functions/map";
declare namespace array = "http://www.w3.org/2005/xpath-functions/array";
declare namespace mapping = "http://docs.rackspace.com/identity/api/ext/MappingRules";
declare namespace xs = "http://www.w3.org/2001/XMLSchema";
declare namespace xsi = "http://www.w3.org/2001/XMLSchema-instance";

declare default element namespace "http://docs.rackspace.com/identity/api/ext/MappingRules";

declare option output:method "xml";
declare option output:indent "yes";

(: declare variable $__JSON__ external; :)
declare variable $__JSON__ external;
declare variable $policyJSON := parse-json($__JSON__);
declare variable $defaultAttributes as xs:string* := ('name','email','expire','domain','roles');

declare function mapping:convertValue($in as xs:string) as xs:string {
  replace($in,' ',' ')
};

declare function mapping:attributeFromValue ($attName as xs:string, $value as item()) as attribute()* {
  typeswitch ($value)
    case $s as xs:string return attribute {$attName} {mapping:convertValue($s)}
    case $b as xs:boolean return attribute {$attName} {mapping:convertValue(string($b))}
    case $a as array(*) return attribute {$attName} {string-join(for $i in $a?* return mapping:convertValue($i),' ')}
    case $o as map(*) return for $att in map:keys($o) return mapping:attributeFromValue($att, $o?($att))
    default return ()
};

declare function mapping:convertLocalAttribute($attribName as xs:string, $attribValue as item(), $userGroup as xs:boolean) as element() {
  element {$attribName} {
    mapping:attributeFromValue("value",$attribValue),
    if ($userGroup and $attribName = $defaultAttributes) then () else attribute {"xsi:type"} {"LocalAttribute"}
  }
};

declare function mapping:convertRemoteAttribute($remoteAttribute as item()) as element() {
  element {"attribute"} {mapping:attributeFromValue("", $remoteAttribute)}
};

<rules xmlns="http://docs.rackspace.com/identity/api/ext/MappingRules"
       xmlns:xs="http://www.w3.org/2001/XMLSchema"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
       {
       if (map:contains($policyJSON,"namespaces")) then
         let $namespaces := $policyJSON?namespaces
         for $key in map:keys($namespaces) return namespace {$key} {$namespaces?($key)}
       else ()
       }

       {
         for $rule in $policyJSON?rules?* return
         <rule>
             <local>
                 {
                   let $local := $rule?local
                   for $localGroupName in map:keys($local) return element {$localGroupName} {
                     if ($localGroupName != 'user') then attribute {"xsi:type"} {"LocalAttributeGroup"} else (),
                     let $localGroup := $local?($localGroupName)
                     for $attributeName in map:keys($localGroup) return
                       mapping:convertLocalAttribute($attributeName, $localGroup?($attributeName), $localGroupName = 'user')
                   }
                 }
             </local>
             {
               if (map:contains($rule,"remote")) then
               <remote>
                 { for $remoteAttribute in $rule?remote?* return mapping:convertRemoteAttribute($remoteAttribute) }
               </remote>
               else ()
             }
         </rule>
       }
</rules>

xquery version "3.1" encoding "UTF-8";

declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare namespace map = "http://www.w3.org/2005/xpath-functions/map";
declare namespace array = "http://www.w3.org/2005/xpath-functions/array";
declare namespace mapping = "http://docs.rackspace.com/identity/api/ext/MappingRules";
declare namespace xs = "http://www.w3.org/2001/XMLSchema";
declare namespace xsi = "http://www.w3.org/2001/XMLSchema-instance";

declare default element namespace "http://docs.rackspace.com/identity/api/ext/MappingRules";

declare option output:method "xml";
declare option output:indent "yes";

(: declare variable $__JSON__ external; :)
declare variable $__JSON__ := "{"rules":[{"remote":[{"regex":false,"name":"bar","multiValue":false},{"path":"'AWSPolicy'","regex":false,"multiValue":false}],"local":{"user":{"domain":"{D}","foo":"{0}","name":"{D}","email":"{D}","roles":"{D}","expire":"{D}"},"faws":{"policy":"{1}"}}},{"local":{"user":{},"faws":{"policy":"AWSPolicy2"}}}]}";
declare variable $policyJSON := parse-json($__JSON__);
declare variable $defaultAttributes as xs:string* := ('name','email','expire','domain','roles');

declare function mapping:convertValue($in as xs:string) as xs:string {
  replace($in,' ',' ')
};

declare function mapping:attributeFromValue ($attName as xs:string, $value as item()) as attribute()* {
  typeswitch ($value)
    case $s as xs:string return attribute {$attName} {mapping:convertValue($s)}
    case $b as xs:boolean return attribute {$attName} {mapping:convertValue(string($b))}
    case $a as array(*) return attribute {$attName} {string-join(for $i in $a?* return mapping:convertValue($i),' ')}
    case $o as map(*) return for $att in map:keys($o) return mapping:attributeFromValue($att, $o?($att))
    default return ()
};

declare function mapping:convertLocalAttribute($attribName as xs:string, $attribValue as item(), $userGroup as xs:boolean) as element() {
  element {$attribName} {
    mapping:attributeFromValue("value",$attribValue),
    if ($userGroup and $attribName = $defaultAttributes) then () else attribute {"xsi:type"} {"LocalAttribute"}
  }
};

<rules xmlns="http://docs.rackspace.com/identity/api/ext/MappingRules"
       xmlns:xs="http://www.w3.org/2001/XMLSchema"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
       {
       if (map:contains($policyJSON,"namespaces")) then
         let $namespaces := $policyJSON?namespaces
         for $key in map:keys($namespaces) return namespace {$key} {$namespaces?($key)}
       else ()
       }

       {
         for $rule in $policyJSON?rules?* return
         <rule>
             <local>
                 {
                   let $local := $rule?local
                   for $localGroupName in map:keys($local) return element {$localGroupName} {
                     if ($localGroupName != 'user') then attribute {"xsi:type"} {"LocalAttributeGroup"} else (),
                     let $localGroup := $local?($localGroupName)
                     for $attributeName in map:keys($localGroup) return
                       mapping:convertLocalAttribute($attributeName, $localGroup?($attributeName), $localGroupName = 'user')
                   }
                 }
             </local>
         </rule>
       }
</rules>


Fix a bug with a missing namespace declaration in a RESTXQ Example

xquery version "3.0";

module namespace ex = "http://example/restxq/2";

import module namespace rest = "http://exquery.org/ns/restxq";
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare namespace http = "http://expath.org/ns/http-client";

declare
    %rest:GET
    %rest:HEAD
    %rest:POST
    %rest:PUT
    %rest:DELETE
    %output:method("html5")
function ex:not-found() {
    (
    <rest:response>
        <http:response status="404"/>
    </rest:response>
    ,

        <title>Document not found!</title>

Sorry, we could not find the document that you requested :-(

    )
};

xquery version "3.0";

module namespace ex = "http://example/restxq/2";

import module namespace rest = "http://exquery.org/ns/restxq";
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";

declare
    %rest:GET
    %rest:HEAD
    %rest:POST
    %rest:PUT
    %rest:DELETE
    %output:method("html5")
function ex:not-found() {
    (
    <rest:response>
        <http:response status="404"/>
    </rest:response>
    ,

        <title>Document not found!</title>

Sorry, we could not find the document that you requested :-(

    )
};


Updated parse-xml:parse()'s documentation

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.
 :

 :
 : @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
 : @project data processing/data converters
 :
 :)
module namespace parse-xml = "http://www.zorba-xquery.com/modules/xml";

import schema namespace parse-xml-options = "http://www.zorba-xquery.com/modules/xml-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.0";

(:~
 : 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.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.
 :

 :
 :

 : <strip-boundary-space/> - if present, it will enable the removal of blank nodes from the input.
 :

 :
 :

 : <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). 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 two 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.
 :

 :
 :

 : <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.
 :

 :
 :

 :
 :
 : @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 parse-xml:parse(
  $xml-string as xs:string?,
  $options as element()?) as node()* 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.
 :

 :
 : @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
 : @project data processing/data converters
 :
 :)
module namespace parse-xml = "http://www.zorba-xquery.com/modules/xml";

import schema namespace parse-xml-options = "http://www.zorba-xquery.com/modules/xml-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.0";

(:~
 : 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.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.
 :

 :
 :

 : <strip-boundary-space/> - if present, it will enable LibXml2's XML_PARSE_NOBLANKS option,
 : which will remove all the blank nodes from the input.
 :

 :
 :

 : <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 <DTDValidate/> or the <parseExternalParsedEntity/>
 : 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 <DTDLoad/> 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 <schemaValidate/> or the <parseExternalParsedEntity>
 : option. Doing so will raise a zerr:ZXQD0003 error.
 :

 :
 :

 : <DTD-load/> - if present, it will enable LibXml2's XML_PARSE_DTDLOAD option which
 : will load the external subset.
 :

 :
 :

 : <default-DTD-attributes/> - if present, it will enable LibXml2's XML_PARSE_DTDATTR option,
 : which enables 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). 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 <schemaValidate/> or the <DTDValidate/>
 : option. Doing so will raise a zerr:ZXQD0003 error.
 : The <parse-external-parsed-entity/> option has two 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.
 :

 :
 :

 : <substitute-entities/> - if present, it will enable LibXml2's XML_PARSE_NOENT option,
 : which tells the parser to substitute entities.
 :

 :
 :

 : <xinclude-substitutions/> - if present, it will enable LibXml2's XML_PARSE_XINCLUDE option,
 : which will implement the XInclude substitution.
 :

 :
 :

 : <remove-redundant-ns/> - if present, it will enable LibXml2's XML_PARSE_NSCLEAN option,
 : which will remove redundant namespaces declarations.
 :

 :
 :

 : <no-CDATA/> - if present, it will enable LibXml2's XML_PARSE_NOCDATA option,
 : which will tell the parser to merge CDATA as text nodes.
 :

 :
 :

 : <no-xinclude-nodes/> - if present, it will enable LibXml2's XML_PARSE_NOXINCNODE option,
 : which will tell parser not to generate XINCLUDE START/END nodes.
 :

 :
 :

 :
 :
 : @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.
 :
 :)

declare function parse-xml:parse(
  $xml-string as xs:string?,
  $options as element()?) as node()* external;


[FIX] XQUnit: Namespace in existing test fixed

module namespace _ = '_';

(:~ Function demonstrating a successful test. :)
declare %unit:test function _:assert-success() {
  unit:assert(<a/>)
};

(:~ Function demonstrating an expected failure. :)
declare %unit:test("expected", "err:FORG0001") function _:expected-failure() {
  1 + <a/>
};

module namespace _ = '_';

(:~ Function demonstrating a successful test. :)
declare %unit:test function _:assert-success() {
  unit:assert(<a/>)
};

(:~ Function demonstrating an expected failure. :)
declare %unit:test("expected", "FORG0001") function _:expected-failure() {
  1 + <a/>
};


[ignore] small fix: /webdav URIs should be ignored by the urlrewriter

svn path=/trunk/eXist/; revision=8395

(: 	This is the main controller for the web application. It is called from the
	XQueryURLRewrite filter configured in web.xml. :)
xquery version "1.0";

import module namespace request="http://exist-db.org/xquery/request";

let $uri := request:get-uri()
let $context := request:get-context-path()
let $path := substring-after($uri, $context)
let $name := replace($uri, '^.*/([^/]+)$', '$1')
let $query := request:get-parameter("q", ())
return
	(: redirect webapp root to index.xml :)
	if ($path eq '/') then
		<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
			<redirect url="index.xml"/>
		</dispatch>
	(: /rest and /webdav will be ignored :)
	else if (matches($path, "/(rest|webdav|cocoon)")) then
		<ignore xmlns="http://exist.sourceforge.net/NS/exist">
            <cache-control cache="yes"/>
		</ignore>
	(: redirect sandbox root to sandbox.xql :)
	else if (matches($uri, "sandbox/?$")) then
		<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
			<redirect url="sandbox.xql"/>
		</dispatch>
	else if ($name = ('search.xql', 'functions.xql')) then
		<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
			<forward url="{$path}">
				<!-- query results are passed to XSLT servlet via request attribute -->
				<set-attribute name="xquery.attribute"
					value="xslt.model"/>
			</forward>
			<view>
				<forward servlet="XSLTServlet">
					<set-attribute name="xslt.input"
						value="xslt.model"/>
					<set-attribute name="xslt.stylesheet"
						value="stylesheets/db2html.xsl"/>
				</forward>
			</view>
		</dispatch>
	else if ($name eq 'acronyms.xql') then
		<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
			<!-- query results are passed to XSLT servlet via request attribute -->
			<set-attribute name="xquery.attribute"
				value="xslt.model"/>
			<view>
				<forward servlet="XSLTServlet">
					<set-attribute name="xslt.input"
						value="xslt.model"/>
					<set-attribute name="xslt.stylesheet"
						value="xquery/stylesheets/acronyms.xsl"/>
				</forward>
				<forward servlet="XSLTServlet">
					<set-attribute name="xslt.input"
						value=""/>
					<set-attribute name="xslt.stylesheet"
						value="stylesheets/db2html.xsl"/>
				</forward>
			</view>
		</dispatch>
	else if ($name eq 'biblio.xql') then
		let $display := request:get-parameter("display", "overview")
		let $xsl :=
			if ($display eq "details") then "detailed.xsl" else "overview.xsl"
		return
			<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
				<set-attribute name="xquery.attribute" value="xslt.model"/>
				<view>
				<forward servlet="XSLTServlet">
					<set-attribute name="xslt.input"
						value="xslt.model"/>
					<set-attribute name="xslt.stylesheet"
						value="xquery/stylesheets/{$xsl}"/>
				</forward>
				<forward servlet="XSLTServlet">
					<set-attribute name="xslt.input"
						value=""/>
					<set-attribute name="xslt.stylesheet"
						value="stylesheets/doc2html-2.xsl"/>
				</forward>

				</view>
			</dispatch>
	else if ($name eq 'applications.xml') then
		<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
			<!-- query results are passed to XSLT servlet via request attribute -->
			<set-attribute name="xquery.attribute"
				value="xslt.model"/>
			<view>
				<forward servlet="XSLTServlet">
					<set-attribute name="xslt.input"
						value="xslt.model"/>
					<set-attribute name="xslt.stylesheet"
						value="apps/applications.xsl"/>
				</forward>
				<forward servlet="XSLTServlet">
					<set-attribute name="xslt.input"
						value=""/>
					<set-attribute name="xslt.stylesheet"
						value="stylesheets/db2html.xsl"/>
				</forward>
			</view>
		</dispatch>
	(: the following xml files use different stylesheets :)
	else if ($name = ('index.xml', 'examples.xml', 'roadmap.xml', 'facts.xml', 'biblio.xml')) then
		let $stylesheet :=
			if ($name eq 'roadmap.xml') then
				"stylesheets/roadmap.xsl"
			else if ($name eq "facts.xml") then
				"stylesheets/facts.xsl"
			else
				"stylesheets/doc2html-2.xsl"
		return
			<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
				<view>
					<forward servlet="XSLTServlet">
						<set-attribute name="xslt.stylesheet"
							value="{$stylesheet}"/>
					</forward>
				</view>
				<cache-control cache="yes"/>
			</dispatch>
	else if (ends-with($uri, '.xml')) then
		(: 	check if the requested document was selected from a query result.
			if yes, pass it to docs.xql to get the match highlighting. :)
		if ($query) then
			let $docName := replace($uri, '^.*/([^/]+)$', '$1')
			return
				<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
					<forward url="docs.xql">
						<add-parameter name="path" value="/db/xqdocs/{$docName}"/>
					</forward>
				</dispatch>
		else
			<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
				<view>
					<forward servlet="XSLTServlet">
						<set-attribute name="xslt.stylesheet"
							value="stylesheets/db2html.xsl"/>
					</forward>
				</view>
            	<cache-control cache="yes"/>
			</dispatch>
	else
		<ignore xmlns="http://exist.sourceforge.net/NS/exist">
            <cache-control cache="yes"/>
		</ignore>

(: 	This is the main controller for the web application. It is called from the
	XQueryURLRewrite filter configured in web.xml. :)
xquery version "1.0";

import module namespace request="http://exist-db.org/xquery/request";

let $uri := request:get-uri()
let $context := request:get-context-path()
let $path := substring-after($uri, $context)
let $name := replace($uri, '^.*/([^/]+)$', '$1')
let $query := request:get-parameter("q", ())
return
	(: redirect webapp root to index.xml :)
	if ($path eq '/') then
		<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
			<redirect url="index.xml"/>
		</dispatch>
	(: /rest and /webdav will be ignored :)
	else if (matches($path, "/(rest|webdav$|cocoon)")) then
		<ignore xmlns="http://exist.sourceforge.net/NS/exist">
            <cache-control cache="yes"/>
		</ignore>
	(: redirect sandbox root to sandbox.xql :)
	else if (matches($uri, "sandbox/?$")) then
		<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
			<redirect url="sandbox.xql"/>
		</dispatch>
	else if ($name = ('search.xql', 'functions.xql')) then
		<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
			<forward url="{$path}">
				<!-- query results are passed to XSLT servlet via request attribute -->
				<set-attribute name="xquery.attribute"
					value="xslt.model"/>
			</forward>
			<view>
				<forward servlet="XSLTServlet">
					<set-attribute name="xslt.input"
						value="xslt.model"/>
					<set-attribute name="xslt.stylesheet"
						value="stylesheets/db2html.xsl"/>
				</forward>
			</view>
		</dispatch>
	else if ($name eq 'acronyms.xql') then
		<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
			<!-- query results are passed to XSLT servlet via request attribute -->
			<set-attribute name="xquery.attribute"
				value="xslt.model"/>
			<view>
				<forward servlet="XSLTServlet">
					<set-attribute name="xslt.input"
						value="xslt.model"/>
					<set-attribute name="xslt.stylesheet"
						value="xquery/stylesheets/acronyms.xsl"/>
				</forward>
				<forward servlet="XSLTServlet">
					<set-attribute name="xslt.input"
						value=""/>
					<set-attribute name="xslt.stylesheet"
						value="stylesheets/db2html.xsl"/>
				</forward>
			</view>
		</dispatch>
	else if ($name eq 'biblio.xql') then
		let $display := request:get-parameter("display", "overview")
		let $xsl :=
			if ($display eq "details") then "detailed.xsl" else "overview.xsl"
		return
			<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
				<set-attribute name="xquery.attribute" value="xslt.model"/>
				<view>
				<forward servlet="XSLTServlet">
					<set-attribute name="xslt.input"
						value="xslt.model"/>
					<set-attribute name="xslt.stylesheet"
						value="xquery/stylesheets/{$xsl}"/>
				</forward>
				<forward servlet="XSLTServlet">
					<set-attribute name="xslt.input"
						value=""/>
					<set-attribute name="xslt.stylesheet"
						value="stylesheets/doc2html-2.xsl"/>
				</forward>

				</view>
			</dispatch>
	else if ($name eq 'applications.xml') then
		<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
			<!-- query results are passed to XSLT servlet via request attribute -->
			<set-attribute name="xquery.attribute"
				value="xslt.model"/>
			<view>
				<forward servlet="XSLTServlet">
					<set-attribute name="xslt.input"
						value="xslt.model"/>
					<set-attribute name="xslt.stylesheet"
						value="apps/applications.xsl"/>
				</forward>
				<forward servlet="XSLTServlet">
					<set-attribute name="xslt.input"
						value=""/>
					<set-attribute name="xslt.stylesheet"
						value="stylesheets/db2html.xsl"/>
				</forward>
			</view>
		</dispatch>
	(: the following xml files use different stylesheets :)
	else if ($name = ('index.xml', 'examples.xml', 'roadmap.xml', 'facts.xml', 'biblio.xml')) then
		let $stylesheet :=
			if ($name eq 'roadmap.xml') then
				"stylesheets/roadmap.xsl"
			else if ($name eq "facts.xml") then
				"stylesheets/facts.xsl"
			else
				"stylesheets/doc2html-2.xsl"
		return
			<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
				<view>
					<forward servlet="XSLTServlet">
						<set-attribute name="xslt.stylesheet"
							value="{$stylesheet}"/>
					</forward>
				</view>
				<cache-control cache="yes"/>
			</dispatch>
	else if (ends-with($uri, '.xml')) then
		(: 	check if the requested document was selected from a query result.
			if yes, pass it to docs.xql to get the match highlighting. :)
		if ($query) then
			let $docName := replace($uri, '^.*/([^/]+)$', '$1')
			return
				<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
					<forward url="docs.xql">
						<add-parameter name="path" value="/db/xqdocs/{$docName}"/>
					</forward>
				</dispatch>
		else
			<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
				<view>
					<forward servlet="XSLTServlet">
						<set-attribute name="xslt.stylesheet"
							value="stylesheets/db2html.xsl"/>
					</forward>
				</view>
            	<cache-control cache="yes"/>
			</dispatch>
	else
		<ignore xmlns="http://exist.sourceforge.net/NS/exist">
            <cache-control cache="yes"/>
		</ignore>


Additional comments.

Additional comments.

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
 : @project data processing/data converters
 :
 :)
module namespace x = "http://www.zorba-xquery.com/modules/xml";

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.0";

(:~
 : 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 http://www.w3.org/TR/xml-c14n .
 :
 :

 : 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 http://www.w3.org/TR/xml-c14n .
 : 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
 : http://xmlsoft.org/html/libxml-parser.html#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.
 :        The options available are the following:
 :        <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()
  ) 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
 : @project data processing/data converters
 :
 :)
module namespace x = "http://www.zorba-xquery.com/modules/xml";

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.0";

(:~
 : 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.
 :
 :

 : 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.
 :
 :

 : 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.
 :        The options available are the following:
 :        <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()
  ) as xs:string external;


Adding mandatory testcases

Adding mandatory testcases

xquery version "3.1";

(:~
 : Tests to check if the reported line numbers for errors are correct:
 :
 : * if a function is called dynamically. In previous eXist versions, the
 : line number always pointed to the place where the function item was created,
 : not the actual function body
 : * if newlines occur in string literals, constructors or comments
 :)
module namespace et="http://exist-db.org/xquery/test/error-test";

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

(: Causes an error when called :)
declare function et:test($a) {
    $a + "bla"
};

(: May cause an error when called :)
declare function et:test2($a) {
    $a/foo
};

declare
    %test:assertEquals(17)
function et:dynamically-called-function() {
    let $fn := function-lookup(xs:QName("et:test"), 1)
    return
        try {
            $fn(1)
        } catch * {
            $err:line-number
        }
};

declare
    %test:assertEquals(22)
function et:dynamically-called-function-path-expr() {
    let $fn := function-lookup(xs:QName("et:test2"), 1)
    return
        try {
            $fn(1)
        } catch * {
            $err:line-number
        }
};

declare
    %test:assertEquals(53)
function et:inline-function-call() {
    let $fn := function($a) {
        $a + "bla"
    }
    return
        try {
            $fn(1)
        } catch * {
            $err:line-number
        }
};

declare
    %test:assertEquals(17)
function et:function-reference-call() {
    let $fn := et:test#1
    return
        try {
            $fn(1)
        } catch * {
            $err:line-number
        }
};

declare
    %test:assertEquals(87)
function et:nl-in-string-literal() {
    try {
        let $foo := "bar

        "
        return
            element x {
                attribute y { "1" },
                (: next line will generate dynamic error :)
                element z { sum($foo) }
            }
    } catch * {
        $err:line-number
    }
};

declare
    %test:assertEquals(106)
function et:nl-in-string-constructor() {
    try {
        let $foo := ``[bar

        ]``
        return
            element x {
                attribute y { "1" },
                (: next line will generate dynamic error :)
                element z { sum($foo) }
            }
    } catch * {
        $err:line-number
    }
};

declare
    %test:assertEquals(124)
function et:nl-in-element-constructor() {
    try {
        let $foo :=
            <test>
                <p>foo

                </p>
            </test>
        return
            "abc"/node()
    } catch * {
        $err:line-number
    }
};

declare
    %test:assertEquals(137)
function et:nl-in-comment() {
    try {
        (: This is a

        multiline comment :)
        "abc"/node()
    } catch * {
        $err:line-number
    }
};

declare
    %test:assertXPath("/error[@line='2'][contains(., 'Invalid qname console:log')]")
function et:compile-query-unknown-func() {
    let $query := ``[
        console:log('foo')
    ]``
    return
        util:compile-query($query, "xmldb:exist://")
};

declare
    %test:assertXPath("/self::info[@result='pass']")
function et:compile-query-variable-decl-pass() {
    let $query := ``[
        declare variable $v := map {
            "a": "b",
            "f": function() {
                ()
            }
        };
        $v?f()
    ]``
    return
        util:compile-query($query, "xmldb:exist://")
};

(: Should not result in an NPE, see https://github.com/eXist-db/exist/pull/1520#issuecomment-604514099 :)
declare
    %test:assertXPath("/error[@line='5'][contains(., 'Invalid qname console:log')]")
function et:compile-query-variable-decl() {
    let $query := ``[
        declare variable $v := map {
            "a": "b",
            "f": function() {
                console:log('foo')
            }
        };
        $v?f()
    ]``
    return
        util:compile-query($query, "xmldb:exist://")
};

declare
    %test:assertXPath("/error[@line='6'][contains(., 'local:test')]")
function et:compile-query-func-decl() {
    let $query := ``[
        declare function local:test($x) {
            $x
        };

        local:test(123, 345)
    ]``
    return
        util:compile-query($query, "xmldb:exist://")
};

(: https://github.com/eXist-db/exist/issues/3450 :)
declare
    %test:assertEquals(208)
function et:issue3450a() {
    try {
    (:
    empty
    :)
        if (map { "foo": "bar" } eq 1) then "yay" else "boo"
    } catch * {
        $err:line-number
    }
};

(: https://github.com/eXist-db/exist/issues/3450 :)
declare
    %test:assertEquals(220)
function et:issue3450b() {
    try {
        if ("a" eq 1) then "yay" else "boo"
    } catch * {
        $err:line-number
    }
};

(: https://github.com/eXist-db/exist/issues/3462 :)
declare
    %test:assertEquals(233)
function et:issue3462a() {
    try {
        map {
            "foo": ["bar", "baz"]
        }[?foo eq "bar"]
    } catch * {
        $err:line-number
    }
};

declare
    %test:assertEquals(248)
function et:issue3462b() {
    try {
            map {
                "foo":
                    map {
                        "bar": "baz"
                    }
            }[?foo eq "bar"]
    } catch * {
        $err:line-number
    }
};

(: https://github.com/eXist-db/exist/issues/3473 :)
declare
    %test:assertEquals(259)
function et:issue3473a() {
    try {
        1 eq "2"
    } catch * {
        $err:line-number
    }
};

(: https://github.com/eXist-db/exist/issues/3473 :)
declare
    %test:assertEquals(270)
function et:issue3473b() {
    try {
        1 = "2"
    } catch * {
        $err:line-number
    }
};

(: https://github.com/eXist-db/exist/issues/3473 :)
declare
    %test:assertEquals(301)
function et:issue3473c() {
    try {
        let $colors :=
                 map {
                     "blue": "#2d7ff9",
                     "cyan": "#18bfff",
                     "gray": "#666",
                     "grayDark": "666",
                     "green": "#20c933",
                     "greenDark": "20c933",
                     "orange": "#ff6f2c",
                     "pink": "#ff08c2",
                     "pinkDark": "ff08c2",
                     "purple": "#8b46ff",
                     "red": "#f82b60",
                     "redDarker": "f82b60",
                     "teal": "#20d9d2",
                     "yellow": "#fcb400",
                     "yellowDark": "fcb400"
                 }

             return
                error()
    } catch * {
        $err:line-number
    }
};

(: https://github.com/eXist-db/exist/issues/3474 :)
declare
    %test:pending("to be addressed in another PR")
    %test:assertEquals(312)
function et:issue3474() {
    try {
        element foo { map { "x": "y" } }
    } catch * {
        $err:line-number
    }
};


[bugfix] Re-enable match highlighting in XQuery sandbox. Port of rev. 7255 from trunk.

svn path=/branches/eXist-stable-1.2/; revision=7280

xquery version "1.0";
(: $Id$ :)

declare namespace sandbox="http://exist-db.org/xquery/sandbox";
declare namespace system="http://exist-db.org/xquery/system";

import module namespace util="http://exist-db.org/xquery/util";
import module namespace request="http://exist-db.org/xquery/request";
import module namespace session="http://exist-db.org/xquery/session";
import module namespace xdb="http://exist-db.org/xquery/xmldb";

declare option exist:serialize "method=xhtml indent=no highlight-matches=elements";

(:~ Points to the location of the xml-highlight.xsl stylesheet stored in the database :)
declare variable $sandbox:XML_HIGHLIGHT_STYLE { "/db/sandbox/xml-highlight.xsl" };

(:~ The required stylesheets were not found in the db. Try to import them. :)
declare function sandbox:import-stylesheets() as xs:string* {
    let $home := system:get-exist-home()
    let $pathSep := util:system-property("file.separator")
    let $dir :=
			if (doc-available(concat("file:///", system:get-module-load-path(), "/stylesheets/xml-highlight.xsl")))
			then
				concat(system:get-module-load-path(), $pathSep, "stylesheets")
        	else if(ends-with($home, "WEB-INF")) then
        	    concat(substring-before($home, "WEB-INF"), "sandbox", $pathSep, "stylesheets")
        	else
               concat($home, $pathSep, "webapp", $pathSep, "sandbox", $pathSep, "stylesheets")
    let $col := xdb:create-collection("/db", "sandbox")
    return
        concat("Imported: ", xdb:store-files-from-pattern($col, $dir, "*.xsl", "text/xml"))
};

(:~ Check for stylesheets required for the application. Try to import them if they could not be found. :)
declare function sandbox:check-paths() as item()* {
    if (not(doc-available($sandbox:XML_HIGHLIGHT_STYLE))) then
        let $dummy := sandbox:import-stylesheets()
        return
            if (not(doc-available($sandbox:XML_HIGHLIGHT_STYLE))) then
                concat($sandbox:XML_HIGHLIGHT_STYLE, " not found! Please store this file into ",
                    "the database collection or the application will not work properly.")
            else ()
    else
        You can also try out an updated XQuery sandbox.
        It does not work with all browsers yet though.
};

declare function sandbox:init-slots() as element()+ {
    for $i in 1 to 10 return

[{$i}] --- empty ---

};

(:~ Export the current query results into a new document in the database. :)
declare function sandbox:export($docName as xs:string) as element() {
    let $collection := request:get-parameter("collection", ())
    let $wrapper0 := request:get-parameter("wrapper", ())
    let $wrapper := if ($wrapper0) then $wrapper0 else "exist:result"
    let $cached := session:get-attribute("cached")
    return
        if (empty($cached)) then
            <error>No query results to export!</error>
        else
            let $newDoc :=
                element { $wrapper } { $cached }
            return
                util:catch("java.lang.Exception",
                    (let $dummy := xdb:store($collection, $docName, $newDoc, "text/xml") return <ajax-response/>),
                    <error>{$util:exception-message}</error>
                )
};

(:~ Append the given query to the query examples file or update an existing old query. :)
declare function sandbox:save-query($query as xs:string, $description as xs:string) as element() {
    let $root0 := /example-queries
    let $root :=
        if ($root0) then
            $root0
        else
            xdb:store("/db", "examples.xml", <example-queries/>, "text/xml")
    let $existing := $root/query[description = $description][1]
    let $newEntry :=
            <query>
                <description>{$description}</description>
                {$query}
            </query>
    return (
        if ($existing) then
            update replace $existing with $newEntry
        else
            update insert $newEntry into $root,
        <ajax-response/>
    )
};

(:~ Check if the passed query string would correctly compile. :)
declare function sandbox:check-query($query as xs:string) as element() {
    util:declare-option("exist:serialize", "media-type=text/xml omit-xml-declaration=no"),
    <ajax-response>
        { util:compile($query) }
    </ajax-response>
};

(:~ Retrieve a single query result. :)
declare function sandbox:retrieve($num as xs:integer) as element() {
    util:declare-option("exist:serialize", "media-type=text/xml omit-xml-declaration=no indent=no"),
    let $cached := session:get-attribute("cached")
    let $item :=
        <item num="{$num}">
            {$cached[$num]}
        </item>
    return
        transform:transform($item, doc($sandbox:XML_HIGHLIGHT_STYLE), ())
};

(:~ Execute a query :)
declare function sandbox:exec-query($qu as xs:string) as element() {
    let $startTime := util:system-time()
    let $results := util:eval($qu)
    let $elapsed :=
		string(seconds-from-duration(util:system-time() - $startTime))
	let $elapsedStr := concat(substring-before($elapsed, '.'), '.',
			substring(substring-after($elapsed, '.'), 1, 3))
    return (
        session:set-attribute("cached", $results),
        <result hits="{count($results)}" elapsed="{$elapsedStr}"/>
    )
};

declare function sandbox:query($qu as xs:string) as element() {
    util:declare-option("exist:serialize", "media-type=text/xml omit-xml-declaration=no"),
    util:catch("org.exist.xquery.XPathException",
         sandbox:exec-query($qu),
         <error>{$util:exception-message}</error>
    )
 };

declare function sandbox:display-page() as element() {
    util:declare-option("exist:serialize", "media-type=text/html method=xhtml"),

            <title>XQuery Sandbox</title>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
            <link type="text/css" href="styles/sandbox.css" rel="stylesheet"/>

xquery version "1.0";
(: $Id$ :)

declare namespace sandbox="http://exist-db.org/xquery/sandbox";
declare namespace system="http://exist-db.org/xquery/system";

import module namespace util="http://exist-db.org/xquery/util";
import module namespace request="http://exist-db.org/xquery/request";
import module namespace session="http://exist-db.org/xquery/session";
import module namespace xdb="http://exist-db.org/xquery/xmldb";

declare option exist:serialize "method=xhtml indent=no";

(:~ Points to the location of the xml-highlight.xsl stylesheet stored in the database :)
declare variable $sandbox:XML_HIGHLIGHT_STYLE { "/db/sandbox/xml-highlight.xsl" };

(:~ The required stylesheets were not found in the db. Try to import them. :)
declare function sandbox:import-stylesheets() as xs:string* {
    let $home := system:get-exist-home()
    let $pathSep := util:system-property("file.separator")
    let $dir :=
			if (doc-available(concat("file:///", system:get-module-load-path(), "/stylesheets/xml-highlight.xsl")))
			then
				concat(system:get-module-load-path(), $pathSep, "stylesheets")
        	else if(ends-with($home, "WEB-INF")) then
        	    concat(substring-before($home, "WEB-INF"), "sandbox", $pathSep, "stylesheets")
        	else
               concat($home, $pathSep, "webapp", $pathSep, "sandbox", $pathSep, "stylesheets")
    let $col := xdb:create-collection("/db", "sandbox")
    return
        concat("Imported: ", xdb:store-files-from-pattern($col, $dir, "*.xsl", "text/xml"))
};

(:~ Check for stylesheets required for the application. Try to import them if they could not be found. :)
declare function sandbox:check-paths() as item()* {
    if (not(doc-available($sandbox:XML_HIGHLIGHT_STYLE))) then
        let $dummy := sandbox:import-stylesheets()
        return
            if (not(doc-available($sandbox:XML_HIGHLIGHT_STYLE))) then
                concat($sandbox:XML_HIGHLIGHT_STYLE, " not found! Please store this file into ",
                    "the database collection or the application will not work properly.")
            else ()
    else
        You can also try out an updated XQuery sandbox.
        It does not work with all browsers yet though.
};

declare function sandbox:init-slots() as element()+ {
    for $i in 1 to 10 return

[{$i}] --- empty ---

};

(:~ Export the current query results into a new document in the database. :)
declare function sandbox:export($docName as xs:string) as element() {
    let $collection := request:get-parameter("collection", ())
    let $wrapper0 := request:get-parameter("wrapper", ())
    let $wrapper := if ($wrapper0) then $wrapper0 else "exist:result"
    let $cached := session:get-attribute("cached")
    return
        if (empty($cached)) then
            <error>No query results to export!</error>
        else
            let $newDoc :=
                element { $wrapper } { $cached }
            return
                util:catch("java.lang.Exception",
                    (let $dummy := xdb:store($collection, $docName, $newDoc, "text/xml") return <ajax-response/>),
                    <error>{$util:exception-message}</error>
                )
};

(:~ Append the given query to the query examples file or update an existing old query. :)
declare function sandbox:save-query($query as xs:string, $description as xs:string) as element() {
    let $root0 := /example-queries
    let $root :=
        if ($root0) then
            $root0
        else
            xdb:store("/db", "examples.xml", <example-queries/>, "text/xml")
    let $existing := $root/query[description = $description][1]
    let $newEntry :=
            <query>
                <description>{$description}</description>
                {$query}
            </query>
    return (
        if ($existing) then
            update replace $existing with $newEntry
        else
            update insert $newEntry into $root,
        <ajax-response/>
    )
};

(:~ Check if the passed query string would correctly compile. :)
declare function sandbox:check-query($query as xs:string) as element() {
    util:declare-option("exist:serialize", "media-type=text/xml omit-xml-declaration=no"),
    <ajax-response>
        { util:compile($query) }
    </ajax-response>
};

(:~ Retrieve a single query result. :)
declare function sandbox:retrieve($num as xs:integer) as element() {
    util:declare-option("exist:serialize", "media-type=text/xml omit-xml-declaration=no indent=no"),
    let $cached := session:get-attribute("cached")
    let $item :=
        <item num="{$num}">
            {$cached[$num]}
        </item>
    return
        transform:transform($item, doc($sandbox:XML_HIGHLIGHT_STYLE), ())
};

(:~ Execute a query :)
declare function sandbox:exec-query($qu as xs:string) as element() {
    let $startTime := util:system-time()
    let $results := util:eval($qu)
    let $elapsed :=
		string(seconds-from-duration(util:system-time() - $startTime))
	let $elapsedStr := concat(substring-before($elapsed, '.'), '.',
			substring(substring-after($elapsed, '.'), 1, 3))
    return (
        session:set-attribute("cached", $results),
        <result hits="{count($results)}" elapsed="{$elapsedStr}"/>
    )
};

declare function sandbox:query($qu as xs:string) as element() {
    util:declare-option("exist:serialize", "media-type=text/xml omit-xml-declaration=no"),
    util:catch("org.exist.xquery.XPathException",
         sandbox:exec-query($qu),
         <error>{$util:exception-message}</error>
    )
 };

declare function sandbox:display-page() as element() {
    util:declare-option("exist:serialize", "media-type=text/html method=xhtml"),

            <title>XQuery Sandbox</title>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
            <link type="text/css" href="styles/sandbox.css" rel="stylesheet"/>