[test] add tests for fn:serialize with new option exist:insert-final-newline

(:
 : eXist-db Open Source Native XML Database
 : Copyright (C) 2001 The eXist-db Authors
 :
 : info@exist-db.org
 : http://www.exist-db.org
 :
 : This library is free software; you can redistribute it and/or
 : modify it under the terms of the GNU Lesser General Public
 : License as published by the Free Software Foundation; either
 : version 2.1 of the License, or (at your option) any later version.
 :
 : This library is distributed in the hope that it will be useful,
 : but WITHOUT ANY WARRANTY; without even the implied warranty of
 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 : Lesser General Public License for more details.
 :
 : You should have received a copy of the GNU Lesser General Public
 : License along with this library; if not, write to the Free Software
 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 :)
xquery version "3.1";

module namespace ser="http://exist-db.org/xquery/test/serialize";

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

declare %private function ser:adaptive($data, $itemSep as xs:string?) {
    let $options :=
        <output:serialization-parameters
            xmlns:output="http://www.w3.org/2010/xslt-xquery-serialization">
            <output:method value="adaptive"/>
            <output:indent>no</output:indent>
            {
                if ($itemSep) then
                    <output:item-separator>{$itemSep}</output:item-separator>
                else
                    ()
            }
        </output:serialization-parameters>
    return
        fn:serialize($data, $options)
};

declare %private function ser:adaptive-map-params($data, $itemSep as xs:string?) {
    let $options :=
        map {
            "method": "adaptive",
            "indent": false(),
            "item-separator": $itemSep
        }
    return
        fn:serialize($data, $options)
};

declare %private function ser:adaptive($data) {
    ser:adaptive($data, ())
};

declare %private function ser:adaptive-map-params($data) {
    ser:adaptive-map-params($data, ())
};

declare %private function ser:serialize-with-item-separator($data as item()*, $method as xs:string) {
    let $options :=
        <output:serialization-parameters
            xmlns:output="http://www.w3.org/2010/xslt-xquery-serialization">
            <output:method value="{$method}"/>
            <output:indent>no</output:indent>
            <output:item-separator>--</output:item-separator>
        </output:serialization-parameters>
    return
        fn:serialize($data, $options)
};

declare variable $ser:atomic :=
    <atomic:root xmlns:atomic="http://www.w3.org/XQueryTest" xmlns:foo="http://www.example.com/foo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <atomic:duration>P1Y2M3DT10H30M</atomic:duration>
      <atomic:dateTime>2002-04-02T12:00:00Z</atomic:dateTime>
      <atomic:time>13:20:10.5Z</atomic:time>
      <atomic:date>2000-01-01+05:00</atomic:date>
      <atomic:gYearMonth>2001-12</atomic:gYearMonth>
      <atomic:gYear>2001</atomic:gYear>
      <atomic:gMonthDay>--12-17</atomic:gMonthDay>
      <atomic:gDay>---17</atomic:gDay>
      <atomic:gMonth>--12</atomic:gMonth>
      <atomic:boolean>true</atomic:boolean>
      <atomic:base64Binary>R0lGODlhcgGSALMAAAQCAEMmCZtuMFQxDS8b</atomic:base64Binary>
      <atomic:hexBinary>A9FD64E12C</atomic:hexBinary>
      <atomic:float>1267.43233E12</atomic:float>
      <atomic:double>1267.43233E12</atomic:double>
      <atomic:anyURI>http://www.example.com</atomic:anyURI>
      <atomic:NCName atomic:attr="aNCname">aNCname</atomic:NCName>
      <atomic:QName atomic:attr="foo:aQname">foo:aQname</atomic:QName>
      <atomic:string>A String Function</atomic:string>
      <atomic:normalizedString>aNormalizedString</atomic:normalizedString>
      <atomic:language>EN</atomic:language>
      <atomic:decimal atomic:attr="12678967.543233">12678967.543233</atomic:decimal>
      <atomic:integer>12678967543233</atomic:integer>
      <atomic:nonPositiveInteger>-1</atomic:nonPositiveInteger>
      <atomic:long>12678967543233</atomic:long>
      <atomic:nonNegativeInteger>12678967543233</atomic:nonNegativeInteger>
      <atomic:negativeInteger>-12678967543233</atomic:negativeInteger>
      <atomic:int>126789675</atomic:int>
      <atomic:unsignedLong>12678967543233</atomic:unsignedLong>
      <atomic:positiveInteger>12678967543233</atomic:positiveInteger>
      <atomic:short>12678</atomic:short>
      <atomic:unsignedInt>1267896754</atomic:unsignedInt>
      <atomic:byte>126</atomic:byte>
      <atomic:unsignedShort>12678</atomic:unsignedShort>
      <atomic:unsignedByte>126</atomic:unsignedByte>
      <atomic:id1>id1</atomic:id1>
      <atomic:id2>id2</atomic:id2>
      <atomic:idrefs atomic:attr="id1 id2">id1 id2</atomic:idrefs>
    </atomic:root>;

declare variable $ser:test-xsl := document {
    <?xml-stylesheet href="xmldb:exist:///db/serialization-test/test.xsl" type="text/xsl"?>,
    <elem a="abc">123</elem>
};

declare variable $ser:xsl := document {
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
    <xsl:template match="b">processed</xsl:template>
    </xsl:stylesheet>
};

declare variable $ser:test-xml := document {
    <?pi?>,
    <elem a="abc">123</elem>
};

declare variable $ser:collection-name := "serialization-test";

declare variable $ser:collection := "/db/" || $ser:collection-name;

declare
    %test:setUp
function ser:setup() {
    xmldb:create-collection("/db", $ser:collection-name),
    xmldb:store($ser:collection, "test.xml", $ser:test-xml),
    xmldb:store($ser:collection, "test-xsl.xml", $ser:test-xsl),
    xmldb:store($ser:collection, "test.xsl", $ser:xsl)
};

declare
    %test:tearDown
function ser:teardown() {
    xmldb:remove($ser:collection)
};

declare
    %test:assertXPath("contains($result,'atomic')")
function ser:serialize-element() {
    fn:serialize($ser:atomic)
};

declare
    %test:assertError
function ser:serialize-attribute() {
    fn:serialize(($ser:atomic//@*)[1])
};

declare
    %test:assertXPath("contains($result,'atomic')")
function ser:serialize-with-params() {
    let $params :=
      <output:serialization-parameters
           xmlns:output="http://www.w3.org/2010/xslt-xquery-serialization">
        <output:method value="xml"/>
        <output:indent value="yes"/>
      </output:serialization-parameters>
    return fn:serialize($ser:atomic, $params)
};

declare
    %test:assertXPath("contains($result,'atomic')")
function ser:serialize-with-params-map-params() {
    let $params :=
      map {
        "method": "xml",
        "indent": true()
      }
    return fn:serialize($ser:atomic, $params)
};

declare
    %test:assertXPath("contains($result,'atomic')")
function ser:serialize-no-method() {
    let $params :=
        <output:serialization-parameters xmlns:output="http://www.w3.org/2010/xslt-xquery-serialization">
            <output:indent value="yes"/>
        </output:serialization-parameters>
    return fn:serialize($ser:atomic, $params)
};

declare
    %test:assertXPath("contains($result,'atomic')")
function ser:serialize-no-method-map-params() {
    let $params :=
        map {
            "indent": true()
        }
    return fn:serialize($ser:atomic, $params)
};

declare
    %test:assertXPath("contains($result,'atomic')")
function ser:serialize-empty-params() {
    let $params := ()
    return fn:serialize($ser:atomic, $params)
};

declare
    %test:assertEquals("aaa bbb")
function ser:serialize-atomic() {
    let $nodes := ("aaa", "bbb")
    return
        fn:serialize($nodes)
};

declare
    %test:assertEquals("")
function ser:serialize-empty-sequence() {
    let $nodes := ()
    return
        fn:serialize($nodes)
};

declare
    %test:args(1234)
    %test:assertEquals('"1234"')
    %test:args('Hello "world"!')
    %test:assertEquals('"Hello ""world""!"')
function ser:adaptive-simple-atomic($atomic as xs:anyAtomicType) {
    ser:adaptive($atomic)
};

declare
    %test:args(1234)
    %test:assertEquals('"1234"')
    %test:args('Hello "world"!')
    %test:assertEquals('"Hello ""world""!"')
function ser:adaptive-simple-atomic-map-params($atomic as xs:anyAtomicType) {
    ser:adaptive-map-params($atomic)
};

declare
    %test:assertEquals("fn:substring#3
math:pi#0
fn:exists#1
(anonymous-function)#1
Q{http://exist-db.org/xquery/test/serialize}adaptive-simple-atomic#1")
function ser:adaptive-function-item() {
    let $input := (
        substring#3,
        math:pi#0,
        Q{http://www.w3.org/2005/xpath-functions}exists#1,
        function ($a) { $a },
        ser:adaptive-simple-atomic#1
    )
    return
        ser:adaptive($input)
};

declare
    %test:assertEquals("fn:substring#3
math:pi#0
fn:exists#1
(anonymous-function)#1
Q{http://exist-db.org/xquery/test/serialize}adaptive-simple-atomic#1")
function ser:adaptive-function-item-map-params() {
    let $input := (
        substring#3,
        math:pi#0,
        Q{http://www.w3.org/2005/xpath-functions}exists#1,
        function ($a) { $a },
        ser:adaptive-simple-atomic#1
    )
    return
        ser:adaptive-map-params($input)
};

declare
    %test:assertEquals('<?pi?><elem a="abc">123</elem>
<elem a="abc">123</elem>
a="abc"
')
function ser:adaptive-xml() {
    let $input := ($ser:test-xml, $ser:test-xml/elem, $ser:test-xml/elem/@a, $ser:test-xml/elem/comment())
    return
        ser:adaptive($input)
};

declare
    %test:assertEquals('<?pi?><elem a="abc">123</elem>
<elem a="abc">123</elem>
a="abc"
')
function ser:adaptive-xml-map-params() {
    let $input := ($ser:test-xml, $ser:test-xml/elem, $ser:test-xml/elem/@a, $ser:test-xml/elem/comment())
    return
        ser:adaptive-map-params($input)
};

declare
    %test:assertEquals('<?pi?><elem a="abc">123</elem>
<elem a="abc">123</elem>
a="abc"
')
function ser:adaptive-xml-stored() {
    let $doc := doc($ser:collection || "/test.xml")
    let $input := ($doc, $doc/elem, $doc/elem/@a, $doc/elem/comment())
    return
        ser:adaptive($input)
};

declare
    %test:assertEquals('<?pi?><elem a="abc">123</elem>
<elem a="abc">123</elem>
a="abc"
')
function ser:adaptive-xml-stored-map-params() {
    let $doc := doc($ser:collection || "/test.xml")
    let $input := ($doc, $doc/elem, $doc/elem/@a, $doc/elem/comment())
    return
        ser:adaptive-map-params($input)
};

declare
    %test:assertEquals('xmlns:foo="http://exist-db.org/foo"')
function ser:adaptive-xml-namespace() {
    let $input := namespace foo { "http://exist-db.org/foo" }
    return
        ser:adaptive($input)
};

declare
    %test:assertEquals('xmlns:foo="http://exist-db.org/foo"')
function ser:adaptive-xml-namespace-map-params() {
    let $input := namespace foo { "http://exist-db.org/foo" }
    return
        ser:adaptive-map-params($input)
};

declare
    %test:assertEquals("Q{http://exist.sourceforge.net/NS/exist}test")
function ser:adaptive-qname() {
    ser:adaptive(xs:QName("exist:test"))
};

declare
    %test:assertEquals("Q{http://exist.sourceforge.net/NS/exist}test")
function ser:adaptive-qname-map-params() {
    ser:adaptive-map-params(xs:QName("exist:test"))
};

declare
    %test:assertEquals('[(1,2,3),"hello ""world""!",true(),false()]')
function ser:adaptive-array() {
    let $input := [(1 to 3), 'hello "world"!', true(), 1 = 0]
    return
        ser:adaptive($input)
};

declare
    %test:assertEquals('[(1,2,3),"hello ""world""!",true(),false()]')
function ser:adaptive-array-map-params() {
    let $input := [(1 to 3), 'hello "world"!', true(), 1 = 0]
    return
        ser:adaptive-map-params($input)
};

declare
    %test:assertEquals('map{"k1":(1,2,3),"k2":map{"k3":a="abc","k4":[1,2]}}')
function ser:adaptive-map() {
    let $input := map {
        "k1": 1 to 3,
        "k2": map { "k3": $ser:test-xml/elem/@a, "k4": array { 1 to 2 } }
    }
    return
        ser:adaptive($input)
};

declare
    %test:assertEquals('map{"k1":(1,2,3),"k2":map{"k3":a="abc","k4":[1,2]}}')
function ser:adaptive-map-map-params() {
    let $input := map {
        "k1": 1 to 3,
        "k2": map { "k3": $ser:test-xml/elem/@a, "k4": array { 1 to 2 } }
    }
    return
        ser:adaptive-map-params($input)
};

declare
    %test:assertEquals('1.0e0
3.141592653589793e0
2.543e1')
function ser:adaptive-double() {
    let $input := (xs:double(1), xs:double(math:pi()), xs:double(2.543e1))
    return
        ser:adaptive($input)
};

declare
    %test:assertEquals('1.0e0
3.141592653589793e0
2.543e1')
function ser:adaptive-double-map-params() {
    let $input := (xs:double(1), xs:double(math:pi()), xs:double(2.543e1))
    return
        ser:adaptive-map-params($input)
};

declare
    %test:assertEquals('a="abc"
["a",2,<b>123</b>,()]
3.141592653589793e0
math:pi#0
"hello"
"""quoted"""
true()
map{"k":()}')
function ser:adaptive-mixed() {
    let $input := (
        $ser:test-xml/elem/@a,
        ["a", 2, $ser:test-xml/elem/b, ()],
        xs:double(math:pi()),
        math:pi#0,
        "hello",
        '"quoted"',
        2 = 1+1,
        map:entry("k", ())
    )
    return
        ser:adaptive($input)
};

declare
    %test:assertEquals('a="abc"
["a",2,<b>123</b>,()]
3.141592653589793e0
math:pi#0
"hello"
"""quoted"""
true()
map{"k":()}')
function ser:adaptive-mixed-map-params() {
    let $input := (
        $ser:test-xml/elem/@a,
        ["a", 2, $ser:test-xml/elem/b, ()],
        xs:double(math:pi()),
        math:pi#0,
        "hello",
        '"quoted"',
        2 = 1+1,
        map:entry("k", ())
    )
    return
        ser:adaptive-map-params($input)
};

declare
    %test:assertEquals("[]")
function ser:adaptive-empty-array() {
    ser:adaptive([])
};

declare
    %test:assertEquals("[]")
function ser:adaptive-empty-array-map-params() {
    ser:adaptive-map-params([])
};

declare
    %test:assertEquals("map{}")
function ser:adaptive-empty-map() {
    ser:adaptive(map { })
};

declare
    %test:assertEquals("map{}")
function ser:adaptive-empty-map-map-params() {
    ser:adaptive-map-params(map { })
};

declare
    %test:assertEquals("")
function ser:adaptive-empty-seq() {
    ser:adaptive(())
};

declare
    %test:assertEquals("")
function ser:adaptive-empty-seq-map-params() {
    ser:adaptive-map-params(())
};

declare
    %test:assertEquals("content")
function ser:adaptive-text-node() {
    ser:adaptive(<test>content</test>/text())
};

declare
    %test:assertEquals("content")
function ser:adaptive-text-node-map-params() {
    ser:adaptive-map-params(<test>content</test>/text())
};

declare
    %test:assertEquals("")
function ser:adaptive-comment-node() {
    ser:adaptive()
};

declare
    %test:assertEquals("")
function ser:adaptive-comment-node-map-params() {
    ser:adaptive-map-params()
};

declare
    %test:assertEquals("<?target instruction ?>")
function ser:adaptive-processing-instr() {
    ser:adaptive(<?target instruction ?>)
};

declare
    %test:assertEquals("<?target instruction ?>")
function ser:adaptive-processing-instr-map-params() {
    ser:adaptive-map-params(<?target instruction ?>)
};

declare
    %test:assertEquals('att-name="att-value"')
function ser:adaptive-attribute-node() {
    ser:adaptive(attribute att-name { "att-value" })
};

declare
    %test:assertEquals('att-name="att-value"')
function ser:adaptive-attribute-node-map-params() {
    ser:adaptive-map-params(attribute att-name { "att-value" })
};

declare
    %test:assertEquals('[xs:float("NaN")]')
function ser:adaptive-array-with-NaN() {
    ser:adaptive([ xs:float("NaN") ])
};

declare
    %test:assertEquals('[xs:float("NaN")]')
function ser:adaptive-array-with-NaN-map-params() {
    ser:adaptive-map-params([ xs:float("NaN") ])
};

declare
    %test:assertEquals('1-2-3-4-5')
function ser:adaptive-seq-with-item-separator() {
    ser:adaptive(1 to 5, "-")
};

declare
    %test:assertEquals('1-2-3-4-5')
function ser:adaptive-seq-with-item-separator-map-params() {
    ser:adaptive-map-params(1 to 5, "-")
};

declare
    %test:assertEquals('"the quick", "brown fox"')
function ser:adaptive-seq-with-item-separator2() {
    ser:adaptive(("the quick", "brown fox"), ", ")
};

declare
    %test:assertEquals('"the quick", "brown fox"')
function ser:adaptive-seq-with-item-separator2-map-params() {
    ser:adaptive-map-params(("the quick", "brown fox"), ", ")
};

declare
    %test:assertEquals('map{"a":("quotes ("")","apos (')")}')
function ser:adaptive-map-with-itemsep-no-quotes() {
    let $input := map{ "a":("quotes ("")", "apos (')") }
    return
        ser:adaptive($input, ",")
};

declare
    %test:assertEquals('map{"a":("quotes ("")","apos (')")}')
function ser:adaptive-map-with-itemsep-no-quotes-map-params() {
    let $input := map{ "a":("quotes ("")", "apos (')") }
    return
        ser:adaptive-map-params($input, ",")
};

declare
    %test:assertEquals('xs:dateTime("1999-05-31T13:20:00-05:00")')
function ser:adaptive-xs-date-time() {
    ser:adaptive(xs:dateTime('1999-05-31T13:20:00-05:00'))
};

declare
    %test:assertEquals('xs:dateTime("1999-05-31T13:20:00-05:00")')
function ser:adaptive-xs-date-time-map-params() {
    ser:adaptive-map-params(xs:dateTime('1999-05-31T13:20:00-05:00'))
};

declare
    %test:assertEquals('xs:duration("P1Y2M3DT10H30M23S")')
function ser:adaptive-xs-duration() {
    ser:adaptive(xs:duration("P1Y2M3DT10H30M23S"))
};

declare
    %test:assertEquals('xs:duration("P1Y2M3DT10H30M23S")')
function ser:adaptive-xs-duration-map-params() {
    ser:adaptive-map-params(xs:duration("P1Y2M3DT10H30M23S"))
};

declare
    %test:assertEquals('xs:float("1")')
function ser:adaptive-xs-float() {
    ser:adaptive(xs:float("1e0"))
};

declare
    %test:assertEquals('xs:float("1")')
function ser:adaptive-xs-float-map-params() {
    ser:adaptive-map-params(xs:float("1e0"))
};

declare
    %test:assertEquals('1.0e0')
function ser:adaptive-xs-double() {
    let $input := xs:double(1e0)
    return
        ser:adaptive($input, ",")
};

declare
    %test:assertEquals('1.0e0')
function ser:adaptive-xs-double-map-params() {
    let $input := xs:double(1e0)
    return
        ser:adaptive-map-params($input, ",")
};

declare
    %test:assertEquals('1.2,1,0,-1,0,0')
function ser:adaptive-xs-integers() {
    let $input := (xs:decimal(1.2), xs:integer(1), xs:nonPositiveInteger("0"),
        xs:negativeInteger(-1), xs:long(0), xs:int(0))
    return
        ser:adaptive($input, ",")
};

declare
    %test:assertEquals('1.2,1,0,-1,0,0')
function ser:adaptive-xs-integers-map-params() {
    let $input := (xs:decimal(1.2), xs:integer(1), xs:nonPositiveInteger("0"),
        xs:negativeInteger(-1), xs:long(0), xs:int(0))
    return
        ser:adaptive-map-params($input, ",")
};

declare
    %test:assertEquals('"""","""",""""')
function ser:adaptive-string-escaping() {
    let $input := ('"', xs:untypedAtomic('"'), xs:anyURI('"'))
    return
        ser:adaptive($input, ",")
};

declare
    %test:assertEquals('"""","""",""""')
function ser:adaptive-string-escaping-map-params() {
    let $input := ('"', xs:untypedAtomic('"'), xs:anyURI('"'))
    return
        ser:adaptive-map-params($input, ",")
};

declare
    %test:assertEquals('"en","en","en","en","en"')
function ser:adaptive-xs-strings() {
    let $input := (xs:normalizedString("en"), xs:token("en"), xs:language("en"), xs:ID("en"), xs:NCName("en"))
    return
        ser:adaptive($input, ",")
};

declare
    %test:assertEquals('"en","en","en","en","en"')
function ser:adaptive-xs-strings-map-params() {
    let $input := (xs:normalizedString("en"), xs:token("en"), xs:language("en"), xs:ID("en"), xs:NCName("en"))
    return
        ser:adaptive-map-params($input, ",")
};

declare
    %test:assertXPath("contains($result, 'include')")
function ser:exist-expand-xinclude-false() {
    let $doc := document{

                            <title>My Title</title>
                            <xi:include href="{$ser:collection}/test.xml"/>

}
    return
        fn:serialize($doc, map { xs:QName("exist:expand-xincludes"): false() })
};

declare
    %test:assertXPath("contains($result, 'comment')")
function ser:exist-expand-xinclude-true() {
    let $doc := document{

                            <title>My Title</title>
                            <xi:include href="{$ser:collection}/test.xml"/>

}
    return
        fn:serialize($doc, map {  xs:QName("exist:expand-xincludes"): true() })
};

declare
    %test:assertXPath("contains($result, 'true')")
function ser:exist-add-exist-id-all() {
    let $doc := doc($ser:collection || "/test.xml")
    return fn:serialize($doc, map { xs:QName("exist:add-exist-id"): "all" }) eq '<?pi?><elem xmlns:exist="http://exist.sourceforge.net/NS/exist" exist:id="2" exist:source="test.xml" a="abc">123</elem>'
};

declare
    %test:assertXPath("contains($result, 'true')")
function ser:exist-add-exist-id-element() {
    let $doc := doc($ser:collection || "/test.xml")
    return fn:serialize($doc, map { xs:QName("exist:add-exist-id"): "element" })  eq '<?pi?><elem xmlns:exist="http://exist.sourceforge.net/NS/exist" exist:id="2" exist:source="test.xml" a="abc">123</elem>'
};

declare
     %test:assertXPath("not(contains($result, 'exist:id'))")
function ser:exist-add-exist-id-none() {
    let $doc := doc($ser:collection || "/test.xml")
    return fn:serialize($doc, map { xs:QName("exist:add-exist-id"): "none" })
};

declare
    %test:assertXPath("contains($result, 'true')")
function ser:exist-jsonp() {
      let $node := <book>
          <author>John Doe</author>
          <author>Robert Smith</author>
      </book>
    return fn:serialize($node, map {"method":"json", "media-type":"application/json", xs:QName("exist:jsonp"):"functionName"}) eq 'functionName({"author":["John Doe","Robert Smith"]})'
};

declare
    %test:assertEquals('processed')
function ser:exist-process-xsl-pi-true() {
    let $doc := doc($ser:collection || "/test-xsl.xml")
    return fn:serialize($doc, map {xs:QName("exist:process-xsl-pi"): true()})
};

declare
    %test:assertXPath("contains($result, 'stylesheet')")
function ser:exist-process-xsl-pi-false() {
    let $doc := doc($ser:collection || "/test-xsl.xml")
    return fn:serialize($doc, map {xs:QName("exist:process-xsl-pi"): false()})
};

declare
    %test:assertEquals("1--2")
function ser:item-separator-text-method() {
    let $data := (1, 2)
    return ser:serialize-with-item-separator($data, "text")
};

declare
    %test:assertEquals("1--2")
function ser:item-separator-html-method() {
    let $data := (1, 2)
    return ser:serialize-with-item-separator($data, "html")
};

declare
    %test:assertEquals("1--2")
function ser:item-separator-xhtml-method() {
    let $data := (1, 2)
    return ser:serialize-with-item-separator($data, "xhtml")
};

declare
    %test:assertEquals("1--2")
function ser:item-separator-xml-method() {
    let $data := (1, 2)
    return ser:serialize-with-item-separator($data, "xml")
};

declare
    %test:assertEquals("1--2")
function ser:item-separator-adaptive-method() {
    let $data := (1, 2)
    return ser:serialize-with-item-separator($data, "adaptive")
};

declare
    %test:assertEquals("1|2|3|4|5|6|7|8|9|10")
function ser:serialize-xml-033() {
    let $params :=
        <output:serialization-parameters xmlns:output="http://www.w3.org/2010/xslt-xquery-serialization">
            <output:method value="xml"/>
            <output:item-separator value="|"/>
        </output:serialization-parameters>
    return serialize(1 to 10, $params)
};

declare
    %test:assertEquals("1==2==3==4")
function ser:serialize-xml-034() {
    let $params :=
        <output:serialization-parameters xmlns:output="http://www.w3.org/2010/xslt-xquery-serialization">
            <output:method value="xml"/>
            <output:omit-xml-declaration value="yes"/>
            <output:item-separator value="=="/>
        </output:serialization-parameters>
    return serialize(1 to 4, $params)
};

declare
    %test:assertEquals("1|2|3|4|5|6|7|8|9|10")
function ser:serialize-xml-133() {
    let $params := map {
        "method" : "xml",
        "item-separator" : "|"
    }
    return serialize(1 to 10, $params)
};

declare
    %test:assertEquals("1==2==3==4")
function ser:serialize-xml-134() {
    let $params := map {
        "method" : "xml",
        "omit-xml-declaration" : true(),
        "item-separator" : "=="
    }
    return serialize((1 to 4)!text{.}, $params)
};

declare
    %test:assertTrue
function ser:exist-insert-final-newline-false() {
    let $doc := <root>
    <nested />
    </root>
    let $serialized := fn:serialize($doc,
        map {xs:QName("exist:insert-final-newline"): false()})
    return fn:ends-with($serialized, ">")
};

declare
    %test:assertTrue
function ser:exist-insert-final-newline-true() {
    let $doc := <root>
    <nested />
    </root>
    let $serialized := fn:serialize($doc,
        map {xs:QName("exist:insert-final-newline"): true()})
    return fn:ends-with($serialized, "
")
};


Attempt to get $section from subject attribute

declare default element namespace "http://www.w3.org/1999/xhtml";
declare namespace xfdf="http://ns.adobe.com/xfdf/";

<xhtml>

Issue #	Section	Page	Author	Observation

{
  for $h at $issue in //xfdf:highlight
  let $page := fn:string($h/@page + 1) (: XFDF page numbers are 0-based :)
  let $author := fn:string($h/@title)
  let $comment := $h/xfdf:contents/text()
  let $rich_comment := $h/xfdf:contents-richtext/body/p/span/text()
  let $comment := fn:concat($comment,$rich_comment)
  let $section := fn:string($h/@subject) (: if it exists, it might include context :)
  return
{fn:string($issue)}	{$section}	{$page}	{$author}	{$tokenized_comment}

}

</xhtml>

declare default element namespace "http://www.w3.org/1999/xhtml";
declare namespace xfdf="http://ns.adobe.com/xfdf/";

<xhtml>

Issue #	Section	Page	Author	Observation

{
  for $h at $issue in //xfdf:highlight
  let $page := fn:string($h/@page + 1) (: XFDF page numbers are 0-based :)
  let $author := fn:string($h/@title)
  let $comment := $h/xfdf:contents/text()
  let $rich_comment := $h/xfdf:contents-richtext/body/p/span/text()
  let $comment := fn:concat($comment,$rich_comment)
  return
{fn:string($issue)}	{$section}	{$page}	{$author}	{$tokenized_comment}

}

</xhtml>


Fixed documentation typos. Approved: Matthias Brantner, Paul J. Lucas

xquery version "3.0";

(:
 : Copyright 2006-2011 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 an XQuery API to full-text functions.
 : For general information about Zorba's implementation of the
 : XQuery and XPath Full Text 1.0 specification
 : as well as instructions for building an installing a thesaurus,
 : see the Full Text Thesaurus documentation.
 :
Notes on languages

 : To refer to paricular human languages,
 : Zorba uses both the
 : ISO 639-1
 : and
 : ISO 639-2
 : languages codes.
 : Note that Zorba supports only a subset of the
 : complete list of language codes
 : and not every function supports the same subset.
 :

 : Most functions in this module take a language as a parameter
 : using the
 : xs:language
 : XML schema data type.
 :
Notes on stemming

 : The stem() functions return the
 : stem
 : of a word.
 : In Zorba,
 : the stem of a word itself, however, is not guaranteed to be a word.
 : It is best to consider a stem as an opaque byte sequence.
 : All that is guaranteed about a stem is that,
 : for a given word,
 : the stem of that word will always be the same byte sequence.
 : Hence,
 : you should never compare the result of one of the stem()
 : functions against a non-stemmed string,
 : for example:
 :

 :  if ( ft:stem( "apples" ) eq "apple" )             ** WRONG **
 :

 : Instead do:
 :

 :  if ( ft:stem( "apples" ) eq ft:stem( "apple" ) )  ** CORRECT **
 :

 :
Notes on the thesaurus

 : The thesaurus-lookup() functions have "levels"
 : and "relationship" parameters.
 : The values for these are implementation-defined.
 : Zorba's default implementation uses the
 : WordNet lexical database,
 : version 3.0.
 :

 : In WordNet,
 : the number of "levels" that two phrases are apart
 : are how many hierarchical meanings apart they are.
 : For example,
 : "canary" is 5 levels away from "vertebrate"
 : (carary > finch > oscine > passerine > bird > vertebrate).
 :

 : When using the WordNet implementation,
 : Zorba supports all of the relationships (and their abbreviations)
 : specified by
 : ISO 2788
 : and
 : ANSI/NISO Z39.19-2005
 : with the exceptions of "HN" (history note)
 : and "X SN" (see scope note for).
 : These relationships are:
 :

 :

 :      Rel.
 :      Meaning
 :      WordNet Rel.
 :

 :

 :      BT
 :      broader term
 :      hypernym
 :

 :

 :      BTG
 :      broader term generic
 :      hypernym
 :

 :

 :      BTI
 :      broader term instance
 :      instance hypernym
 :

 :

 :      BTP
 :      broader term partitive
 :      part meronym
 :

 :

 :      NT
 :      narrower term
 :      hyponym
 :

 :

 :      NTG
 :      narrower term generic
 :      hyponym
 :

 :

 :      NTI
 :      narrower term instance
 :      instance hyponym
 :

 :

 :      NTP
 :      narrower term partitive
 :      part holonym
 :

 :

 :      RT
 :      related term
 :      also see
 :

 :

 :      SN
 :      scope note
 :      n/a
 :

 :

 :      TT
 :      top term
 :      hypernym
 :

 :

 :      UF
 :      non-preferred term
 :      n/a
 :

 :

 :      USE
 :      preferred term
 :      n/a
 :

 :

 : Note that you can specify relationships
 : either by their abbreviation
 : or their meaning.
 : Relationships are case-insensitive.
 :
 : In addition to the
 : ISO 2788
 : and
 : ANSI/NISO Z39.19-2005
 : relationships,
 : Zorba also supports all of the relationships offered by WordNet.
 : These relationships are:
 :

 :

 :      Relationship
 :      Meaning
 :

 :

 :      also see
 :
 :        A word that is related to another,
 :        e.g., for "varnished" (furniture)
 :        one should also see "finished."
 :
 :

 :

 :      antonym
 :
 :        A word opposite in meaning to another,
 :        e.g., "light" is an antonym for "heavy."
 :
 :

 :

 :      attribute
 :
 :        A noun for which adjectives express values,
 :        e.g., "weight" is an attribute
 :        for which the adjectives "light" and "heavy"
 :        express values.
 :
 :

 :

 :      cause
 :
 :        A verb that causes another,
 :        e.g., "show" is a cause of "see."
 :
 :

 :

 :      derivationally related form
 :
 :        A word that is derived from a root word,
 :        e.g., "metric" is a derivationally related form of "meter."
 :
 :

 :

 :      derived from adjective
 :
 :        An adverb that is derived from an adjective,
 :        e.g., "correctly" is derived from the adjective "correct."
 :
 :

 :

 :      entailment
 :
 :        A verb that presupposes another,
 :        e.g., "snoring" entails "sleeping."
 :
 :

 :

 :      hypernym
 :
 :        A word with a broad meaning that more specific words fall under,
 :        e.g., "meal" is a hypernym of "breakfast."
 :
 :

 :

 :      hyponym
 :
 :        A word of more specific meaning than a general term applicable to it,
 :        e.g., "breakfast" is a hyponym of "meal."
 :
 :

 :

 :      instance hypernym
 :
 :        A word that denotes a category of some specific instance,
 :        e.g., "author" is an instance hypernym of "Asimov."
 :
 :

 :

 :      instance hyponym
 :
 :        A term that donotes a specific instance of some general category,
 :        e.g., "Asimov" is an instance hyponym of "author."
 :
 :

 :

 :      member holonym
 :
 :        A word that denotes a collection of individuals,
 :        e.g., "faculty" is a member holonym of "professor."
 :
 :

 :

 :      member meronym
 :
 :        A word that denotes a member of a larger group,
 :        e.g., a "person" is a member meronym of a "crowd."
 :
 :

 :

 :      part holonym
 :
 :        A word that denotes a larger whole comprised of some part,
 :        e.g., "car" is a part holonym of "engine."
 :
 :

 :

 :      part meronym
 :
 :        A word that denotes a part of a larger whole,
 :        e.g., an "engine" is part meronym of a "car."
 :
 :

 :

 :      participle of verb
 :
 :        An adjective that is the participle of some verb,
 :        e.g., "breaking" is the participle of the verb "break."
 :
 :

 :

 :      pertainym
 :
 :        An adjective that classifies its noun,
 :        e.g., "musical" is a pertainym in "musical instrument."
 :
 :

 :

 :      similar to
 :
 :        Similar, though not necessarily interchangeable, adjectives.
 :        For example, "shiny" is similar to "bright",
 :        but they have subtle differences.
 :
 :

 :

 :      substance holonym
 :
 :        A word that denotes a larger whole containing some constituent
 :        substance, e.g., "bread" is a substance holonym of "flour."
 :
 :

 :

 :      substance meronym
 :
 :        A word that denotes a constituant substance of some larger whole,
 :        e.g., "flour" is a substance meronym of "bread."
 :
 :

 :

 :      verb group
 :
 :        A verb that is a member of a group of similar verbs,
 :        e.g., "live" is in the verb group
 :        of "dwell", "live", "inhabit", etc.
 :
 :

 :

 :
Notes on tokenization

 : For general information about Zorba's implementation of tokenization,
 : including what constitutes a token,
 : see the Full Text Tokenizer documentation.
 : @author Paul J. Lucas
 :)
module namespace ft = "http://www.zorba-xquery.com/modules/full-text";

import schema namespace ft-schema =
  "http://www.zorba-xquery.com/modules/full-text";

declare namespace err = "http://www.w3.org/2005/xqt-errors";
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";

(:===========================================================================:)

(:~
 : Predeclared constant for the Danish
 : xs:language.
 :)
declare variable $ft:lang-da as xs:language := xs:language("da");

(:~
 : Predeclared constant for the German
 : xs:language.
 :)
declare variable $ft:lang-de as xs:language := xs:language("de");

(:~
 : Predeclared constant for the English
 : xs:language.
 :)
declare variable $ft:lang-en as xs:language := xs:language("en");

(:~
 : Predeclared constant for the Spanish
 : xs:language.
 :)
declare variable $ft:lang-es as xs:language := xs:language("es");

(:~
 : Predeclared constant for the Finnish
 : xs:language.
 :)
declare variable $ft:lang-fi as xs:language := xs:language("fi");

(:~
 : Predeclared constant for the French
 : xs:language.
 :)
declare variable $ft:lang-fr as xs:language := xs:language("fr");

(:~
 : Predeclared constant for the Hungarian
 : xs:language.
 :)
declare variable $ft:lang-hu as xs:language := xs:language("hu");

(:~
 : Predeclared constant for the Italian
 : xs:language.
 :)
declare variable $ft:lang-it as xs:language := xs:language("it");

(:~
 : Predeclared constant for the Dutch
 : xs:language.
 :)
declare variable $ft:lang-nl as xs:language := xs:language("nl");

(:~
 : Predeclared constant for the Norwegian
 : xs:language.
 :)
declare variable $ft:lang-no as xs:language := xs:language("no");

(:~
 : Predeclared constant for the Portuguese
 : xs:language.
 :)
declare variable $ft:lang-pt as xs:language := xs:language("pt");

(:~
 : Predeclared constant for the Romanian
 : xs:language.
 :)
declare variable $ft:lang-ro as xs:language := xs:language("ro");

(:~
 : Predeclared constant for the Russian
 : xs:language.
 :)
declare variable $ft:lang-ru as xs:language := xs:language("ru");

(:~
 : Predeclared constant for the Swedish
 : xs:language.
 :)
declare variable $ft:lang-sv as xs:language := xs:language("sv");

(:~
 : Predeclared constant for the Turkish
 : xs:language.
 :)
declare variable $ft:lang-tr as xs:language := xs:language("tr");

(:===========================================================================:)

(:~
 : Gets the current compare options.
 :
 : @return said compare options.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-current-compare-options-1.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-current-compare-options-2.xq
 :)
declare function ft:current-compare-options()
  as element(ft-schema:compare-options) external;

(:~
 : Gets the current
 : language:
 : either the language specified by the
 : declare ft-option using
 : language
 : statement (if any)
 : or the one returned by ft:host-lang() (if none).
 :
 : @return said language.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-current-lang-true-1.xq
 :)
declare function ft:current-lang()
  as xs:language external;

(:~
 : Gets the host's current
 : language.
 : The "host" is the computer on which Zorba is running.
 : The host's current language is obtained as follows:
 :

 :

 :      For *nix systems:
 :

 :

 :          If setlocale(3) returns non-null,
 :          the language corresponding to that locale is used.
 :

 :

 :          Else, if the LANG environment variable is set,
 :          that language is ued.
 :

 :

 :          Otherwise, there is no default language.
 :

 :

 :

 :

 :      For Windows systems,
 :      the language corresponding to the locale returned by the
 :      GetLocaleInfo()
 :      function is used.
 :

 :

 :
 : @return said language.
 :)
declare function ft:host-lang()
  as xs:language external;

(:~
 : Checks whether the given
 : language
 : is supported for stemming.
 :
 : @param $lang The language to check.
 : @return true only if the language is supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stem-lang-es-supported-true.xq
 :)
declare function ft:is-stem-lang-supported( $lang as xs:language )
  as xs:boolean external;

(:~
 : Checks whether the given word is a stop-word.
 :
 : @param $word The word to check.
 : @param $lang The
 : language
 : of $word.
 : @return true only if $word is a stop-word.
 : @error err:FTST0009 if $lang is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-true-1.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-true-3.xq
 :)
declare function ft:is-stop-word( $word as xs:string, $lang as xs:language )
  as xs:boolean external;

(:~
 : Checks whether the given word is a stop-word.
 :
 : @param $word The word to check.
 : The word's language
 : is assumed to be the one returned by ft:current-lang().
 : @return true only if $word is a stop-word.
 : @error err:FTST0009 if ft:current-lang() is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-true-2.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-true-4.xq
 :)
declare function ft:is-stop-word( $word as xs:string )
  as xs:boolean external;

(:~
 : Checks whether the given
 : language
 : is supported for stop words.
 :
 : @param $lang The language to check.
 : @return true only if the language is supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-lang-en-supported-true.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-lang-supported-false-1.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-lang-supported-false-2.xq
 :)
declare function ft:is-stop-word-lang-supported( $lang as xs:language )
  as xs:boolean external;

(:~
 : Checks whether the given
 : language
 : is supported for look-up using the default thesaurus.
 :
 : @param $lang The language to check.
 : @return true only if the language is supported.
 :)
declare function ft:is-thesaurus-lang-supported( $lang as xs:language )
  as xs:boolean external;

(:~
 : Checks whether the given
 : language
 : is supported for look-up using the thesaurus specified by the given URI.
 :
 : @param $uri The URI specifying the thesaurus to use.
 : @param $lang The language to check.
 : @return true only if the language is supported.
 : @error err:FTST0018 if $uri refers to a thesaurus
 : that is not found in the statically known thesauri.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-thesaurus-lang-supported-true-1.xq
 :)
declare function ft:is-thesaurus-lang-supported( $uri as xs:string,
                                                 $lang as xs:language )
  as xs:boolean external;

(:~
 : Checks whether the given
 : language
 : is supported for tokenization.
 :
 : @param $lang The language to check.
 : @return true only if the language is supported.
 :)
declare function ft:is-tokenizer-lang-supported( $lang as xs:language )
  as xs:boolean external;

(:~
 : Stems the given word.
 :
 : @param $word The word to stem.
 : @param $lang The
 : language
 : of $word.
 : @return the stem of $word.
 : @error err:FTST0009 if $lang is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-stem-1.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-stem-2.xq
 :)
declare function ft:stem( $word as xs:string, $lang as xs:language )
  as xs:string external;

(:~
 : Stems the given word.
 :
 : @param $word The word to stem.
 : The word's language
 : is assumed to be the one returned by ft:current-lang().
 : @return the stem of $word.
 : @error err:FTST0009 if ft:current-lang() is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-stem-3.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-stem-4.xq
 :)
declare function ft:stem( $word as xs:string )
  as xs:string external;

(:~
 : Strips all diacritical marks from all characters.
 :
 : @param $string The string to strip diacritical marks from.
 : @return $string with diacritical marks stripped.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-strip-diacritics-1.xq
 :)
declare function ft:strip-diacritics( $string as xs:string )
  as xs:string external;

(:~
 : Looks-up the given phrase in the default thesaurus.
 :
 : @param $phrase The phrase to look up.
 : The phrase's
 : language
 : is assumed to be the one returned by ft:current-lang().
 : @return the related phrases if $phrase is found in the
 : thesaurus or the empty sequence if not.
 : @error err:FTST0009 if ft:current-lang() is not supported.
 : @error zerr:ZXQP8401 if the thesaurus data file's version is not supported
 : by the currently running version of Zorba.
 : @error zerr:ZXQP8402 if the thesaurus data file's endianness does not match
 : that of the CPU on which Zorba is currently running.
 : @error zerr:ZXQP8403 if there was an error reading the thesaurus data.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-thesaurus-lookup-1.xq
 :)
declare function ft:thesaurus-lookup( $phrase as xs:string )
  as xs:string* external;

(:~
 : Looks-up the given phrase in the thesaurus specified by the given URI.
 :
 : @param $uri The URI specifying the thesaurus to use.
 : @param $phrase The phrase to look up.
 : @param $lang The
 : language
 : of $phrase.
 : @return the related phrases if $phrase is found in the
 : thesaurus or the empty sequence if not.
 : @error err:FTST0009 if $lang is not supported.
 : @error err:FTST0018 if $uri refers to a thesaurus
 : that is not found in the statically known thesauri.
 : @error zerr:ZOSE0001 if the thesaurus data file could not be found.
 : @error zerr:ZOSE0002 if the thesaurus data file is not a plain file.
 : @error zerr:ZXQP8401 if the thesaurus data file's version is not supported
 : by the currently running version of Zorba.
 : @error zerr:ZXQP8402 if the thesaurus data file's endianness does not match
 : that of the CPU on which Zorba is currently running.
 : @error zerr:ZXQP8403 if there was an error reading the thesaurus data file.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-thesaurus-lookup-2.xq
 :)
declare function ft:thesaurus-lookup( $uri as xs:string, $phrase as xs:string,
                                      $lang as xs:language )
  as xs:string* external;

(:~
 : Looks-up the given phrase in a thesaurus.
 :
 : @param $uri The URI specifying the thesaurus to use.
 : @param $phrase The phrase to look up.
 : The phrase's
 : language
 : is assumed to be the one the one returned by ft:current-lang().
 : @return the related phrases if $phrase is found in the
 : thesaurus or the empty sequence if not.
 : @error err:FTST0009 if ft:current-lang() is unsupported.
 : @error err:FTST0018 if $uri refers to a thesaurus
 : that is not found in the statically known thesauri.
 : @error zerr:ZOSE0001 if the thesaurus data file could not be found.
 : @error zerr:ZOSE0002 if the thesaurus data file is not a plain file.
 : @error zerr:ZXQP8401 if the thesaurus data file's version is not supported
 : by the currently running version of Zorba.
 : @error zerr:ZXQP8402 if the thesaurus data file's endianness does not match
 : that of the CPU on which Zorba is currently running.
 : @error zerr:ZXQP8403 if there was an error reading the thesaurus data file.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-thesaurus-lookup-3.xq
 :)
declare function ft:thesaurus-lookup( $uri as xs:string, $phrase as xs:string )
  as xs:string* external;

(:~
 : Looks-up the given phrase in a thesaurus.
 :
 : @param $uri The URI specifying the thesaurus to use.
 : @param $phrase The phrase to look up.
 : @param $lang The
 : language
 : of $phrase.
 : @param $relationship The relationship the results are to have to
 : $phrase.
 : @return the related phrases if $phrase is found in the
 : thesaurus or the empty sequence if not.
 : @error err:FTST0018 if $uri refers to a thesaurus
 : that is not found in the statically known thesauri.
 : @error err:FTST0009 if $lang is not supported.
 : @error zerr:ZOSE0001 if the thesaurus data file could not be found.
 : @error zerr:ZOSE0002 if the thesaurus data file is not a plain file.
 : @error zerr:ZXQP8401 if the thesaurus data file's version is not supported
 : by the currently running version of Zorba.
 : @error zerr:ZXQP8402 if the thesaurus data file's endianness does not match
 : that of the CPU on which Zorba is currently running.
 : @error zerr:ZXQP8403 if there was an error reading the thesaurus data file.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-thesaurus-lookup-4.xq
 :)
declare function ft:thesaurus-lookup( $uri as xs:string, $phrase as xs:string,
                                      $lang as xs:language,
                                      $relationship as xs:string )
  as xs:string* external;

(:~
 : Looks-up the given phrase in a thesaurus.
 :
 : @param $uri The URI specifying the thesaurus to use.
 : @param $phrase The phrase to look up.
 : @param $lang The
 : language
 : of $phrase.
 : @param $relationship The relationship the results are to have to
 : $phrase.
 : @param $level-least The minimum number of levels within the thesaurus to be
 : traversed.
 : @param $level-most The maximum number of levels within the thesaurus to be
 : traversed.
 : @return the related phrases if $phrase is found in the
 : thesaurus or the empty sequence if not.
 : @error err:FOCA0003 if either $level-least or
 : $level-most is either negative or too large.
 : @error err:FTST0018 if $uri refers to a thesaurus
 : that is not found in the statically known thesauri.
 : @error err:FTST0009 if $lang is not supported.
 : @error zerr:ZOSE0001 if the thesaurus data file could not be found.
 : @error zerr:ZOSE0002 if the thesaurus data file is not a plain file.
 : @error zerr:ZXQP8401 if the thesaurus data file's version is not supported
 : by the currently running version of Zorba.
 : @error zerr:ZXQP8402 if the thesaurus data file's endianness does not match
 : that of the CPU on which Zorba is currently running.
 : @error zerr:ZXQP8403 if there was an error reading the thesaurus data file.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-thesaurus-lookup-5.xq
 :)
declare function ft:thesaurus-lookup( $uri as xs:string, $phrase as xs:string,
                                      $lang as xs:language,
                                      $relationship as xs:string,
                                      $level-least as xs:integer,
                                      $level-most as xs:integer )
  as xs:string* external;

(:~
 : Tokenizes the given node and all of its decendants.
 :
 : @param $node The node to tokenize.
 : @param $lang The default
 : language
 : of $node.
 : @return a (possibly empty) sequence of tokens.
 : @error err:FTST0009 if $lang is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-node-1.xq
 :)
declare function ft:tokenize-node( $node as node(), $lang as xs:language )
  as element(ft-schema:token)* external;

(:~
 : Tokenizes the given node and all of its descendants.
 :
 : @param $node The node to tokenize.
 : The node's default
 : language
 : is assumed to be the one returned by ft:current-lang().
 : @return a (possibly empty) sequence of tokens.
 : @error err:FTST0009 if ft:current-lang() is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-node-2.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-node-3.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-node-4.xq
 :)
declare function ft:tokenize-node( $node as node() )
  as element(ft-schema:token)* external;

(:~
 : Tokenizes the set of nodes comprising $includes (and all of its
 : descendants) but excluding $excludes (and all of its
 : descendants), if any.
 :
 : @param $includes The set of nodes (and its descendants) to include.
 : The default
 : language
 : is assumed to be the one returned by ft:current-lang().
 : @param $excludes The set of nodes (and its descendants) to exclude.
 : @return a (possibly empty) sequence of tokens.
 : @error err:FTST0009 if ft:current-lang() is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-nodes-1.xq
 :)
declare function ft:tokenize-nodes( $includes as node()+,
                                    $excludes as node()* )
  as element(ft-schema:token)* external;

(:~
 : Tokenizes the set of nodes comprising $includes (and all of its
 : descendants) but excluding $excludes (and all of its
 : descendants), if any.
 :
 : @param $includes The set of nodes (and its descendants) to include.
 : @param $excludes The set of nodes (and its descendants) to exclude.
 : @param $lang The default
 : language
 : for nodes.
 : @return a (possibly empty) sequence of tokens.
 : @error err:FTST0009 if $lang is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-nodes-1.xq
 :)
declare function ft:tokenize-nodes( $includes as node()+,
                                    $excludes as node()*,
                                    $lang as xs:language )
  as element(ft-schema:token)* external;

(:~
 : Tokenizes the given string.
 :
 : @param $string The string to tokenize.
 : @param $lang The
 : language
 : of $string.
 : @return a (possibly empty) sequence of tokens.
 : @error err:FTST0009 if $lang is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-string-1.xq
 :)
declare function ft:tokenize-string( $string as xs:string,
                                     $lang as xs:language )
  as xs:string* external;

(:~
 : Tokenizes the given string.
 :
 : @param $string The string to tokenize.
 : The string's
 : language
 : is assumed to be the one returned by ft:current-lang().
 : @return a (possibly empty) sequence of tokens.
 : @error err:FTST0009 if ft:current-lang() is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-string-2.xq
 :)
declare function ft:tokenize-string( $string as xs:string )
  as xs:string* external;

(:~
 : Gets properties of the tokenizer for the given
 : language.
 :
 : @param $lang The language of the tokenizer to get the properties of.
 : @return said properties.
 : @error err:FTST0009 if $lang is not supported.
 : tokenization specifically.
 :)
declare function ft:tokenizer-properties( $lang as xs:language )
  as element(ft-schema:tokenizer-properties) external;

(:~
 : Gets properties of the tokenizer for the
 : language
 : returned by ft:current-lang().
 :
 : @return said properties.
 : @error err:FTST0009 if ft:current-lang() is not supported.
 :)
declare function ft:tokenizer-properties()
  as element(ft-schema:tokenizer-properties) external;

(:===========================================================================:)

(: vim:set et sw=2 ts=2: :)

xquery version "3.0";

(:
 : Copyright 2006-2011 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 an XQuery API to full-text functions.
 : For general information about Zorba's implementation of the
 : XQuery and XPath Full Text 1.0 specification
 : as well as instructions for building an installing a thesaurus,
 : see the Full Text Thesaurus documentation.
 :
Notes on languages

 : To refer to paricular human languages,
 : Zorba uses both the
 : ISO 639-1
 : and
 : ISO 639-2
 : languages codes.
 : Note that Zorba supports only a subset of the
 : complete list of language codes
 : and not every function supports the same subset.
 :

 : Most functions in this module take a language as a parameter
 : using the
 : xs:language
 : XML schema data type.
 :
Notes on stemming

 : The stem() functions return the
 : stem
 : of a word.
 : In Zorba,
 : the stem of a word itself, however, is not guaranteed to be a word.
 : It is best to consider a stem as an opaque byte sequence.
 : All that is guaranteed about a stem is that,
 : for a given word,
 : the stem of that word will always be the same byte sequence.
 : Hence,
 : you sould never compare the result of one of the stem()
 : functions against a non-stemmed string,
 : for example:
 :

 :  if ( ft:stem( "apples" ) eq "apple" )             ** WRONG **
 :

 : Instead do:
 :

 :  if ( ft:stem( "apples" ) eq ft:stem( "apple" ) )  ** CORRECT **
 :

 :
Notes on the thesaurus

 : The thesaurus-lookup() functions have "levels"
 : and "relationship" parameters.
 : The values for these are implementation-defined.
 : Zorba's default implementation uses the
 : WordNet lexical database,
 : version 3.0.
 :

 : In WordNet,
 : the number of "levels" that two phrases are apart
 : are how many hierarchical meanings apart they are.
 : For example,
 : "canary" is 5 levels away from "vertebrate"
 : (carary > finch > oscine > passerine > bird > vertebrate).
 :

 : When using the WordNet implementation,
 : Zorba supports all of the relationships (and their abbreviations)
 : specified by
 : ISO 2788
 : and
 : ANSI/NISO Z39.19-2005
 : with the exceptions of "HN" (history note)
 : and "X SN" (see scope note for).
 : These relationships are:
 :

 :

 :      Rel.
 :      Meaning
 :      WordNet Rel.
 :

 :

 :      BT
 :      broader term
 :      hypernym
 :

 :

 :      BTG
 :      broader term generic
 :      hypernym
 :

 :

 :      BTI
 :      broader term instance
 :      instance hypernym
 :

 :

 :      BTP
 :      broader term partitive
 :      part meronym
 :

 :

 :      NT
 :      narrower term
 :      hyponym
 :

 :

 :      NTG
 :      narrower term generic
 :      hyponym
 :

 :

 :      NTI
 :      narrower term instance
 :      instance hyponym
 :

 :

 :      NTP
 :      narrower term partitive
 :      part holonym
 :

 :

 :      RT
 :      related term
 :      also see
 :

 :

 :      SN
 :      scope note
 :      n/a
 :

 :

 :      TT
 :      top term
 :      hypernym
 :

 :

 :      UF
 :      non-preferred term
 :      n/a
 :

 :

 :      USE
 :      preferred term
 :      n/a
 :

 :

 : Note that you can specify relationships
 : either by their abbreviation
 : or their meaning.
 : Relationships are case-insensitive.
 :
 : In addition to the
 : ISO 2788
 : and
 : ANSI/NISO Z39.19-2005
 : relationships,
 : Zorba also supports all of the relationships offered by WordNet.
 : These relationships are:
 :

 :

 :      Relationship
 :      Meaning
 :

 :

 :      also see
 :
 :        A word that is related to another,
 :        e.g., for "varnished" (furniture)
 :        one should also see "finished."
 :
 :

 :

 :      antonym
 :
 :        A word opposite in meaning to another,
 :        e.g., "light" is an antonym for "heavy."
 :
 :

 :

 :      attribute
 :
 :        A noun for which adjectives express values,
 :        e.g., "weight" is an attribute
 :        for which the adjectives "light" and "heavy"
 :        express values.
 :
 :

 :

 :      cause
 :
 :        A verb that causes another,
 :        e.g., "show" is a cause of "see."
 :
 :

 :

 :      derivationally related form
 :
 :        A word that is derived from a root word,
 :        e.g., "metric" is a derivationally related form of "meter."
 :
 :

 :

 :      derived from adjective
 :
 :        An adverb that is derived from an adjective,
 :        e.g., "correctly" is derived from the adjective "correct."
 :
 :

 :

 :      entailment
 :
 :        A verb that presupposes another,
 :        e.g., "snoring" entails "sleeping."
 :
 :

 :

 :      hypernym
 :
 :        A word with a broad meaning that more specific words fall under,
 :        e.g., "meal" is a hypernym of "breakfast."
 :
 :

 :

 :      hyponym
 :
 :        A word of more specific meaning than a general term applicable to it,
 :        e.g., "breakfast" is a hyponym of "meal."
 :
 :

 :

 :      instance hypernym
 :
 :        A word that denotes a category of some specific instance,
 :        e.g., "author" is an instance hypernym of "Asimov."
 :
 :

 :

 :      instance hyponym
 :
 :        A term that donotes a specific instance of some general category,
 :        e.g., "Asimov" is an instance hyponym of "author."
 :
 :

 :

 :      member holonym
 :
 :        A word that denotes a collection of individuals,
 :        e.g., "faculty" is a member holonym of "professor."
 :
 :

 :

 :      member meronym
 :
 :        A word that denotes a member of a larger group,
 :        e.g., a "person" is a member meronym of a "crowd."
 :
 :

 :

 :      part holonym
 :
 :        A word that denotes a larger whole comprised of some part,
 :        e.g., "car" is a part holonym of "engine."
 :
 :

 :

 :      part meronym
 :
 :        A word that denotes a part of a larger whole,
 :        e.g., an "engine" is part meronym of a "car."
 :
 :

 :

 :      participle of verb
 :
 :        An adjective that is the participle of some verb,
 :        e.g., "breaking" is the participle of the verb "break."
 :
 :

 :

 :      pertainym
 :
 :        An adjective that classifies its noun,
 :        e.g., "musical" is a pertainym in "musical instrument."
 :
 :

 :

 :      similar to
 :
 :        Similar, though not necessarily interchangeable, adjectives.
 :        For example, "shiny" is similar to "bright",
 :        but they have subtle differences.
 :
 :

 :

 :      substance holonym
 :
 :        A word that denotes a larger whole containing some constituent
 :        substance, e.g., "bread" is a substance holonym of "flour."
 :
 :

 :

 :      substance meronym
 :
 :        A word that denotes a constituant substance of some larger whole,
 :        e.g., "flour" is a substance meronym of "bread."
 :
 :

 :

 :      verb group
 :
 :        A verb that is a member of a group of similar verbs,
 :        e.g., "live" is in the verb group
 :        of "dwell", "live", "inhabit", etc.
 :
 :

 :

 :
Notes on tokenization

 : For general information about Zorba's implementation of tokenization,
 : including what constitutes a token,
 : see the Full Text Tokenizer documentation.
 : @author Paul J. Lucas
 :)
module namespace ft = "http://www.zorba-xquery.com/modules/full-text";

import schema namespace ft-schema =
  "http://www.zorba-xquery.com/modules/full-text";

declare namespace err = "http://www.w3.org/2005/xqt-errors";
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";

(:===========================================================================:)

(:~
 : Predeclared constant for the Danish
 : xs:language.
 :)
declare variable $ft:lang-da as xs:language := xs:language("da");

(:~
 : Predeclared constant for the German
 : xs:language.
 :)
declare variable $ft:lang-de as xs:language := xs:language("de");

(:~
 : Predeclared constant for the English
 : xs:language.
 :)
declare variable $ft:lang-en as xs:language := xs:language("en");

(:~
 : Predeclared constant for the Spanish
 : xs:language.
 :)
declare variable $ft:lang-es as xs:language := xs:language("es");

(:~
 : Predeclared constant for the Finnish
 : xs:language.
 :)
declare variable $ft:lang-fi as xs:language := xs:language("fi");

(:~
 : Predeclared constant for the French
 : xs:language.
 :)
declare variable $ft:lang-fr as xs:language := xs:language("fr");

(:~
 : Predeclared constant for the Hungarian
 : xs:language.
 :)
declare variable $ft:lang-hu as xs:language := xs:language("hu");

(:~
 : Predeclared constant for the Italian
 : xs:language.
 :)
declare variable $ft:lang-it as xs:language := xs:language("it");

(:~
 : Predeclared constant for the Dutch
 : xs:language.
 :)
declare variable $ft:lang-nl as xs:language := xs:language("nl");

(:~
 : Predeclared constant for the Norwegian
 : xs:language.
 :)
declare variable $ft:lang-no as xs:language := xs:language("no");

(:~
 : Predeclared constant for the Portuguese
 : xs:language.
 :)
declare variable $ft:lang-pt as xs:language := xs:language("pt");

(:~
 : Predeclared constant for the Romanian
 : xs:language.
 :)
declare variable $ft:lang-ro as xs:language := xs:language("ro");

(:~
 : Predeclared constant for the Russian
 : xs:language.
 :)
declare variable $ft:lang-ru as xs:language := xs:language("ru");

(:~
 : Predeclared constant for the Swedish
 : xs:language.
 :)
declare variable $ft:lang-sv as xs:language := xs:language("sv");

(:~
 : Predeclared constant for the Turkish
 : xs:language.
 :)
declare variable $ft:lang-tr as xs:language := xs:language("tr");

(:===========================================================================:)

(:~
 : Gets the current compare options.
 :
 : @return said compare options.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-current-compare-options-1.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-current-compare-options-2.xq
 :)
declare function ft:current-compare-options()
  as element(ft-schema:compare-options) external;

(:~
 : Gets the current
 : language:
 : either the language specified by the
 : declare ft-option using
 : language
 : statement (if any)
 : or the one returned by ft:host-lang() (if none).
 :
 : @return said language.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-current-lang-true-1.xq
 :)
declare function ft:current-lang()
  as xs:language external;

(:~
 : Gets the host's current
 : language.
 : The "host" is the computer on which Zorba is running.
 : The host's current language is obtained as follows:
 :

 :

 :      For *nix systems:
 :

 :

 :          If setlocale(3) returns non-null,
 :          the language corresponding to that locale is used.
 :

 :

 :          Else, if the LANG environment variable is set,
 :          that language is ued.
 :

 :

 :          Otherwise, there is no default language.
 :

 :

 :

 :

 :      For Windows systems,
 :      the language corresponding to the locale returned by the
 :      GetLocaleInfo()
 :      function is used.
 :

 :

 :
 : @return said language.
 :)
declare function ft:host-lang()
  as xs:language external;

(:~
 : Checks whether the given
 : language
 : is supported for stemming.
 :
 : @param $lang The language to check.
 : @return true only if the language is supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stem-lang-es-supported-true.xq
 :)
declare function ft:is-stem-lang-supported( $lang as xs:language )
  as xs:boolean external;

(:~
 : Checks whether the given word is a stop-word.
 :
 : @param $word The word to check.
 : @param $lang The
 : language
 : of $word.
 : @return true only if $word is a stop-word.
 : @error err:FTST0009 if $lang is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-true-1.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-true-3.xq
 :)
declare function ft:is-stop-word( $word as xs:string, $lang as xs:language )
  as xs:boolean external;

(:~
 : Checks whether the given word is a stop-word.
 :
 : @param $word The word to check.
 : The word's language
 : is assumed to be the one returned by ft:current-lang().
 : @return true only if $word is a stop-word.
 : @error err:FTST0009 if ft:current-lang() is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-true-2.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-true-4.xq
 :)
declare function ft:is-stop-word( $word as xs:string )
  as xs:boolean external;

(:~
 : Checks whether the given
 : language
 : is supported for stop words.
 :
 : @param $lang The language to check.
 : @return true only if the language is supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-lang-en-supported-true.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-lang-supported-false-1.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-lang-supported-false-2.xq
 :)
declare function ft:is-stop-word-lang-supported( $lang as xs:language )
  as xs:boolean external;

(:~
 : Checks whether the given
 : language
 : is supported for look-up using the default thesaurus.
 :
 : @param $lang The language to check.
 : @return true only if the language is supported.
 :)
declare function ft:is-thesaurus-lang-supported( $lang as xs:language )
  as xs:boolean external;

(:~
 : Checks whether the given
 : language
 : is supported for look-up using the thesaurus specified by the given URI.
 :
 : @param $uri The URI specifying the thesaurus to use.
 : @param $lang The language to check.
 : @return true only if the language is supported.
 : @error err:FTST0018 if $uri refers to a thesaurus
 : that is not found in the statically known thesauri.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-thesaurus-lang-supported-true-1.xq
 :)
declare function ft:is-thesaurus-lang-supported( $uri as xs:string,
                                                 $lang as xs:language )
  as xs:boolean external;

(:~
 : Checks whether the given
 : language
 : is supported for tokenization.
 :
 : @param $lang The language to check.
 : @return true only if the language is supported.
 :)
declare function ft:is-tokenizer-lang-supported( $lang as xs:language )
  as xs:boolean external;

(:~
 : Stems the given word.
 :
 : @param $word The word to stem.
 : @param $lang The
 : language
 : of $word.
 : @return the stem of $word.
 : @error err:FTST0009 if $lang is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-stem-1.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-stem-2.xq
 :)
declare function ft:stem( $word as xs:string, $lang as xs:language )
  as xs:string external;

(:~
 : Stems the given word.
 :
 : @param $word The word to stem.
 : The word's language
 : is assumed to be the one returned by ft:current-lang().
 : @return the stem of $word.
 : @error err:FTST0009 if ft:current-lang() is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-stem-3.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-stem-4.xq
 :)
declare function ft:stem( $word as xs:string )
  as xs:string external;

(:~
 : Strips all diacritical marks from all characters.
 :
 : @param $string The string to strip diacritical marks from.
 : @return $string with diacritical marks stripped.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-strip-diacritics-1.xq
 :)
declare function ft:strip-diacritics( $string as xs:string )
  as xs:string external;

(:~
 : Looks-up the given phrase in the default thesaurus.
 :
 : @param $phrase The phrase to look up.
 : The phrase's
 : language
 : is assumed to be the one returned by ft:current-lang().
 : @return the related phrases if $phrase is found in the
 : thesaurus or the empty sequence if not.
 : @error err:FTST0009 if ft:current-lang() is not supported.
 : @error zerr:ZXQP8401 if the thesaurus data file's version is not supported
 : by the currently running version of Zorba.
 : @error zerr:ZXQP8402 if the thesaurus data file's endianness does not match
 : that of the CPU on which Zorba is currently running.
 : @error zerr:ZXQP8403 if there was an error reading the thesaurus data.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-thesaurus-lookup-1.xq
 :)
declare function ft:thesaurus-lookup( $phrase as xs:string )
  as xs:string* external;

(:~
 : Looks-up the given phrase in the thesaurus specified by the given URI.
 :
 : @param $uri The URI specifying the thesaurus to use.
 : @param $phrase The phrase to look up.
 : @param $lang The
 : language
 : of $phrase.
 : @return the related phrases if $phrase is found in the
 : thesaurus or the empty sequence if not.
 : @error err:FTST0009 if $lang is not supported.
 : @error err:FTST0018 if $uri refers to a thesaurus
 : that is not found in the statically known thesauri.
 : @error zerr:ZOSE0001 if the thesaurus data file could not be found.
 : @error zerr:ZOSE0002 if the thesaurus data file is not a plain file.
 : @error zerr:ZXQP8401 if the thesaurus data file's version is not supported
 : by the currently running version of Zorba.
 : @error zerr:ZXQP8402 if the thesaurus data file's endianness does not match
 : that of the CPU on which Zorba is currently running.
 : @error zerr:ZXQP8403 if there was an error reading the thesaurus data file.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-thesaurus-lookup-2.xq
 :)
declare function ft:thesaurus-lookup( $uri as xs:string, $phrase as xs:string,
                                      $lang as xs:language )
  as xs:string* external;

(:~
 : Looks-up the given phrase in a thesaurus.
 :
 : @param $uri The URI specifying the thesaurus to use.
 : @param $phrase The phrase to look up.
 : The phrase's
 : language
 : is assumed to be the one the one returned by ft:current-lang().
 : @return the related phrases if $phrase is found in the
 : thesaurus or the empty sequence if not.
 : @error err:FTST0009 if ft:current-lang() is unsupported.
 : @error err:FTST0018 if $uri refers to a thesaurus
 : that is not found in the statically known thesauri.
 : @error zerr:ZOSE0001 if the thesaurus data file could not be found.
 : @error zerr:ZOSE0002 if the thesaurus data file is not a plain file.
 : @error zerr:ZXQP8401 if the thesaurus data file's version is not supported
 : by the currently running version of Zorba.
 : @error zerr:ZXQP8402 if the thesaurus data file's endianness does not match
 : that of the CPU on which Zorba is currently running.
 : @error zerr:ZXQP8403 if there was an error reading the thesaurus data file.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-thesaurus-lookup-3.xq
 :)
declare function ft:thesaurus-lookup( $uri as xs:string, $phrase as xs:string )
  as xs:string* external;

(:~
 : Looks-up the given phrase in a thesaurus.
 :
 : @param $uri The URI specifying the thesaurus to use.
 : @param $phrase The phrase to look up.
 : @param $lang The
 : language
 : of $phrase.
 : @param $relationship The relationship the results are to have to
 : $phrase.
 : @return the related phrases if $phrase is found in the
 : thesaurus or the empty sequence if not.
 : @error err:FTST0018 if $uri refers to a thesaurus
 : that is not found in the statically known thesauri.
 : @error err:FTST0009 if $lang is not supported.
 : @error zerr:ZOSE0001 if the thesaurus data file could not be found.
 : @error zerr:ZOSE0002 if the thesaurus data file is not a plain file.
 : @error zerr:ZXQP8401 if the thesaurus data file's version is not supported
 : by the currently running version of Zorba.
 : @error zerr:ZXQP8402 if the thesaurus data file's endianness does not match
 : that of the CPU on which Zorba is currently running.
 : @error zerr:ZXQP8403 if there was an error reading the thesaurus data file.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-thesaurus-lookup-4.xq
 :)
declare function ft:thesaurus-lookup( $uri as xs:string, $phrase as xs:string,
                                      $lang as xs:language,
                                      $relationship as xs:string )
  as xs:string* external;

(:~
 : Looks-up the given phrase in a thesaurus.
 :
 : @param $uri The URI specifying the thesaurus to use.
 : @param $phrase The phrase to look up.
 : @param $lang The
 : language
 : of $phrase.
 : @param $relationship The relationship the results are to have to
 : $phrase.
 : @param $level-least The minimum number of levels within the thesaurus to be
 : travers$ed.
 : @param $level-most The maximum number of levels within the thesaurus to be
 : traversed.
 : @return the related phrases if $phrase is found in the
 : thesaurus or the empty sequence if not.
 : @error err:FOCA0003 if either $level-least or
 : $level-most is either negative or too large.
 : @error err:FTST0018 if $uri refers to a thesaurus
 : that is not found in the statically known thesauri.
 : @error err:FTST0009 if $lang is not supported.
 : @error zerr:ZOSE0001 if the thesaurus data file could not be found.
 : @error zerr:ZOSE0002 if the thesaurus data file is not a plain file.
 : @error zerr:ZXQP8401 if the thesaurus data file's version is not supported
 : by the currently running version of Zorba.
 : @error zerr:ZXQP8402 if the thesaurus data file's endianness does not match
 : that of the CPU on which Zorba is currently running.
 : @error zerr:ZXQP8403 if there was an error reading the thesaurus data file.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-thesaurus-lookup-5.xq
 :)
declare function ft:thesaurus-lookup( $uri as xs:string, $phrase as xs:string,
                                      $lang as xs:language,
                                      $relationship as xs:string,
                                      $level-least as xs:integer,
                                      $level-most as xs:integer )
  as xs:string* external;

(:~
 : Tokenizes the given node and all of its decendants.
 :
 : @param $node The node to tokenize.
 : @param $lang The default
 : language
 : of $node.
 : @return a (possibly empty) sequence of tokens.
 : @error err:FTST0009 if $lang is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-node-1.xq
 :)
declare function ft:tokenize-node( $node as node(), $lang as xs:language )
  as element(ft-schema:token)* external;

(:~
 : Tokenizes the given node and all of its descendants.
 :
 : @param $node The node to tokenize.
 : The node's default
 : language
 : is assumed to be the one returned by ft:current-lang().
 : @return a (possibly empty) sequence of tokens.
 : @error err:FTST0009 if ft:current-lang() is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-node-2.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-node-3.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-node-4.xq
 :)
declare function ft:tokenize-node( $node as node() )
  as element(ft-schema:token)* external;

(:~
 : Tokenizes the set of nodes comprising $includes (and all of its
 : descendants) but excluding $excludes (and all of its
 : descendants), if any.
 :
 : @param $includes The set of nodes (and its descendants) to include.
 : The default
 : language
 : is assumed to be the one returned by ft:current-lang().
 : @param $excludes The set of nodes (and its descendants) to exclude.
 : @return a (possibly empty) sequence of tokens.
 : @error err:FTST0009 if ft:current-lang() is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-nodes-1.xq
 :)
declare function ft:tokenize-nodes( $includes as node()+,
                                    $excludes as node()* )
  as element(ft-schema:token)* external;

(:~
 : Tokenizes the set of nodes comprising $includes (and all of its
 : descendants) but excluding $excludes (and all of its
 : descendants), if any.
 :
 : @param $includes The set of nodes (and its descendants) to include.
 : @param $excludes The set of nodes (and its descendants) to exclude.
 : @param $lang The default
 : language
 : for nodes.
 : @return a (possibly empty) sequence of tokens.
 : @error err:FTST0009 if $lang is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-nodes-1.xq
 :)
declare function ft:tokenize-nodes( $includes as node()+,
                                    $excludes as node()*,
                                    $lang as xs:language )
  as element(ft-schema:token)* external;

(:~
 : Tokenizes the given string.
 :
 : @param $string The string to tokenize.
 : @param $lang The
 : language
 : of $string.
 : @return a (possibly empty) sequence of tokens.
 : @error err:FTST0009 if $lang is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-string-1.xq
 :)
declare function ft:tokenize-string( $string as xs:string,
                                     $lang as xs:language )
  as xs:string* external;

(:~
 : Tokenizes the given string.
 :
 : @param $string The string to tokenize.
 : The string's
 : language
 : is assumed to be the one returned by ft:current-lang().
 : @return a (possibly empty) sequence of tokens.
 : @error err:FTST0009 if ft:current-lang() is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-string-2.xq
 :)
declare function ft:tokenize-string( $string as xs:string )
  as xs:string* external;

(:~
 : Gets properties of the tokenizer for the given
 : language.
 :
 : @param $lang The language of the tokenizer to get the properties of.
 : @return said properties.
 : @error err:FTST0009 if $lang is not supported.
 : tokenization specifically.
 :)
declare function ft:tokenizer-properties( $lang as xs:language )
  as element(ft-schema:tokenizer-properties) external;

(:~
 : Gets properties of the tokenizer for the
 : language
 : returned by ft:current-lang().
 :
 : @return said properties.
 : @error err:FTST0009 if ft:current-lang() is not supported.
 :)
declare function ft:tokenizer-properties()
  as element(ft-schema:tokenizer-properties) external;

(:===========================================================================:)

(: vim:set et sw=2 ts=2: :)


Fixed index page to correspond with new document collection as a variable.

import module namespace notes="http://cefn.com/readinglog/notes" at "/home/cefn/Documents/highwire/participatory firmware design/readinglog/scripts/server/xquery/lib/notes.xq";
import module namespace template="http://cefn.com/readinglog/template" at "/home/cefn/Documents/highwire/participatory firmware design/readinglog/scripts/server/xquery/lib/template.xq";
declare default element namespace "http://www.w3.org/1999/xhtml";

template:webpage(

		{for $heading in $notes:allnotes//h1 return
{string($heading)}
}

)

import module namespace notes="http://cefn.com/readinglog/notes" at "/home/cefn/Documents/highwire/participatory firmware design/readinglog/scripts/server/xquery/lib/notes.xq";
import module namespace template="http://cefn.com/readinglog/template" at "/home/cefn/Documents/highwire/participatory firmware design/readinglog/scripts/server/xquery/lib/template.xq";
declare default element namespace "http://www.w3.org/1999/xhtml";

template:webpage(

		{for $heading in notes:allnotes()//h1 return
{string($heading)}
}

)


Reformatting

Reformatting

xquery version "3.0";

(:~
 : Origami transformers.
 :
 : @version 0.3
 : @author Marc van Grootel
 : @see https://github.com/xokomola/origami
 :)

module namespace xf = 'http://xokomola.com/xquery/origami/xform';

(:~
 : Transforms input, using the specified templates.
 :)
declare function xf:transform($templates as map(*)*, $input as item()*) as item()* {
    xf:transform($templates)($input)
};

(:~
 : Returns a node transformation function.
 :)
declare function xf:transform($templates as map(*)*) as function(*) {
    function ($nodes as item()*) as item()* {
        xf:apply($nodes, $templates)
    }
};

(:~
 : Identity transformer.
 :)
declare function xf:transform() { xf:transform(()) };

(:~
 : Extracts nodes from input, using the specified selectors.
 :)
declare function xf:extract($selectors as function(*)*, $input as item()*)
    as item()* {
    xf:extract($selectors)($input)
};

(:~
 : Returns an extractor function that only returns selected nodes.
 :)
declare function xf:extract($selectors as function(*)*)
    as function(*) {
    function ($nodes as item()*) as item()* {
        xf:distinct-nodes(xf:select($nodes, $selectors))
    }
};

(:~
 : Defines a template.
 :
 : A template takes a selector string or function and
 : a node transformation function or the items to return as
 : the template body.
 : Providing invalid matcher returns empty sequence.
 :)
declare function xf:template($selector, $body)
    as map(*)? {
    let $selector :=
        typeswitch ($selector)
        case xs:string return xf:matches(?, $selector)
        case function(item()) as xs:boolean return $selector
        default return ()
    let $body :=
        typeswitch ($body)
        case empty-sequence() return function($node) { () }
        case function(item()) as item()* return $body
        case function(*)* return ()
        default return function($node) { $body }
    where $selector instance of function(*) and $body instance of function(*)
    return
        map {
            'selector': $selector,
            'fn': $body
        }
};

declare function xf:select($selector) as function(item())
    as item()* {
    xf:xpath-matches($selector)
};

(:~
 : Copies nodes to output, and calls apply for
 : nodes that are wrapped inside <xf:apply>.
 :)
declare %private function xf:copy($nodes as item()*, $xform as map(*)*)
    as item()* {
    for $node in $nodes
    return
        if ($node/self::xf:apply) then
            xf:apply(($node/@*,$node/node()), $xform)
        else if ($node instance of element()) then
            element { node-name($node) } {
                $node/@*,
                xf:copy($node/node(), $xform)
            }
        else if ($node instance of document-node()) then
            document {
                xf:copy($node/node(), $xform)
            }
        else
            $node
};

(:~
 : Applies node transformations to nodes.
 :)
declare %private function xf:apply($nodes as item()*, $xform as map(*)*)
    as item()* {
    for $node in $nodes
    let $match := xf:match($node, $xform)
    return
        if ($match instance of function(*)) then
            xf:copy($match($node), $xform)
        else if ($node instance of element()) then
            element { node-name($node) } {
                xf:apply($node/@*, $xform),
                xf:apply($node/node(), $xform)
            }
        else if ($node instance of document-node()) then
            document {
                xf:apply($node/node(), $xform)
            }
        else
            $node
};

(:~
 : Apply to be used from within templates.
 :)
declare function xf:apply($nodes as item()*)
    as element(xf:apply) {
    <xf:apply>{ $nodes }</xf:apply>
};

(:~
 : Return matching nodes.
 :
 : This returns nodes in breadth-first order not in conventional document order.
 :)
declare %private function xf:select($nodes as item()*, $selectors as function(*)*)
    as item()* {
    for $node in $nodes
    return (
        for $selector in $selectors
        return
            $selector($node),
            (: descend :)
            typeswitch($node)
            case element()
            return
                xf:select($node/node(), $selectors)
            case document-node()
            return
                xf:select($node/node(), $selectors)
            default
            return
                ()
    )
};

(:~
 : Find the first matching template for a node and return
 : it's node transformation function.
 :)
declare %private function xf:match($node as item(), $xform as map(*)*)
    as function(*)? {
    hof:until(
        function($templates as map(*)*) {
            let $is-match := head($templates)
            return
                empty($is-match) or
                not($is-match instance of map(*))
        },
        function($templates as map(*)*) {
            let $template := head($templates)
            return
                (
                    if ($template('selector')($node)) then
                        $template('fn')
                    else
                        ()
                    ,
                    tail($templates)
                )
        },
        $xform
    )[1]
};

(:~
 : Returns true if the string expression matches the $node.
 :)
declare function xf:matches($node as item(), $selector as xs:string)
    as xs:boolean {
    typeswitch ($node)
    case element() return not($node/self::xf:*) and $selector = (name($node),'*')
    case attribute() return substring-after($selector, '@') = (name($node), '*')
    default return false()
};

(:~
 : Match using XPath (only works in xf:select)
 :)
declare function xf:xpath-matches($selector as xs:string)
    as function(item()) as item()* {
    function($node as item()*) as item()* {
        xquery:eval($selector, map { '': $node })
    }
};

(:~
 : Returns only distinct nodes.
 : @see http://www.xqueryfunctions.com/xq/functx_distinct-nodes.html
 :)
declare %private function xf:distinct-nodes($nodes as node()*)
    as node()* {
    for $seq in (1 to count($nodes))
    return $nodes[$seq][
        not(xf:is-node-in-sequence(
            .,$nodes[position() < $seq]))]
};

(:~
 : Is node defined in seq?
 : @see http://www.xqueryfunctions.com/xq/functx_is-node-in-sequence.html
 :)
declare %private function xf:is-node-in-sequence ($node as node()?, $seq as node()*)
    as xs:boolean {
    some $nodeInSeq in $seq satisfies $nodeInSeq is $node
 };


deleting otherid by code and value

deleting otherid by code and value

import module namespace csd_bl = "https://github.com/openhie/openinfoman/csd_bl";
import module namespace csd_blu = "https://github.com/openhie/openinfoman/csd_blu" ;
declare default element  namespace   "urn:ihe:iti:csd:2013";
declare variable $careServicesRequest as item() external;

(:
   The query will be executed against the root element of the CSD document.

   The dynamic context of this query has $careServicesRequest set to contain any of the search
   and limit paramaters as sent by the Service Finder
:)
  if (exists($careServicesRequest/id/otherID/@code))
    then
    let $facilities := if (exists($careServicesRequest/id/@entityID)) then csd_bl:filter_by_primary_id(/CSD/facilityDirectory/*,$careServicesRequest/id) else ()
    return
      if ( count($facilities) = 1 )
	then
	let  $id :=  $facilities[1]/otherID[@code = $careServicesRequest/id/otherID/@code and @assigningAuthorityName = $careServicesRequest/id/otherID/@assigningAuthorityName and ./text() = $careServicesRequest/id/otherID/text()]
	return if (exists($id)) then (delete node $id) else ()
      else  ()
    else ()

import module namespace csd_bl = "https://github.com/openhie/openinfoman/csd_bl";
import module namespace csd_blu = "https://github.com/openhie/openinfoman/csd_blu" ;
declare default element  namespace   "urn:ihe:iti:csd:2013";
declare variable $careServicesRequest as item() external;

(:
   The query will be executed against the root element of the CSD document.

   The dynamic context of this query has $careServicesRequest set to contain any of the search
   and limit paramaters as sent by the Service Finder
:)
  if (exists($careServicesRequest/id/otherID/@code))
    then
    let $facilities := if (exists($careServicesRequest/id/@entityID)) then csd_bl:filter_by_primary_id(/CSD/facilityDirectory/*,$careServicesRequest/id) else ()
    return
      if ( count($facilities) = 1 )
	then
	let  $id :=  $facilities[1]/otherID[@code = $careServicesRequest/id/otherID/@code and @assigningAuthorityName = $careServicesRequest/id/otherID/@assigningAuthorityName]
	return if (exists($id)) then (delete node $id) else ()
      else  ()
    else ()


Changes to Json module: - changed the accepted type of the parameter to "element(json-options:options)" instead of "element(json-options:options)?" - jsonparam was updated to json-param

import module namespace doc = "http://www.zorba-xquery.com/modules/store/dynamic/documents";

import module namespace j = "http://www.zorba-xquery.com/modules/converters/json";

j:serialize(
  doc:document("meat_poultry.xml")/root/row,
  <options xmlns="http://www.zorba-xquery.com/modules/converters/json-options" >
    <json-param name="mapping" value="json-ml" />
  </options>
)

import module namespace doc = "http://www.zorba-xquery.com/modules/store/dynamic/documents";

import module namespace j = "http://www.zorba-xquery.com/modules/converters/json";

j:serialize(
  doc:document("meat_poultry.xml")/root/row,
  <options xmlns="http://www.zorba-xquery.com/modules/converters/json-options" >
    <jsonParam name="mapping" value="json-ml" />
  </options>
)