Use the fn: namespace explicitely for calls to standard function, in order to work on MarkLogic.

(::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
(:  File:       generate-query-utils.xql                                    :)
(:  Author:     Jeni Tennsion                                               :)
(:  URI:        http://xspec.googlecode.com/                                :)
(:  Tags:                                                                   :)
(:    Copyright (c) 2008, 2010 Jeni Tennsion (see end of file.)             :)
(: ------------------------------------------------------------------------ :)

module namespace test = "http://www.jenitennison.com/xslt/unit-test";

declare namespace fn = "http://www.w3.org/2005/xpath-functions";

declare function test:deep-equal($seq1 as item()*, $seq2 as item()*) as xs:boolean
{
  test:deep-equal($seq1, $seq2, 2.0)
};

declare function test:deep-equal(
    $seq1 as item()*,
    $seq2 as item()*,
    $version as xs:double
  ) as xs:boolean
{
  if ( $version = 1.0 ) then
    if ( $seq1 instance of xs:string and $seq2 instance of text()+ ) then
      test:deep-equal($seq1, fn:string-join($seq2, ''))
    else if ( $seq1 instance of xs:double and $seq2 instance of text()+ ) then
      test:deep-equal($seq1, xs:double(fn:string-join($seq2, '')))
    else if ( $seq1 instance of xs:decimal and $seq2 instance of text()+ ) then
      test:deep-equal($seq1, xs:decimal(fn:string-join($seq2, '')))
    else if ( $seq1 instance of xs:integer and $seq2 instance of text()+ ) then
      test:deep-equal($seq1, xs:integer(fn:string-join($seq2, '')))
    else
      test:deep-equal($seq1, $seq2)
  else if ( fn:empty($seq1) or fn:empty($seq2) ) then
    fn:empty($seq1) and fn:empty($seq2)
  else if ( fn:count($seq1) = fn:count($seq2) ) then
    every $i in (1 to fn:count($seq1))
    satisfies test:item-deep-equal($seq1[$i], $seq2[$i])
  else if ( $seq1 instance of text() and $seq2 instance of text()+ ) then
    test:deep-equal($seq1, text { fn:string-join($seq2, '') })
  else
    fn:false()
};

declare function test:item-deep-equal($item1 as item(), $item2 as item()) as xs:boolean
{
  if ( $item1 instance of node() and $item2 instance of node() ) then
    test:node-deep-equal($item1, $item2)
  else if ( fn:not($item1 instance of node()) and fn:not($item2 instance of node()) ) then
    fn:deep-equal($item1, $item2)
  else
    fn:false()
};

declare function test:node-deep-equal($node1 as node(), $node2 as node()) as xs:boolean
{
  if ( $node1 instance of document-node() and $node2 instance of document-node() ) then
    test:deep-equal(test:sorted-children($node1), test:sorted-children($node2))
  else if ( $node1 instance of element() and $node2 instance of element() ) then
    if ( fn:node-name($node1) eq fn:node-name($node2) ) then
      let $atts1 as attribute()* := test:sort-named-nodes($node1/@*)
      let $atts2 as attribute()* := test:sort-named-nodes($node2/@*)
        return
          if ( test:deep-equal($atts1, $atts2) ) then
            if ( $node1/text() = '...' and fn:count($node1/node()) = 1 ) then
              fn:true()
            else
              test:deep-equal(test:sorted-children($node1), test:sorted-children($node2))
          else
            fn:false()
    else
      fn:false()
  else if ( $node1 instance of text() and $node1 = '...' ) then
    fn:true()
  else if ( $node1 instance of text() and $node2 instance of text() ) then
    fn:string($node1) eq fn:string($node2)
  else if ( ( $node1 instance of attribute() and $node2 instance of attribute() )
            or ( $node1 instance of processing-instruction()
                 and $node2 instance of processing-instruction()) ) then
    fn:node-name($node1) eq fn:node-name($node2)
      and ( $node1 = '...' or fn:string($node1) eq fn:string($node2) )
  else if ( $node1 instance of comment() and $node2 instance of comment() ) then
    $node1 = '...' or fn:string($node1) eq fn:string($node2)
  else
    fn:false()
};

declare function test:sorted-children($node as node()) as node()*
{
  $node/child::node()
  except ( $node/text()[fn:not(fn:normalize-space(.))], $node/test:message )
};

(: Aim to be identical to:
 :
 :     <xsl:perform-sort select="$nodes">
 :        <xsl:sort select="namespace-uri(.)" />
 :        <xsl:sort select="local-name(.)" />
 :     </xsl:perform-sort>
 :)
declare function test:sort-named-nodes($nodes as node()*) as node()*
{
  if ( fn:empty($nodes) ) then
    ()
  else
    let $idx := test:named-nodes-minimum($nodes)
      return (
        $nodes[$idx],
        test:sort-named-nodes(fn:remove($nodes, $idx))
      )
};

(: Return the "minimum" of $nodes, using the order defined by
 : test:sort-named-nodes().
 :)
declare function test:named-nodes-minimum($nodes as node()+) as xs:integer
{
  (: if there is only one node, this is the minimum :)
  if ( fn:empty($nodes[2]) ) then
    1
  (: if not, init the temp minimum on the first one, then walk through the sequence :)
  else
    test:named-nodes-minimum($nodes, fn:node-name($nodes[1]), 1, 2)
};

declare function test:named-nodes-minimum(
    $nodes as node()+,
    $min   as xs:QName,
    $idx   as xs:integer,
    $curr  as xs:integer
  ) as xs:integer
{
  if ( $curr gt fn:count($nodes) ) then
    $idx
  else if ( test:qname-lt(fn:node-name($nodes[$curr]), $min) ) then
    test:named-nodes-minimum($nodes, fn:node-name($nodes[$curr]), $curr, $curr + 1)
  else
    test:named-nodes-minimum($nodes, $min, $idx, $curr + 1)
};

declare function test:qname-lt($n1 as xs:QName, $n2 as xs:QName) as xs:boolean
{
  if ( fn:namespace-uri-from-QName($n1) eq fn:namespace-uri-from-QName($n2) ) then
    fn:local-name-from-QName($n1) lt fn:local-name-from-QName($n2)
  else
    fn:namespace-uri-from-QName($n1) lt fn:namespace-uri-from-QName($n2)
};

declare function test:report-value($value as item()*, $wrapper-name as xs:string) as element()
{
  test:report-value($value, $wrapper-name, 'http://www.jenitennison.com/xslt/xspec')
};

declare function test:report-value(
    $value as item()*,
    $wrapper-name as xs:string,
    $wrapper-ns as xs:string
  ) as element()
{
  element { fn:QName($wrapper-ns, $wrapper-name) } {
    if ( $value[1] instance of attribute() ) then (
        attribute { 'select' } { '/*/(@* | node())' },
        element { fn:QName($wrapper-ns, 'temp') } { $value }
      )
    else if ( $value instance of node()+ ) then (
        if ( $value instance of document-node() ) then
          attribute { 'select' } { '/' }
        else if ( fn:not($value instance of element()+) ) then
          attribute { 'select' } { '/node()' }
        else
          ()
        ,
        if ( fn:count($value//node()) > 1000 ) then
          fn:error((), 'TODO: Write the value within a file...')
        else
          (: TODO: The original stylesheet use a mode to do a bit
             different copy, to preserve withespaces... :)
          $value
      )
    else
      attribute { 'select' } {
        if ( fn:empty($value) ) then
          '()'
        else if ( $value instance of item() ) then
          test:report-atomic-value($value)
        else
          fn:concat('(', fn:string-join(for $v in $value return test:report-atomic-value($v), ', '), ')')
      }
  }
};

declare function test:report-atomic-value($value as item()) as xs:string
{
  if ( $value instance of xs:string ) then
    fn:concat("'", fn:replace($value, "'", "''"), "'")
  else if ( $value instance of xs:integer or
            $value instance of xs:decimal or
            $value instance of xs:double ) then
    fn:string($value)
  else if ( $value instance of xs:QName ) then
    fn:concat("QName('",
           fn:namespace-uri-from-QName($value),
           "', '",
           if ( fn:prefix-from-QName($value) ) then
             fn:concat(fn:prefix-from-QName($value), ':')
           else
             '',
           fn:local-name-from-QName($value),
           "')")
  else
    fn:concat(test:atom-type($value), '(', test:report-atomic-value(fn:string($value)), ')')
};

declare function test:atom-type($value as xs:anyAtomicType) as xs:string
{
  if ( $value instance of xs:string ) then
    'xs:string'
  else if ( $value instance of xs:boolean ) then
    'xs:boolean'
  else if ( $value instance of xs:double ) then
    'xs:double'
  else if ( $value instance of xs:anyURI ) then
    'xs:anyURI'
  else if ( $value instance of xs:dateTime ) then
    'xs:dateTime'
  else if ( $value instance of xs:date ) then
    'xs:date'
  else if ( $value instance of xs:time ) then
    'xs:time'
  else
    'xs:anyAtomicType'
};

(: ------------------------------------------------------------------------ :)
(:  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS COMMENT.               :)
(:                                                                          :)
(:  Copyright (c) 2008, 2010 Jeni Tennsion                                  :)
(:                                                                          :)
(:  The contents of this file are subject to the MIT License (see the URI   :)
(:  http://www.opensource.org/licenses/mit-license.php for details).        :)
(:                                                                          :)
(:  Permission is hereby granted, free of charge, to any person obtaining   :)
(:  a copy of this software and associated documentation files (the         :)
(:  "Software"), to deal in the Software without restriction, including     :)
(:  without limitation the rights to use, copy, modify, merge, publish,     :)
(:  distribute, sublicense, and/or sell copies of the Software, and to      :)
(:  permit persons to whom the Software is furnished to do so, subject to   :)
(:  the following conditions:                                               :)
(:                                                                          :)
(:  The above copyright notice and this permission notice shall be          :)
(:  included in all copies or substantial portions of the Software.         :)
(:                                                                          :)
(:  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,         :)
(:  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF      :)
(:  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  :)
(:  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY    :)
(:  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,    :)
(:  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE       :)
(:  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                  :)
(: ------------------------------------------------------------------------ :)

(::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
(:  File:       generate-query-utils.xql                                    :)
(:  Author:     Jeni Tennsion                                               :)
(:  URI:        http://xspec.googlecode.com/                                :)
(:  Tags:                                                                   :)
(:    Copyright (c) 2008, 2010 Jeni Tennsion (see end of file.)             :)
(: ------------------------------------------------------------------------ :)

module namespace test = "http://www.jenitennison.com/xslt/unit-test";

declare function test:deep-equal($seq1 as item()*, $seq2 as item()*) as xs:boolean
{
  test:deep-equal($seq1, $seq2, 2.0)
};

declare function test:deep-equal(
    $seq1 as item()*,
    $seq2 as item()*,
    $version as xs:double
  ) as xs:boolean
{
  if ( $version = 1.0 ) then
    if ( $seq1 instance of xs:string and $seq2 instance of text()+ ) then
      test:deep-equal($seq1, string-join($seq2, ''))
    else if ( $seq1 instance of xs:double and $seq2 instance of text()+ ) then
      test:deep-equal($seq1, xs:double(string-join($seq2, '')))
    else if ( $seq1 instance of xs:decimal and $seq2 instance of text()+ ) then
      test:deep-equal($seq1, xs:decimal(string-join($seq2, '')))
    else if ( $seq1 instance of xs:integer and $seq2 instance of text()+ ) then
      test:deep-equal($seq1, xs:integer(string-join($seq2, '')))
    else
      test:deep-equal($seq1, $seq2)
  else if ( empty($seq1) or empty($seq2) ) then
    empty($seq1) and empty($seq2)
  else if ( count($seq1) = count($seq2) ) then
    every $i in (1 to count($seq1))
    satisfies test:item-deep-equal($seq1[$i], $seq2[$i])
  else if ( $seq1 instance of text() and $seq2 instance of text()+ ) then
    test:deep-equal($seq1, text { string-join($seq2, '') })
  else
    false()
};

declare function test:item-deep-equal($item1 as item(), $item2 as item()) as xs:boolean
{
  if ( $item1 instance of node() and $item2 instance of node() ) then
    test:node-deep-equal($item1, $item2)
  else if ( not($item1 instance of node()) and not($item2 instance of node()) ) then
    deep-equal($item1, $item2)
  else
    false()
};

declare function test:node-deep-equal($node1 as node(), $node2 as node()) as xs:boolean
{
  if ( $node1 instance of document-node() and $node2 instance of document-node() ) then
    test:deep-equal(test:sorted-children($node1), test:sorted-children($node2))
  else if ( $node1 instance of element() and $node2 instance of element() ) then
    if ( node-name($node1) eq node-name($node2) ) then
      let $atts1 as attribute()* := test:sort-named-nodes($node1/@*)
      let $atts2 as attribute()* := test:sort-named-nodes($node2/@*)
        return
          if ( test:deep-equal($atts1, $atts2) ) then
            if ( $node1/text() = '...' and count($node1/node()) = 1 ) then
              true()
            else
              test:deep-equal(test:sorted-children($node1), test:sorted-children($node2))
          else
            false()
    else
      false()
  else if ( $node1 instance of text() and $node1 = '...' ) then
    true()
  else if ( $node1 instance of text() and $node2 instance of text() ) then
    string($node1) eq string($node2)
  else if ( ( $node1 instance of attribute() and $node2 instance of attribute() )
            or ( $node1 instance of processing-instruction()
                 and $node2 instance of processing-instruction()) ) then
    node-name($node1) eq node-name($node2)
      and ( $node1 = '...' or string($node1) eq string($node2) )
  else if ( $node1 instance of comment() and $node2 instance of comment() ) then
    $node1 = '...' or string($node1) eq string($node2)
  else
    false()
};

declare function test:sorted-children($node as node()) as node()*
{
  $node/child::node()
  except ( $node/text()[not(normalize-space(.))], $node/test:message )
};

(: Aim to be identical to:
 :
 :     <xsl:perform-sort select="$nodes">
 :        <xsl:sort select="namespace-uri(.)" />
 :        <xsl:sort select="local-name(.)" />
 :     </xsl:perform-sort>
 :)
declare function test:sort-named-nodes($nodes as node()*) as node()*
{
  if ( empty($nodes) ) then
    ()
  else
    let $idx := test:named-nodes-minimum($nodes)
      return (
        $nodes[$idx],
        test:sort-named-nodes(remove($nodes, $idx))
      )
};

(: Return the "minimum" of $nodes, using the order defined by
 : test:sort-named-nodes().
 :)
declare function test:named-nodes-minimum($nodes as node()+) as xs:integer
{
  (: if there is only one node, this is the minimum :)
  if ( empty($nodes[2]) ) then
    1
  (: if not, init the temp minimum on the first one, then walk through the sequence :)
  else
    test:named-nodes-minimum($nodes, node-name($nodes[1]), 1, 2)
};

declare function test:named-nodes-minimum(
    $nodes as node()+,
    $min   as xs:QName,
    $idx   as xs:integer,
    $curr  as xs:integer
  ) as xs:integer
{
  if ( $curr gt count($nodes) ) then
    $idx
  else if ( test:qname-lt(node-name($nodes[$curr]), $min) ) then
    test:named-nodes-minimum($nodes, node-name($nodes[$curr]), $curr, $curr + 1)
  else
    test:named-nodes-minimum($nodes, $min, $idx, $curr + 1)
};

declare function test:qname-lt($n1 as xs:QName, $n2 as xs:QName) as xs:boolean
{
  if ( namespace-uri-from-QName($n1) eq namespace-uri-from-QName($n2) ) then
    local-name-from-QName($n1) lt local-name-from-QName($n2)
  else
    namespace-uri-from-QName($n1) lt namespace-uri-from-QName($n2)
};

declare function test:report-value($value as item()*, $wrapper-name as xs:string) as element()
{
  test:report-value($value, $wrapper-name, 'http://www.jenitennison.com/xslt/xspec')
};

declare function test:report-value(
    $value as item()*,
    $wrapper-name as xs:string,
    $wrapper-ns as xs:string
  ) as element()
{
  element { QName($wrapper-ns, $wrapper-name) } {
    if ( $value[1] instance of attribute() ) then (
        attribute { 'select' } { '/*/(@* | node())' },
        element { QName($wrapper-ns, 'temp') } { $value }
      )
    else if ( $value instance of node()+ ) then (
        if ( $value instance of document-node() ) then
          attribute { 'select' } { '/' }
        else if ( not($value instance of element()+) ) then
          attribute { 'select' } { '/node()' }
        else
          ()
        ,
        if ( count($value//node()) > 1000 ) then
          error((), 'TODO: Write the value within a file...')
        else
          (: TODO: The original stylesheet use a mode to do a bit
             different copy, to preserve withespaces... :)
          $value
      )
    else
      attribute { 'select' } {
        if ( empty($value) ) then
          '()'
        else if ( $value instance of item() ) then
          test:report-atomic-value($value)
        else
          concat('(', string-join(for $v in $value return test:report-atomic-value($v), ', '), ')')
      }
  }
};

declare function test:report-atomic-value($value as item()) as xs:string
{
  if ( $value instance of xs:string ) then
    concat("'", replace($value, "'", "''"), "'")
  else if ( $value instance of xs:integer or
            $value instance of xs:decimal or
            $value instance of xs:double ) then
    string($value)
  else if ( $value instance of xs:QName ) then
    concat("QName('",
           namespace-uri-from-QName($value),
           "', '",
           if ( prefix-from-QName($value) ) then
             concat(prefix-from-QName($value), ':')
           else
             '',
           local-name-from-QName($value),
           "')")
  else
    concat(test:atom-type($value), '(', test:report-atomic-value(string($value)), ')')
};

declare function test:atom-type($value as xs:anyAtomicType) as xs:string
{
  if ( $value instance of xs:string ) then
    'xs:string'
  else if ( $value instance of xs:boolean ) then
    'xs:boolean'
  else if ( $value instance of xs:double ) then
    'xs:double'
  else if ( $value instance of xs:anyURI ) then
    'xs:anyURI'
  else if ( $value instance of xs:dateTime ) then
    'xs:dateTime'
  else if ( $value instance of xs:date ) then
    'xs:date'
  else if ( $value instance of xs:time ) then
    'xs:time'
  else
    'xs:anyAtomicType'
};

(: ------------------------------------------------------------------------ :)
(:  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS COMMENT.               :)
(:                                                                          :)
(:  Copyright (c) 2008, 2010 Jeni Tennsion                                  :)
(:                                                                          :)
(:  The contents of this file are subject to the MIT License (see the URI   :)
(:  http://www.opensource.org/licenses/mit-license.php for details).        :)
(:                                                                          :)
(:  Permission is hereby granted, free of charge, to any person obtaining   :)
(:  a copy of this software and associated documentation files (the         :)
(:  "Software"), to deal in the Software without restriction, including     :)
(:  without limitation the rights to use, copy, modify, merge, publish,     :)
(:  distribute, sublicense, and/or sell copies of the Software, and to      :)
(:  permit persons to whom the Software is furnished to do so, subject to   :)
(:  the following conditions:                                               :)
(:                                                                          :)
(:  The above copyright notice and this permission notice shall be          :)
(:  included in all copies or substantial portions of the Software.         :)
(:                                                                          :)
(:  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,         :)
(:  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF      :)
(:  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  :)
(:  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY    :)
(:  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,    :)
(:  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE       :)
(:  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                  :)
(: ------------------------------------------------------------------------ :)


Fixed Markos comments

Fixed Markos comments

xquery version "1.0";

(:
 : Copyright 2006-2009 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.
:)

(:~
 : The module provides functions to compute an immutable and opaque reference
 : for any node and for retrieving nodes given their identifier. The identifiers
 : are immutable, i.e. a node identifier does not change during the node lifetime,
 : and cannot be reused for another node after the original node gets deleted.
 : Identifiers are unique, in that, two different nodes will never have the same
 : identifier.  A node, at any time during its lifetime, can be retrieved by its
 : identifier.
 :
 :
Please see the data lifecycle
 : documentation about details on storing nodes in collections or as documents.

 :
 : @see Data Lifecycle
 :
 : @author Federico Cavalieri
 :
 : @project XDM/node
 :
 :)
module namespace ref = "http://www.zorba-xquery.com/modules/node-reference";

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

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

(:~
 : Returns an immutable and opaque node reference (with type xs:anyURI) for
 : a given node, either temporary or stored in a collection.
 :
 :
The generated identifier is immutable, i.e. a node
 : identifier does not change during the node lifetime.

 :
 :
Identifiers are also unique, in that, two nodes with different identities
 : will never have identical identifiers.

 :
 : A node, at any time during its lifetime, can be retrieved by its
 : identifier.
 :
 : @param $arg the node for which the URI should be computed
 :
 : @return the opaque URI of the node.
 :)
declare function ref:node-reference(
  $arg as node()
) as xs:anyURI external;

(:~
 : Returns the node identified by the given node reference.
 :
 :
The function returns the empty sequence if the node
 : that is referenced does not exist.

 :
 : @param $arg the URI of the node to retrieve.
 :
 : @return the node identified by the URI passed as parameter
 :         or the empty-sequence if no node with that URI is found.
 :
 : @error zerr:ZAPI0028 if the given URI is not a valid node reference
 :        computed by the <tt>ref:node-reference</tt> function.
 :)
declare function ref:node-by-reference(
  $arg as xs:anyURI
) as node()? external;

xquery version "1.0";

(:
 : Copyright 2006-2009 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.
:)

(:~
 : The module provides functions to compute an immutable and opaque reference
 : for any node, either temporary or stored in a collection and for retrieving
 : nodes given their identifier. The identifiers are immutable, i.e. a node
 : identifier does not change during the node lifetime. Identifiers are also
 : unique, in that, two nodes with different identities will never have identical
 : identifiers.
 : A node, at any time during its lifetime, can be retrieved by its identifier.
 :
 :
Please see the data lifecycle
 : documentation about details on storing nodes in collections or as documents.

 :
 : @see Data Lifecycle
 :
 : @author Federico Cavalieri
 :
 : @project XDM/node
 :
 :)
module namespace ref = "http://www.zorba-xquery.com/modules/node-reference";

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

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

(:~
 : Returns an immutable and opaque node reference (with type xs:anyURI) for
 : a given node, either temporary or stored in a collection.
 :
 :
The generated identifier is immutable, i.e. a node
 : identifier does not change during the node lifetime.

 :
 :
Identifiers are also unique, in that, two nodes with different identities
 : will never have identical identifiers.

 :
 : A node, at any time during its lifetime, can be retrieved by its
 : identifier.
 :
 : @param $arg the node for which the URI should be computed
 :
 : @return the opaque URI of the node.
 :)
declare function ref:node-reference(
  $arg as node()
) as xs:anyURI external;

(:~
 : Returns the node identified by the given node reference.
 :
 :
The function returns the empty sequence if the node
 : that is referenced does not exist (e.g. because it was
 : deleted or the temporary node is not available anymore).

 :
 : @param $arg the URI of the node to retrieve.
 :
 : @return the node identified by the URI passed as parameter
 :         or the empty-sequence if no node with that URI is found.
 :
 : @error zerr:ZAPI0028 if the given URI is not a valid node reference
 :        computed by the <tt>ref:node-reference</tt> function.
 :)
declare function ref:node-by-reference(
  $arg as xs:anyURI
) as node()? external;


Remove unnecessary import

Remove unnecessary import

xquery version "1.0-ml";

module namespace ext = "http://marklogic.com/rest-api/resource/data-meta-information";

import module namespace data = "http://marklogic.com/appservices/builder/data" at "/ext/content-metadata.xqy";
import module namespace amped-common = "http://marklogic.com/appservices/util-amped" at "/MarkLogic/appservices/utils/common-amped.xqy";
import module namespace utilities = "http://marklogic.com/utilities" at "/ext/utilities.xqy";

declare namespace roxy = "http://marklogic.com/roxy";

(:
 : To add parameters to the functions, specify them in the params annotations.
 : Example
 :   declare %roxy:params("uri=xs:string", "priority=xs:int") ext:get(...)
 : This means that the get function will take two parameters, a string and an int.
 :)

(:
 :)
declare
function ext:get(
  $context as map:map,
  $params  as map:map
) as document-node()*
{
  xdmp:set-response-code(200, "OK"),
  document {
   map:put($context, "output-types", "application/json"),
   ext:content-details()
 }
};

declare variable $sample-size as xs:integer := 5;
declare variable $sample-positions as xs:integer+ := (1 to $sample-size);

declare function ext:content-details()
{
  object-node {
    "json-data": array-node {
        for $node-name in ext:find-unique-root-qnames("json")
        return
          ext:doc-type-details(
            $node-name,
            "json"
          )
      },
    "xml-data": array-node {
        for $node-name in ext:find-unique-root-qnames("xml")
        return
          ext:doc-type-details(
            $node-name,
            "xml"
          )
      }
  }
};

declare function ext:doc-type-details($node-name as xs:QName, $format as xs:string)
{
  let $sample-set :=
    if ($format = "json") then
      cts:search(fn:collection(),
        cts:json-property-scope-query(fn:string($node-name), cts:and-query(())),
        "format-json"
      )[fn:position() = $sample-positions]/object-node()/node()[fn:node-name(.) eq $node-name]
    else
      cts:search(fn:collection()/element(),
        cts:element-query($node-name,cts:and-query(()),"self"),
        "format-xml"
      )[fn:position() = $sample-positions][fn:node-name(.) eq $node-name]
  return
    object-node {
      "format": $format,
      "name": fn:string($node-name),
      "properties": array-node {
        if ($format eq "json") then
          for $node-name in ext:find-unique-json-child-qnames($sample-set)
          return
            ext:determine-json-details($sample-set, $node-name)
        else
          for $node-name in ext:find-unique-xml-child-qnames($sample-set)
          return
            ext:determine-xml-details($sample-set, $node-name)
      }
    }
};

declare function ext:determine-json-details($sample-set as node()*, $property-name as xs:QName)
{
  let $properties := $sample-set//node()[fn:node-name(.) eq $property-name]
  let $all-have-children := every $prop in $properties satisfies $prop instance of array-node() or fn:exists($prop/object-node())
  let $some-have-children := fn:exists($properties[. instance of array-node() or object-node()])
  return
    object-node {
      "propertyName": fn:string($property-name),
      "types": array-node {
          fn:distinct-values(
            for $property in $properties
            return
              typeswitch($property)
              case object-node() return "[Object]"
              case array-node() return "[Array]"
              case number-node() return "number"
              case boolean-node() return "boolean"
              case text() return "string"
              default return "null"
          )
        },
      "allHaveChildren": $all-have-children,
      "someHaveChildren": $some-have-children
    }
};

declare function ext:determine-xml-details($sample-set as node()*, $property-name as xs:QName)
{
  let $properties := $sample-set//node()[fn:node-name(.) eq $property-name]
  let $all-have-children := every $prop in $properties satisfies fn:exists($prop/*)
  let $some-have-children := fn:exists($properties/*)
  return
    object-node {
      "propertyName": fn:string($property-name),
      "types": array-node {
          fn:distinct-values(
            for $property in $properties
            let $children := $property/*
            let $is-array-like := fn:count(fn:distinct-values($children/fn:node-name(.))) eq 1
            return
              if ($is-array-like) then
                "[Array]"
              else if (fn:exists($children)) then
                "[Object]"
              else
                ext:determine-xml-type($property)
          )
        },
      "allHaveChildren": $all-have-children,
      "someHaveChildren": $some-have-children
    }
};

declare function ext:determine-xml-type($property as node())
{
  if (xdmp:type($property) ne xs:QName("xs:untypedAtomic")) then
    fn:string(xdmp:type($property))
  else
    ext:determine-xml-type(
      $property,
      (: Types to check if castable as. string is last since that will match anything :)
      (
        "time",
        "date",
        "dateTime",
        "integer",
        "decimal",
        "double",
        "float",
        "dayTimeDuration",
        "yearMonthDuration",
        "string"
      )
    )
};

declare function ext:determine-xml-type($property as node(), $types as xs:string*)
{
  if (fn:empty($types)) then
    "untypedAtomic"
  else if (xdmp:castable-as("http://www.w3.org/2001/XMLSchema", fn:head($types), $property)) then
    fn:head($types)
  else
    ext:determine-xml-type($property, fn:tail($types))
};

declare function ext:find-unique-xml-child-qnames($node as node()*) {
  fn:distinct-values(
    $node//element()/fn:node-name(.)
  )
};

declare function ext:find-unique-json-child-qnames($node as node()*) {
  fn:distinct-values(
    $node//node()/fn:node-name(.)
  )
};

declare function ext:find-unique-root-qnames($format as xs:string?, $found-qnames as xs:QName*) {
  let $next-qname := fn:distinct-values(cts:search(fn:collection(),
      if (fn:exists($found-qnames))
      then
        if ($format = "json") then
          cts:not-query(cts:json-property-scope-query(($found-qnames ! fn:string(.)), cts:and-query(())))
        else
          cts:not-query(cts:element-query($found-qnames,cts:and-query(()),"self"))
      else cts:and-query(()),
      (
        if (fn:exists($format)) then
          "format-" || $format
        else (),
        "score-random",
        "unfaceted",
        "filtered"
      )
    )[fn:position() = $sample-positions]/(.|object-node())/node()/fn:node-name(.))
  return if (fn:exists($next-qname))
          then ext:find-unique-root-qnames($format, ($found-qnames,$next-qname))
          else $found-qnames
};

declare function ext:find-unique-root-qnames($format as xs:string?) {
  for $qn in ext:find-unique-root-qnames($format, ())
  order by string($qn)
  return $qn
};

xquery version "1.0-ml";

module namespace ext = "http://marklogic.com/rest-api/resource/data-meta-information";

import module namespace data = "http://marklogic.com/appservices/builder/data" at "/ext/content-metadata.xqy";
import module namespace database-model="http://marklogic.com/appservices/infostudio/models/database" at "/ext/database-model.xqy";
import module namespace amped-common = "http://marklogic.com/appservices/util-amped" at "/MarkLogic/appservices/utils/common-amped.xqy";
import module namespace utilities = "http://marklogic.com/utilities" at "/ext/utilities.xqy";

declare namespace roxy = "http://marklogic.com/roxy";

(:
 : To add parameters to the functions, specify them in the params annotations.
 : Example
 :   declare %roxy:params("uri=xs:string", "priority=xs:int") ext:get(...)
 : This means that the get function will take two parameters, a string and an int.
 :)

(:
 :)
declare
function ext:get(
  $context as map:map,
  $params  as map:map
) as document-node()*
{
  xdmp:set-response-code(200, "OK"),
  document {
   map:put($context, "output-types", "application/json"),
   ext:content-details()
 }
};

declare variable $sample-size as xs:integer := 5;
declare variable $sample-positions as xs:integer+ := (1 to $sample-size);

declare function ext:content-details()
{
  object-node {
    "json-data": array-node {
        for $node-name in ext:find-unique-root-qnames("json")
        return
          ext:doc-type-details(
            $node-name,
            "json"
          )
      },
    "xml-data": array-node {
        for $node-name in ext:find-unique-root-qnames("xml")
        return
          ext:doc-type-details(
            $node-name,
            "xml"
          )
      }
  }
};

declare function ext:doc-type-details($node-name as xs:QName, $format as xs:string)
{
  let $sample-set :=
    if ($format = "json") then
      cts:search(fn:collection(),
        cts:json-property-scope-query(fn:string($node-name), cts:and-query(())),
        "format-json"
      )[fn:position() = $sample-positions]/object-node()/node()[fn:node-name(.) eq $node-name]
    else
      cts:search(fn:collection()/element(),
        cts:element-query($node-name,cts:and-query(()),"self"),
        "format-xml"
      )[fn:position() = $sample-positions][fn:node-name(.) eq $node-name]
  return
    object-node {
      "format": $format,
      "name": fn:string($node-name),
      "properties": array-node {
        if ($format eq "json") then
          for $node-name in ext:find-unique-json-child-qnames($sample-set)
          return
            ext:determine-json-details($sample-set, $node-name)
        else
          for $node-name in ext:find-unique-xml-child-qnames($sample-set)
          return
            ext:determine-xml-details($sample-set, $node-name)
      }
    }
};

declare function ext:determine-json-details($sample-set as node()*, $property-name as xs:QName)
{
  let $properties := $sample-set//node()[fn:node-name(.) eq $property-name]
  let $all-have-children := every $prop in $properties satisfies $prop instance of array-node() or fn:exists($prop/object-node())
  let $some-have-children := fn:exists($properties[. instance of array-node() or object-node()])
  return
    object-node {
      "propertyName": fn:string($property-name),
      "types": array-node {
          fn:distinct-values(
            for $property in $properties
            return
              typeswitch($property)
              case object-node() return "[Object]"
              case array-node() return "[Array]"
              case number-node() return "number"
              case boolean-node() return "boolean"
              case text() return "string"
              default return "null"
          )
        },
      "allHaveChildren": $all-have-children,
      "someHaveChildren": $some-have-children
    }
};

declare function ext:determine-xml-details($sample-set as node()*, $property-name as xs:QName)
{
  let $properties := $sample-set//node()[fn:node-name(.) eq $property-name]
  let $all-have-children := every $prop in $properties satisfies fn:exists($prop/*)
  let $some-have-children := fn:exists($properties/*)
  return
    object-node {
      "propertyName": fn:string($property-name),
      "types": array-node {
          fn:distinct-values(
            for $property in $properties
            let $children := $property/*
            let $is-array-like := fn:count(fn:distinct-values($children/fn:node-name(.))) eq 1
            return
              if ($is-array-like) then
                "[Array]"
              else if (fn:exists($children)) then
                "[Object]"
              else
                ext:determine-xml-type($property)
          )
        },
      "allHaveChildren": $all-have-children,
      "someHaveChildren": $some-have-children
    }
};

declare function ext:determine-xml-type($property as node())
{
  if (xdmp:type($property) ne xs:QName("xs:untypedAtomic")) then
    fn:string(xdmp:type($property))
  else
    ext:determine-xml-type(
      $property,
      (: Types to check if castable as. string is last since that will match anything :)
      (
        "time",
        "date",
        "dateTime",
        "integer",
        "decimal",
        "double",
        "float",
        "dayTimeDuration",
        "yearMonthDuration",
        "string"
      )
    )
};

declare function ext:determine-xml-type($property as node(), $types as xs:string*)
{
  if (fn:empty($types)) then
    "untypedAtomic"
  else if (xdmp:castable-as("http://www.w3.org/2001/XMLSchema", fn:head($types), $property)) then
    fn:head($types)
  else
    ext:determine-xml-type($property, fn:tail($types))
};

declare function ext:find-unique-xml-child-qnames($node as node()*) {
  fn:distinct-values(
    $node//element()/fn:node-name(.)
  )
};

declare function ext:find-unique-json-child-qnames($node as node()*) {
  fn:distinct-values(
    $node//node()/fn:node-name(.)
  )
};

declare function ext:find-unique-root-qnames($format as xs:string?, $found-qnames as xs:QName*) {
  let $next-qname := fn:distinct-values(cts:search(fn:collection(),
      if (fn:exists($found-qnames))
      then
        if ($format = "json") then
          cts:not-query(cts:json-property-scope-query(($found-qnames ! fn:string(.)), cts:and-query(())))
        else
          cts:not-query(cts:element-query($found-qnames,cts:and-query(()),"self"))
      else cts:and-query(()),
      (
        if (fn:exists($format)) then
          "format-" || $format
        else (),
        "score-random",
        "unfaceted",
        "filtered"
      )
    )[fn:position() = $sample-positions]/(.|object-node())/node()/fn:node-name(.))
  return if (fn:exists($next-qname))
          then ext:find-unique-root-qnames($format, ($found-qnames,$next-qname))
          else $found-qnames
};

declare function ext:find-unique-root-qnames($format as xs:string?) {
  for $qn in ext:find-unique-root-qnames($format, ())
  order by string($qn)
  return $qn
};


Issue #335 remaining issue with JSON envelopes and attachments

(:
 Copyright 2002-2017 MarkLogic Corporation.  All Rights Reserved.

 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.
:)
xquery version "1.0-ml";

module namespace inst = "http://marklogic.com/entity-services-instance";
declare namespace es = "http://marklogic.com/entity-services";
declare namespace tde = "http://marklogic.com/xdmp/tde";
declare namespace xq = "http://www.w3.org/2012/xquery";

import module namespace sem = "http://marklogic.com/semantics" at "/MarkLogic/semantics.xqy";
import module namespace json = "http://marklogic.com/xdmp/json" at "/MarkLogic/json/json.xqy";

declare default function namespace "http://www.w3.org/2005/xpath-functions";

(: declare option xdmp:mapping "false"; :)
declare option xq:require-feature "xdmp:three-one";

declare function inst:instance-from-document(
    $document as document-node()
) as map:map*
{
    let $xml-from-document := inst:instance-xml-from-document($document)
    for $root-instance in $xml-from-document
        return inst:child-instance($root-instance)
};

declare function inst:child-instance(
    $element as element()
) as map:map*
{
    if (empty($element/*) and exists($element/text()))
    then json:object()
            =>map:with("$type", local-name($element))
            =>map:with("$ref", $element/data())
    else
        let $child := json:object()=>map:with("$type", local-name($element))
        let $_ :=
            for $property in $element/*
            return
                if (map:contains($child, local-name($property)))
                then
                    if (map:get($child, local-name($property)) instance of json:array)
                    then json:array-push(map:get($child, local-name($property)),
                            if ($property/element())
                            then inst:child-instance($property/*)
                            else data($property))
                    else
                        let $new-array := json:array()
                        return (
                            json:array-push($new-array, map:get($child, local-name($property))),
                            json:array-push($new-array, inst:child-instance($property/*)),
                            map:put($child, local-name($property), $new-array)
                        )
                else
                    if ($property[@datatype eq "array"])
                    then
                        map:put($child, local-name($property),
                            json:array()
                            =>json:array-with(
                                if ($property/element())
                                then inst:child-instance($property/element())
                                else data($property))
                            )
                    else
                        map:put($child, local-name($property),
                            if ($property/element())
                            then inst:child-instance($property/element())
                            else data($property))
        return $child
};

declare function inst:instance-xml-from-document(
    $document as document-node()
) as element()*
{
    if ($document/element())
    then $document//es:instance/(* except es:info)
    else
        let $json := inst:instance-json-from-document($document)
        return json:transform-from-json($json,
            json:config("custom")=>map:with("element-namespace",""))

};

declare private function inst:wrap-instance(
    $instance as json:object
) as json:object
{
    let $type := map:get($instance, "$type")
    let $remove-it := map:delete($instance, "$type")
    return json:object()
        =>map:with($type,
            if (map:contains($instance, "$ref"))
            then map:get($instance, "$ref")
            else
                let $value-map := json:object()
                let $_ :=
                    for $k in map:keys($instance)
                    let $v := map:get($instance, $k)
                    return
                    typeswitch ($v)
                    case json:array return

                        if (json:array-size($v) eq 0)
                        then json:object()=>map:with($k, $v)
                        else if ($v[1] instance of json:object)
                        then map:put($value-map, $k, (json:to-array(json:array-values($v) ! inst:wrap-instance(.))))
                        else map:put($value-map, $k, $v)
                    case json:object return
                        map:put($value-map, $k, inst:wrap-instance($v))
                    default return map:put($value-map, $k, $v)
                return $value-map)
};

declare function inst:instance-json-from-document(
    $document as document-node()
) as object-node()*
{
    if ($document/object-node())
    then
        for $n in $document//instance/*
        where fn:node-name($n) ne xs:QName("info")
        return
        object-node { fn:node-name($n) : $n }
    else
    (inst:instance-from-document($document) !
        (inst:wrap-instance(.)=>xdmp:to-json()))/node()
};

declare function inst:instance-get-attachments(
    $document as document-node()
) as item()*
{
    if (exists($document//es:attachments/node()))
    then $document//es:attachments/node()
    else if (exists($document//array-node("attachments")))
    then $document//attachments
    else ()
};

(:
 Copyright 2002-2017 MarkLogic Corporation.  All Rights Reserved.

 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.
:)
xquery version "1.0-ml";

module namespace inst = "http://marklogic.com/entity-services-instance";
declare namespace es = "http://marklogic.com/entity-services";
declare namespace tde = "http://marklogic.com/xdmp/tde";
declare namespace xq = "http://www.w3.org/2012/xquery";

import module namespace sem = "http://marklogic.com/semantics" at "/MarkLogic/semantics.xqy";
import module namespace json = "http://marklogic.com/xdmp/json" at "/MarkLogic/json/json.xqy";

declare default function namespace "http://www.w3.org/2005/xpath-functions";

(: declare option xdmp:mapping "false"; :)
declare option xq:require-feature "xdmp:three-one";

declare function inst:instance-from-document(
    $document as document-node()
) as map:map*
{
    let $xml-from-document := inst:instance-xml-from-document($document)
    for $root-instance in $xml-from-document
        return inst:child-instance($root-instance)
};

declare function inst:child-instance(
    $element as element()
) as map:map*
{
    if (empty($element/*) and exists($element/text()))
    then json:object()
            =>map:with("$type", local-name($element))
            =>map:with("$ref", $element/data())
    else
        let $child := json:object()=>map:with("$type", local-name($element))
        let $_ :=
            for $property in $element/*
            return
                if (map:contains($child, local-name($property)))
                then
                    if (map:get($child, local-name($property)) instance of json:array)
                    then json:array-push(map:get($child, local-name($property)),
                            if ($property/element())
                            then inst:child-instance($property/*)
                            else data($property))
                    else
                        let $new-array := json:array()
                        return (
                            json:array-push($new-array, map:get($child, local-name($property))),
                            json:array-push($new-array, inst:child-instance($property/*)),
                            map:put($child, local-name($property), $new-array)
                        )
                else
                    if ($property[@datatype eq "array"])
                    then
                        map:put($child, local-name($property),
                            json:array()
                            =>json:array-with(
                                if ($property/element())
                                then inst:child-instance($property/element())
                                else data($property))
                            )
                    else
                        map:put($child, local-name($property),
                            if ($property/element())
                            then inst:child-instance($property/element())
                            else data($property))
        return $child
};

declare function inst:instance-xml-from-document(
    $document as document-node()
) as element()*
{
    if ($document/element())
    then $document//es:instance/(* except es:info)
    else
        let $json := inst:instance-json-from-document($document)
        return json:transform-from-json($json,
            json:config("custom")=>map:with("element-namespace",""))

};

declare private function inst:wrap-instance(
    $instance as json:object
) as json:object
{
    let $type := map:get($instance, "$type")
    let $remove-it := map:delete($instance, "$type")
    return json:object()
        =>map:with($type,
            if (map:contains($instance, "$ref"))
            then map:get($instance, "$ref")
            else
                let $value-map := json:object()
                let $_ :=
                    for $k in map:keys($instance)
                    let $v := map:get($instance, $k)
                    return
                    typeswitch ($v)
                    case json:array return

                        if (json:array-size($v) eq 0)
                        then json:object()=>map:with($k, $v)
                        else if ($v[1] instance of json:object)
                        then map:put($value-map, $k, (json:to-array(json:array-values($v) ! inst:wrap-instance(.))))
                        else map:put($value-map, $k, $v)
                    case json:object return
                        map:put($value-map, $k, inst:wrap-instance($v))
                    default return map:put($value-map, $k, $v)
                return $value-map)
};

declare function inst:instance-json-from-document(
    $document as document-node()
) as object-node()*
{
    if ($document/object-node())
    then
        for $n in $document//instance/*
        where fn:node-name($n) ne xs:QName("info")
        return
        object-node { fn:node-name($n) : $n }
    else
    (inst:instance-from-document($document) !
        (inst:wrap-instance(.)=>xdmp:to-json()))/node()
};

declare function inst:instance-get-attachments(
    $document as document-node()
) as item()*
{
    if (exists($document//*:attachments/*))
    then $document//*:attachments/*
    else $document//*:attachments/text()
};


fixed typos

fixed typos

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

import module namespace http = "http://www.expath.org/mod/http-client" at "/db/scripts/http-client/http-client.xq";
declare namespace rb="http://kjc-fs1.kjc.uni-heidelberg.de/refbase";

(: credentials :)
declare variable $scope  := doc('/db/scripts/refbase/conf.xml');
declare variable $repository-name as xs:string := $scope/repository/name/string();
declare variable $database as xs:string := $scope/repository/driver/database/string();
declare variable $repository := concat($repository-name,"?repository=",$database,"&");
declare variable $username as xs:string := $scope/repository/driver/user/string();
declare variable $password as xs:string := $scope/repository/driver/password/string();
declare variable $collection := 'xmldb:exist:///db/mods/refbase/';
declare variable $file-name := 'refbase-metadata.xml';

(: the transform rule :)
declare function local:transform-serials($doc as document-node()) as document-node() {
 document {
   <modsCollection>
   {
     for $serial in $doc//rb:repository/sql:result/sql:row/sql:serial/string()
       return  local:transform-entries(local:get-in($serial))
   }
   </modsCollection>
 }
};

(:author (; nachnanem,vorname) title<titleInfo:title> year<originInfo:dateIssued> publisher<originInfo:c> place (;) <place:placeTerm>  isbn  <identifier type="isbn"> cluster_publication(note type="cp") :)
declare function local:transform-entries($doc as document-node()) as document-node() {
 document {

     for $serial in $doc//rb:repository/rb:id/sql:result/sql:row
      return
        <mods xmlns="http://www.loc.gov/mods/v3" version="3.4" ID="{$serial/sql:serial/string()}">
        <typeOfResource>text</typeOfResource>
        <titleInfo><title>{$serial/sql:title/string()}</title></titleInfo>

        {
        let $names := fn:tokenize($serial/sql:author/string(),';')
        for $name in $names
            return
             <name type="personal">
            <namePart type="given">{$name}</namePart>
        <role><roleTerm authority="marcrelator" type="text">author</roleTerm></role>
        </name>

        }
   (:use : retrieve mods functions , if avavailable:)
        <originInfo><dateIssued>{$serial/sql:year/string()}</dateIssued></originInfo>
        <originInfo><publisher>{$serial/sql:publisher/string()}</publisher></originInfo>
        <place><placeTerm>{$serial/sql:place/string()}</placeTerm></place>
        <identifier type="isbn">{$serial/sql:isbn/string()}</identifier>

   </mods>
   }

};

(: retrieve the input doc :)
declare function local:get-in($serial) as document-node() {
let $serial_id := concat('serial=',$serial)
 let $req := <http:request href="{$repository}{$serial_id}"
                           method="get"
                           username="{ $username }"
                           password="{ $password }"
                           auth-method="basic"
                           send-authorization="true"/>
   return
     (: error checking is left as an exercise :)

     http:send-request($req)[2]
};

(: save the document to database:)
declare function local:save-file($doc as document-node()) {
  let $login := xmldb:login($collection, $username, $password)
  let $store-return-status := xmldb:store($collection, $file-name, $doc)
  return 1
};

(: retrieve a doc, transform it and upload the result :)

let $serial  :=  xs:string(request:get-parameter('serial', ''))
return
<modsCollection>
{
if (not($serial))
 then (
  (:local:transform-serials(local:get-in($serial)) :)
  system:as-user($username,$password,local:save-file(local:transform-serials(local:get-in($serial))))
 )
 else (
  local:transform-entries(local:get-in($serial))
 )

}
</modsCollection>

import module namespace http = "http://www.expath.org/mod/http-client" at "/db/scripts/http-client/http-client.xq";
declare namespace rb="http://kjc-fs1.kjc.uni-heidelberg.de/refbase";

(: credentials :)
declare variable $scope  := doc('/db/scripts/refbase/conf.xml');
declare variable $repository-name as xs:string := $scope/repositroy/name/string();
declare variable $database as xs:string := $scope/repositroy/driver/database/string();
declare variable $repository := concat($repository-name,"?repository=",$database,"&");
declare variable $username as xs:string := $scope/repositroy/driver/user/string();
declare variable $password as xs:string := $scope/repositroy/driver/password/string();
declare variable $collection := 'xmldb:exist:///db/mods/refbase/';
declare variable $file-name := 'refbase-metadata.xml';

(: the transform rule :)
declare function local:transform-serials($doc as document-node()) as document-node() {
 document {
   <modsCollection>
   {
     for $serial in $doc//rb:repository/sql:result/sql:row/sql:serial/string()
       return  local:transform-entries(local:get-in($serial))
   }
   </modsCollection>
 }
};

(:author (; nachnanem,vorname) title<titleInfo:title> year<originInfo:dateIssued> publisher<originInfo:c> place (;) <place:placeTerm>  isbn  <identifier type="isbn"> cluster_publication(note type="cp") :)
declare function local:transform-entries($doc as document-node()) as document-node() {
 document {

     for $serial in $doc//rb:repository/rb:id/sql:result/sql:row
      return
        <mods xmlns="http://www.loc.gov/mods/v3" version="3.4" ID="{$serial/sql:serial/string()}">
        <typeOfResource>text</typeOfResource>
        <titleInfo><title>{$serial/sql:title/string()}</title></titleInfo>

        {
        let $names := fn:tokenize($serial/sql:author/string(),';')
        for $name in $names
            return
             <name type="personal">
            <namePart type="given">{$name}</namePart>
        <role><roleTerm authority="marcrelator" type="text">author</roleTerm></role>
        </name>

        }
   (:use : retrieve mods functions , if avavailable:)
        <originInfo><dateIssued>{$serial/sql:year/string()}</dateIssued></originInfo>
        <originInfo><publisher>{$serial/sql:publisher/string()}</publisher></originInfo>
        <place><placeTerm>{$serial/sql:place/string()}</placeTerm></place>
        <identifier type="isbn">{$serial/sql:isbn/string()}</identifier>

   </mods>
   }

};

(: retrieve the input doc :)
declare function local:get-in($serial) as document-node() {
let $serial_id := concat('serial=',$serial)
 let $req := <http:request href="{$repository}{$serial_id}"
                           method="get"
                           username="{ $username }"
                           password="{ $password }"
                           auth-method="basic"
                           send-authorization="true"/>
   return
     (: error checking is left as an exercise :)
     http:send-request($req)[2]
};

(: save the document to database:)
declare function local:save-file($doc as document-node()) {
  let $login := xmldb:login($collection, $username, $password)
  let $store-return-status := xmldb:store($collection, $file-name, $doc)
  return 1
};

(: retrieve a doc, transform it and upload the result :)

let $serial  :=  xs:string(request:get-parameter('serial', ''))
return
<modsCollection>
{
if (not($serial))
 then (
  (:local:transform-serials(local:get-in($serial)) :)
  system:as-user($username,$password,local:save-file(local:transform-serials(local:get-in($serial))))
 )
 else (
  local:transform-entries(local:get-in($serial))
 )

}
</modsCollection>


Fixed media type typo, added better support of non-basic auth endpoints

(:~
: This is the Care Services Discovery stored query registry
: @version 1.0
: @see https://github.com/his-interop/openinfoman
:
:)
module namespace csd_psd = "https://github.com/his-interop/openinfoman/csd_psd";
import module namespace csd_qus =  "https://github.com/his-interop/openinfoman/csd_qus" at "csd_query_updated_services.xqm";
import module namespace request = "http://exquery.org/ns/request";
declare namespace http = "http://expath.org/ns/http-client" ;
declare namespace soap = "http://www.w3.org/2003/05/soap-envelope";
declare namespace csd = "urn:ihe:iti:csd:2013";

declare variable $csd_psd:directory_manager := 'csd_directories.xml';

declare updating function csd_psd:init($db) {
  if ( not(csd_psd:dm_exists($db)))  then
    db:add($db, <serviceDirectoryLibrary/>,$csd_psd:directory_manager)
  else
      ()
};

declare function csd_psd:dm_exists($db) {
  db:is-xml($db,$csd_psd:directory_manager)
};

declare  function csd_psd:is_registered($db,$name) {
  if ( not(csd_psd:dm_exists($db)))  then
    false()
  else
    let $dm :=  db:open($db,$csd_psd:directory_manager)/serviceDirectoryLibrary
    return exists($dm/serviceDirectory[@name = $name])
};

declare updating function csd_psd:register_service($db,$name,$url,$credentials) {
  let $dm :=  db:open($db,$csd_psd:directory_manager)/serviceDirectoryLibrary
  (:bad bad plain text password:)
  let $reg_doc := <serviceDirectory name="{$name}" url="{$url}">{$credentials}</serviceDirectory>
  let $existing := $dm/serviceDirectory[@name = $name]
  return
    if (not(exists($existing)))  then
      insert node $reg_doc into $dm
    else
      replace  node $existing with $reg_doc

};

declare updating function csd_psd:deregister_service($db,$name) {
  if (csd_psd:dm_exists($db)) then
    let $dm :=  db:open($db,$csd_psd:directory_manager)/serviceDirectoryLibrary
    let $existing := $dm/serviceDirectory[@name = $name]
    return if (exists($existing))  then
      delete node $existing
    else
      ()
   else ()

};

declare function csd_psd:registered_directories($db) {
  if (csd_psd:dm_exists($db)) then
    db:open($db,$csd_psd:directory_manager)//serviceDirectory/text{@name}
  else
    ()
};

declare function csd_psd:get_service_directory_url($db,$name) {
  text{ db:open($db,$csd_psd:directory_manager)//serviceDirectory[@name=$name]/@url}
};

declare function csd_psd:get_service_directory_credentials($db,$name) {
  db:open($db,$csd_psd:directory_manager)//serviceDirectory[@name=$name]/credentials
};

declare function csd_psd:poll_service_directory($db,$name,$mtime)
{
  let $soap := csd_psd:poll_service_directory_soap_response($db,$name,$mtime)
  let $resp := $soap/soap:Envelope/soap:Body/csd:getModificationsResponse
  return  if (exists($resp)) then
     $resp
  else
    ()
};

declare function csd_psd:generate_soap_request ($db,$name,$mtime)  {
  let $url := csd_psd:get_service_directory_url($db,$name)
  let $message :=
    (<http:header name="Content-Type" value="application/soap+xml"/>
     , <http:body   media-type="application/soap+xml">
        {csd_qus:create_last_update_request($url,$mtime)}
      </http:body>
    )
  let $credentials := csd_psd:get_service_directory_credentials($db,$name)
  let $request :=
    if ($credentials/@type = 'basic_auth' and $credentials/@username != '')
      then
      <http:request
      href='{$url}'
      username='{$credentials/@username}'
      password='{$credentials/@password}'
      send-authorization='true'
      method='post' >
      {$message}
      </http:request>
    else
    <http:request
      href='{$url}'
      send-authorization='false'
      method='post' >
      {$message}
    </http:request>
  return $request
};

declare function csd_psd:poll_service_directory_soap_response($db,$name,$mtime)
{
  let $request := csd_psd:generate_soap_request($db,$name,$mtime)
  let $response := http:send-request($request)
  let $status := text{$response[1]/@status}
  return if ($status = "200")
  then
  (    $response[2]
)
  else
    ()
};

(:~
: This is the Care Services Discovery stored query registry
: @version 1.0
: @see https://github.com/his-interop/openinfoman
:
:)
module namespace csd_psd = "https://github.com/his-interop/openinfoman/csd_psd";
import module namespace csd_qus =  "https://github.com/his-interop/openinfoman/csd_qus" at "csd_query_updated_services.xqm";
import module namespace request = "http://exquery.org/ns/request";
declare namespace http = "http://expath.org/ns/http-client" ;
declare namespace soap = "http://www.w3.org/2003/05/soap-envelope";
declare namespace csd = "urn:ihe:iti:csd:2013";

declare variable $csd_psd:directory_manager := 'csd_directories.xml';

declare updating function csd_psd:init($db) {
  if ( not(csd_psd:dm_exists($db)))  then
    db:add($db, <serviceDirectoryLibrary/>,$csd_psd:directory_manager)
  else
      ()
};

declare function csd_psd:dm_exists($db) {
  db:is-xml($db,$csd_psd:directory_manager)
};

declare  function csd_psd:is_registered($db,$name) {
  if ( not(csd_psd:dm_exists($db)))  then
    false()
  else
    let $dm :=  db:open($db,$csd_psd:directory_manager)/serviceDirectoryLibrary
    return exists($dm/serviceDirectory[@name = $name])
};

declare updating function csd_psd:register_service($db,$name,$url,$credentials) {
  let $dm :=  db:open($db,$csd_psd:directory_manager)/serviceDirectoryLibrary
  (:bad bad plain text password:)
  let $reg_doc := <serviceDirectory name="{$name}" url="{$url}">{$credentials}</serviceDirectory>
  let $existing := $dm/serviceDirectory[@name = $name]
  return
    if (not(exists($existing)))  then
      insert node $reg_doc into $dm
    else
      replace  node $existing with $reg_doc

};

declare updating function csd_psd:deregister_service($db,$name) {
  if (csd_psd:dm_exists($db)) then
    let $dm :=  db:open($db,$csd_psd:directory_manager)/serviceDirectoryLibrary
    let $existing := $dm/serviceDirectory[@name = $name]
    return if (exists($existing))  then
      delete node $existing
    else
      ()
   else ()

};

declare function csd_psd:registered_directories($db) {
  if (csd_psd:dm_exists($db)) then
    db:open($db,$csd_psd:directory_manager)//serviceDirectory/text{@name}
  else
    ()
};

declare function csd_psd:get_service_directory_url($db,$name) {
  text{ db:open($db,$csd_psd:directory_manager)//serviceDirectory[@name=$name]/@url}
};

declare function csd_psd:get_service_directory_credentials($db,$name) {
  db:open($db,$csd_psd:directory_manager)//serviceDirectory[@name=$name]/credentials
};

declare function csd_psd:poll_service_directory($db,$name,$mtime)
{
  let $soap := csd_psd:poll_service_directory_soap_response($db,$name,$mtime)
  let $resp := $soap/soap:Envelope/soap:Body/csd:getModificationsResponse
  return  if (exists($resp)) then
     $resp
  else
    ()
};

declare function csd_psd:generate_soap_request ($db,$name,$mtime)  {
  let $url := csd_psd:get_service_directory_url($db,$name)
  let $message :=
    (<http:header name="Content-Type" value="application/soap+xml"/>
     , <http:body   media-type="application/soap+xm">
        {csd_qus:create_last_update_request($url,$mtime)}
      </http:body>
    )
  let $credentials := csd_psd:get_service_directory_credentials($db,$name)
  let $request :=
    if ($credentials/@type = 'basic_auth' and $credentials/@username )
      then
      <http:request
      href='{$url}'
      username='{$credentials/@username}'
      password='{$credentials/@password}'
      send-authorization='true'
      method='post' >
      {$message}
      </http:request>
    else
    <http:request
      href='{$url}'
      send-authorization='false'
      method='post' >
      {$message}
    </http:request>
  return $request
};

declare function csd_psd:poll_service_directory_soap_response($db,$name,$mtime)
{
  let $request := csd_psd:generate_soap_request($db,$name,$mtime)
  let $response := http:send-request($request)
  let $status := text{$response[1]/@status}
  return if ($status = "200")
  then
  (    $response[2]
)
  else
    ()
};


Fixed some comments in the XQDoc generator query.

import module namespace file = "http://www.zorba-xquery.com/modules/file";
import module namespace xqd = "http://www.zorba-xquery.com/modules/xqdoc";

import module namespace xqdg = "http://www.zorba-xquery.com/modules/internal/xqdoc-xhtml" at "xqdoc-xhtml.xq";

import schema namespace xqdoc = "http://www.xqdoc.org/1.0" at "xqdoc-1.0.xsd";

declare copy-namespaces preserve, inherit;

(:~
 : This variable contains the relative paths to directories that contain example code fragments that are included
 :)
declare variable $examplePath  as xs:string* := ('test/rbkt/Queries/zorba','test/update/Queries','test/rbkt/ExpQueryResults/zorba','test/update/ExpectedTestResults');

(:~
 : This variable contains the modules directory path in the source directory
 :)
declare variable $modulesPath as xs:string external;

(:~
 : This variable contains the path where to generate the XQDoc
 :)
declare variable $xqdocBuildPath as xs:string external;

(:~
 : This variable contains the to the index.html main page
 :)
declare variable $indexHtmlPath as xs:string external;

declare variable $indexCollector := <modules/>;

(:~
 : This function generates the XQDoc XML for all the modules found in $modulesPath
 : and write the resulting XML documents in $targetPath. The hierarchy is preserved.
 :
 : @param $modulePath where to search for modules recursively.
 : @param $targetPath where to generate the XQDoc XML documents.
 :)
declare sequential function local:generateXQDocXml($modulesPath as xs:string, $targetPath as xs:string) {
    for $file in file:files($modulesPath)
    let $filePath := concat($modulesPath, "/", $file)
    return
        if (file:is-directory($filePath))
        then
            let $newTargetPath := concat($targetPath, "/", $file)
            return local:generateXQDocXml($filePath, $newTargetPath)
        else if (matches($file, "\.xq$")) then (
            let $xqdoc := xqd:xqdoc(file:path-to-uri($filePath))
            let $moduleDoc := $xqdoc/xqdoc:xqdoc/xqdoc:module
            let $moduleName := $moduleDoc/xqdoc:name
            let $moduleUri := $moduleDoc/xqdoc:uri
            let $xqdocFileName := concat($targetPath, "/", $moduleName, ".xml")
            return
                try {
(: remove this block when bug 2896710 on SF is corrected :)
block {
(: ----------------------------------------------------- :)
                    file:mkdirs($targetPath, false());
                    file:write($xqdocFileName, $xqdoc, "xml");
                    concat("
SUCCESS: ", $moduleUri, " (", $xqdocFileName, ")");
(: remove this block when bug 2896710 on SF is corrected :)
}
(: ----------------------------------------------------- :)
                } catch * ($error_code) {
                    concat("
FAILED: ", $moduleUri, " (", $xqdocFileName, ")")
                }
        )
        else ()
};

(:~
 : This function generates the XQDoc XHTML pages for all the XQDoc XML
 : documents found in $xqdocPath and writes the resulting pages to in
 : $targetPath. The hierarchy is preserved.
 :
 : @param $xqdocPath where to search for XML XQDoc documents recursively.
 : @param $targetPath where to generate the XQDoc XHTML pages.
 :)
declare sequential function local:generateXQDocXhtml($xqdocPath as xs:string, $targetPath as xs:string, $pathToIndex as xs:string, $cssFileName as xs:string) {
    let $absoluteXqdocPath := concat($xqdocBuildPath, "/", $xqdocPath),
        $absoluteTargetPath := concat($xqdocBuildPath, "/", $targetPath)

    for $file in file:files($absoluteXqdocPath)
    let $filePath := concat($absoluteXqdocPath, "/", $file)
    return
        if (file:is-directory($filePath))
        then
            let $newXqdocPath := concat($xqdocPath, "/", $file),
                $newTargetPath := concat($targetPath, "/", $file),
                $newPathToIndex := concat("../", $pathToIndex)
            return local:generateXQDocXhtml($newXqdocPath, $newTargetPath, $newPathToIndex, $cssFileName)
        else if (matches($file, "\.xq\.xml$")) then (
            let $xqdoc := file:read-xml($filePath)/xqdoc:xqdoc
            let $moduleDoc := $xqdoc/xqdoc:module
            let $moduleName := $moduleDoc/xqdoc:name
            let $moduleUri := $moduleDoc/xqdoc:uri
            let $xhtmlFileName := replace($moduleName, "\.xq$", ".html"),
                $xhtmlFilePath := concat($absoluteTargetPath, "/", $xhtmlFileName)
            let $xhtml := xqdg:doc($xqdoc)
            return
                try {
(: remove this block when bug 2896710 on SF is corrected :)
block {
(: ----------------------------------------------------- :)
                    let $fileRelativeToBuild := concat($targetPath, "/", $xhtmlFileName),
                        $fileRelativeToIndex := replace($fileRelativeToBuild, "^xhtml/", "")
                    return
                        local:collectModule($moduleDoc, $fileRelativeToIndex);

                    file:mkdirs($absoluteTargetPath, false());

                    local:configure-xhtml($xhtml, $pathToIndex, $cssFileName);

                    file:write($xhtmlFilePath, $xhtml, "xhtml");
                    concat("
SUCCESS: ", $moduleUri, " (", $xhtmlFilePath, ")");
(: remove this block when bug 2896710 on SF is corrected :)
}
(: ----------------------------------------------------- :)
                } catch * ($error_code) {
                    concat("
FAILED: ", $moduleUri, " (", $xhtmlFilePath, ")")
                }
        )
        else ()
};

declare sequential function local:collectModule ($module, $relativeFileName as xs:string) {
    let $moduleName := $module/xqdoc:name,
        $moduleUri := $module/xqdoc:uri
    return
        insert node <module uri="{$moduleUri/text()}" file="{$relativeFileName}" /> as last into $indexCollector;
    ();
};

declare function local:getFilePath ($filename as xs:string) as xs:string*
{
  let $zorbaPath := replace($modulesPath,"/modules","")
  for $relPath in $examplePath
  let $path := concat($zorbaPath,'/',$relPath)
  let $test := file:files($path,concat("^",$filename,"$"),fn:true())[1]
  return
  if (fn:exists($test)) then
    $test
  else
    ()
};

declare sequential function local:configure-xhtml ($xhtml, $pathToIndex as xs:string, $cssFileName as xs:string) {
    (: add a stylesheet :)
    let $cssPath := concat($pathToIndex, $cssFileName)
    return
        replace value of node $xhtml/*:head/*:link/@href with $cssPath
    ;
    (: replace the <test> nodes with eiter links to the actual files or inline the actual files based on the 'type' attribute value :)
    for $file in $xhtml//*:include
    let $type := $file/@type
    let $path := local:getFilePath($file/text())
    return block {
    (: at the moment there is no way to ship the files defined as links with the packages/installers
      if (matches($type, "link")) then
        replace node $file with
          {$path}
      else :)if (matches($type, "inline")) then
        replace node $file with
          if (fn:exists($path)) then

 {$path}:

{file:read-text($path)}

          else

No example matching pattern '{$file/text()}' was found. Please update 'examplePath' variable.

      else ()
    };
    (: replace the function type description with images :)
    let $xquSpec := "http://www.w3.org/TR/xquery-update-10/",
        $xqsSpec := "http://www.w3.org/TR/xquery-sx-10/#dt-sequential-function"
    let $imagesPath := concat($pathToIndex, "images/")
    for $typeTd in $xhtml//*:td
    where $typeTd/@class eq "type"
    let $type := $typeTd/text()
    return block {
        if (matches($type, "updating")) then
            replace node $typeTd/text() with

        else if (matches($type, "sequential")) then
            replace node $typeTd/text() with

        else ();
    }
    ;
    $xhtml;
};

(:~
 : This function reads, updates and returns the new index.html.
 :
 : @param $xqdocPath where to search for XML XQDoc documents recursively.
 : @return the content of the new index.html
 :)
declare sequential function local:generateIndexHtml($indexPath as xs:string) as document-node() {
    let $indexHtmlDoc := file:read-xml($indexPath)
    return block {
        for $module in $indexCollector/module
        return
            insert nodes
                ({data($module/@uri)},
)
                 as last into $indexHtmlDoc/*:html/*:body;
        $indexHtmlDoc;
    }
};

(: generate the XQDoc XML for all the modules :)
let $xqdocXmlDir := concat($xqdocBuildPath, "/xml")
return
    if (file:mkdirs($xqdocXmlDir, false())) then
        local:generateXQDocXml($modulesPath, $xqdocXmlDir)
    else
        error()
;

(: generate the XQDoc XHTML for all the modules :)
let $absoluteXhtmlDir := concat($xqdocBuildPath, "/xhtml")
return
if (file:mkdirs($absoluteXhtmlDir, false())) then
    (: these paths are relative to the XQDoc build directory :)
    let $xqdocXmlDir := "xml",
        $xqdocXhtmlDir := "xhtml"
    (: this path is relative to $xqdocXhtmlDir :)
    let $cssFileName := "css/zorba.css"
    return
        local:generateXQDocXhtml($xqdocXmlDir, $xqdocXhtmlDir, "", $cssFileName)
else
    error()
;

let $doc := local:generateIndexHtml($indexHtmlPath)
return local:configure-xhtml($doc/*:html, "", "css/zorba.css")
;

import module namespace file = "http://www.zorba-xquery.com/modules/file";
import module namespace xqd = "http://www.zorba-xquery.com/modules/xqdoc";

import module namespace xqdg = "http://www.zorba-xquery.com/modules/internal/xqdoc-xhtml" at "xqdoc-xhtml.xq";

import schema namespace xqdoc = "http://www.xqdoc.org/1.0" at "xqdoc-1.0.xsd";

declare copy-namespaces preserve, inherit;

(:~
 : This variable contains the relative paths to directories that contain example code fragments that are included
 :)
declare variable $examplePath  as xs:string* := ('test/rbkt/Queries/zorba','test/update/Queries','test/rbkt/ExpQueryResults/zorba','test/update/ExpectedTestResults');

(:~
 : This variable contains the modules directory path in the source directory
 :)
declare variable $modulesPath as xs:string external;

(:~
 : This variable contains the path where to generate the XQDoc
 :)
declare variable $xqdocBuildPath as xs:string external;

(:~
 : This variable contains the to the index.html main page
 :)
declare variable $indexHtmlPath as xs:string external;

declare variable $indexCollector := <modules/>;

(:~
 : This function generates the XQDoc XML for all the modules found in $modulesPath
 : and write the resulting XML documents in $targetPath. The hierarchy is preserved.
 :
 : @param $modulePath where to search for modules recursively.
 : @param $targetPath where to generate the XQDoc XML documents.
:)
declare sequential function local:generateXQDocXml($modulesPath as xs:string, $targetPath as xs:string) {
    for $file in file:files($modulesPath)
    let $filePath := concat($modulesPath, "/", $file)
    return
        if (file:is-directory($filePath))
        then
            let $newTargetPath := concat($targetPath, "/", $file)
            return local:generateXQDocXml($filePath, $newTargetPath)
        else if (matches($file, "\.xq$")) then (
            let $xqdoc := xqd:xqdoc(file:path-to-uri($filePath))
            let $moduleDoc := $xqdoc/xqdoc:xqdoc/xqdoc:module
            let $moduleName := $moduleDoc/xqdoc:name
            let $moduleUri := $moduleDoc/xqdoc:uri
            let $xqdocFileName := concat($targetPath, "/", $moduleName, ".xml")
            return
                try {
(: remove this block when bug 2896710 on SF is corrected :)
block {
(: ----------------------------------------------------- :)
                    file:mkdirs($targetPath, false());
                    file:write($xqdocFileName, $xqdoc, "xml");
                    concat("
SUCCESS: ", $moduleUri, " (", $xqdocFileName, ")");
(: remove this block when bug 2896710 on SF is corrected :)
}
(: ----------------------------------------------------- :)
                } catch * ($error_code) {
                    concat("
FAILED: ", $moduleUri, " (", $xqdocFileName, ")")
                }
        )
        else ()
};

(:~
 : This function generates the XQDoc XHTML pages for all the XQDoc XML
 : documents found in $xqdocPath and writes the resulting pages to in
 : $targetPath. The hierarchy is preserved.
 :
 : @param $xqdocPath where to search for XML XQDoc documents recursively.
 : @param $targetPath where to generate the XQDoc XHTML pages.
:)
declare sequential function local:generateXQDocXhtml($xqdocPath as xs:string, $targetPath as xs:string, $pathToIndex as xs:string, $cssFileName as xs:string) {
    let $absoluteXqdocPath := concat($xqdocBuildPath, "/", $xqdocPath),
        $absoluteTargetPath := concat($xqdocBuildPath, "/", $targetPath)

    for $file in file:files($absoluteXqdocPath)
    let $filePath := concat($absoluteXqdocPath, "/", $file)
    return
        if (file:is-directory($filePath))
        then
            let $newXqdocPath := concat($xqdocPath, "/", $file),
                $newTargetPath := concat($targetPath, "/", $file),
                $newPathToIndex := concat("../", $pathToIndex)
            return local:generateXQDocXhtml($newXqdocPath, $newTargetPath, $newPathToIndex, $cssFileName)
        else if (matches($file, "\.xq\.xml$")) then (
            let $xqdoc := file:read-xml($filePath)/xqdoc:xqdoc
            let $moduleDoc := $xqdoc/xqdoc:module
            let $moduleName := $moduleDoc/xqdoc:name
            let $moduleUri := $moduleDoc/xqdoc:uri
            let $xhtmlFileName := replace($moduleName, "\.xq$", ".html"),
                $xhtmlFilePath := concat($absoluteTargetPath, "/", $xhtmlFileName)
            let $xhtml := xqdg:doc($xqdoc)
            return
                try {
(: remove this block when bug 2896710 on SF is corrected :)
block {
(: ----------------------------------------------------- :)
                    let $fileRelativeToBuild := concat($targetPath, "/", $xhtmlFileName),
                        $fileRelativeToIndex := replace($fileRelativeToBuild, "^xhtml/", "")
                    return
                        local:collectModule($moduleDoc, $fileRelativeToIndex);

                    file:mkdirs($absoluteTargetPath, false());

                    local:configure-xhtml($xhtml, $pathToIndex, $cssFileName);

                    file:write($xhtmlFilePath, $xhtml, "xhtml");
                    concat("
SUCCESS: ", $moduleUri, " (", $xhtmlFilePath, ")");
(: remove this block when bug 2896710 on SF is corrected :)
}
(: ----------------------------------------------------- :)
                } catch * ($error_code) {
                    concat("
FAILED: ", $moduleUri, " (", $xhtmlFilePath, ")")
                }
        )
        else ()
};

declare sequential function local:collectModule ($module, $relativeFileName as xs:string) {
    let $moduleName := $module/xqdoc:name,
        $moduleUri := $module/xqdoc:uri
    return
        insert node <module uri="{$moduleUri/text()}" file="{$relativeFileName}" /> as last into $indexCollector;
    ();
};

declare function local:getFilePath ($filename as xs:string) as xs:string*
{
  let $zorbaPath := replace($modulesPath,"/modules","")
  for $relPath in $examplePath
  let $path := concat($zorbaPath,'/',$relPath)
  let $test := file:files($path,concat("^",$filename,"$"),fn:true())[1]
  return
  if (fn:exists($test)) then
    $test
  else
    ()
};

declare sequential function local:configure-xhtml ($xhtml, $pathToIndex as xs:string, $cssFileName as xs:string) {
    (: add a stypesheet :)
    let $cssPath := concat($pathToIndex, $cssFileName)
    return
        replace value of node $xhtml/*:head/*:link/@href with $cssPath
    ;
    (: replace the <test> nodes with eiter links to the actual files or inline the actual files based on the 'type' attribute value :)
    for $file in $xhtml//*:include
    let $type := $file/@type
    let $path := local:getFilePath($file/text())
    return block {
    (: at the moment there is no way to ship the files defined as links with the packages/installers
      if (matches($type, "link")) then
        replace node $file with
          {$path}
      else :)if (matches($type, "inline")) then
        replace node $file with
          if (fn:exists($path)) then

 {$path}:

{file:read-text($path)}

          else

No example matching pattern '{$file/text()}' was found. Please update 'examplePath' variable.

      else ()
    };
    (: replace the function type description with images :)
    let $xquSpec := "http://www.w3.org/TR/xquery-update-10/",
        $xqsSpec := "http://www.w3.org/TR/xquery-sx-10/#dt-sequential-function"
    let $imagesPath := concat($pathToIndex, "images/")
    for $typeTd in $xhtml//*:td
    where $typeTd/@class eq "type"
    let $type := $typeTd/text()
    return block {
        if (matches($type, "updating")) then
            replace node $typeTd/text() with

        else if (matches($type, "sequential")) then
            replace node $typeTd/text() with

        else ();
    }
    ;
    $xhtml;
};

(:~
 : This function reads, updates and returns the new index.html.
 :
 : @param $xqdocPath where to search for XML XQDoc documents recursively.
 : @return the content of the new index.html
:)
declare sequential function local:generateIndexHtml($indexPath as xs:string) as document-node() {
    let $indexHtmlDoc := file:read-xml($indexPath)
    return block {
        for $module in $indexCollector/module
        return
            insert nodes
                ({data($module/@uri)},
)
                 as last into $indexHtmlDoc/*:html/*:body;
        $indexHtmlDoc;
    }
};

(: generate the XQDoc XML for all the modules :)
let $xqdocXmlDir := concat($xqdocBuildPath, "/xml")
return
    if (file:mkdirs($xqdocXmlDir, false())) then
        local:generateXQDocXml($modulesPath, $xqdocXmlDir)
    else
        error()
;

(: generate the XQDoc XHTML for all the modules :)
let $absoluteXhtmlDir := concat($xqdocBuildPath, "/xhtml")
return
if (file:mkdirs($absoluteXhtmlDir, false())) then
    (: these paths are relative to the XQDoc build directory :)
    let $xqdocXmlDir := "xml",
        $xqdocXhtmlDir := "xhtml"
    (: this path is relative to $xqdocXhtmlDir :)
    let $cssFileName := "css/zorba.css"
    return
        local:generateXQDocXhtml($xqdocXmlDir, $xqdocXhtmlDir, "", $cssFileName)
else
    error()
;

let $doc := local:generateIndexHtml($indexHtmlPath)
return local:configure-xhtml($doc/*:html, "", "css/zorba.css")
;