xquery version "3.0"; module namespace risten="http://exist-db.org/xquery/apps/risten"; declare namespace exist = "http://exist.sourceforge.net/NS/exist"; declare namespace xmldb="http://exist-db.org/xquery/xmldb"; declare namespace output="http://www.w3.org/2010/xslt-xquery-serialization"; declare option exist:serialize "method=xml media-type=text/xml indent=yes"; (:import module namespace r="http://exist-db.org/xquery/apps/r" at "search.xql";:) import module namespace config="http://exist-db.org/xquery/apps/config" at "xmldb:exist:/db/risten2/modules/config.xqm"; import module namespace templates="http://exist-db.org/xquery/templates" at "xmldb:exist:/db/risten2/modules/templates.xql"; declare variable $risten:SESSION := "risten:results"; (:~ Pick up the parameters start, langchoice and query sent by the javacript functions directSearch and delayedSearch Execute the query. The search results are not output immediately. Instead they are passed to nested templates through the $model parameter. :) declare %templates:wrap %templates:default("dict", "") function risten:query($node as node()*, $model as map(*), $query as xs:string?, $dict as xs:string) as map(*) { session:create(), (:let $dict := $model("dict"):) let $queryStr := concat('^', $query) let $hits := for $hit in (collection($config:data)//l[matches(., $queryStr, "i")], collection($config:data)//head[matches(., $queryStr, "i")]) order by $hit return $hit return map { "hits" := $hits } }; (:~ Read the last query result from the HTTP session and pass it to nested templates in the $model parameter. :) declare %templates:wrap function risten:from-session($node as node()*, $model as map(*)) { map:entry("hits", session:get-attribute($risten:SESSION)) }; (:~ Create a span with the number of items in the current search result. :) declare %templates:wrap function risten:hit-count($node as node()*, $model as map(*)) { { count($model("hits")) } }; declare %templates:wrap function risten:set-dict($node as node(), $model as map(*), $dict as xs:string) { map:entry("dict", $dict) }; (:~ Extract only the text from the hits, then show only the unique strings :) declare %templates:default("start", 1) function risten:show-hits($node as node()*, $model as map(*), $start as xs:int) { subsequence($model("hits"), 1, 10) (: let $hit-count := count($model("hits")) let $dict := $model("dict") return if (0 < $hit-count) then let $aggs := for $hit in subsequence($model("hits"), $start, 10) return $hit for $agg in distinct-values($aggs) order by $agg return

{$agg} {$dict}

else

No matches found

:) }; declare %templates:wrap function risten:show-dicts($node as node()*, $model as map(*)) { $model("dicts")//id (: let $hit-count := count($model("hits")) return if (0 < $hit-count) then let $dicts := for $hit at $p in subsequence($model("hits"), 1, $hit-count) let $id := root($hit)/@id return collection($config:data)//dictmeta[ $id = @id ]/id[@xml:lang="nob"]/text() for $dict at $pos in distinct-values($dicts) order by $dict return ( , ) else return ( , ) let $dicts := (collection($config:data)//dictmeta/id[1]/text(), collection($config:data)//termmeta/id[1]/text()) for $dict at $pos in distinct-values($dicts) let $dictname := $dicts[$pos]/../../id[@xml:lang = "nob"]/text() order by $dict return ( , ) :) }; declare %templates:wrap function risten:show-all-dicts($node as node()*, $model as map(*)) { , }; declare %templates:wrap function risten:dicts($node as node()*, $model as map(*)) as map(*) { map { "dicts" := (collection($config:data))//dictmeta } }; (:~ Show an article Catch the parameter article sent from the javascript function showArticle Pick the hits that have exactly the string article :) declare function risten:lemma-toHTML($node as node()*, $model as map(*), $article as xs:string*) { (: let $id := xmldb:decode(request:get-parameter("article",())) :) let $hits := $model("hits")[ text() = xmldb:decode($article)] let $dicts := for $hit in $hits return replace(base-uri($hit), "(.*/).*", "$1") for $dict in distinct-values($dicts) order by $dict return (

{collection($dict)//id[@xml:lang="nob"]/text()}

,

{$article}

,
    { for $hit in $hits return if ($hit[ replace(base-uri(.), "(.*/).*", "$1") = $dict]) then typeswitch ($hit/parent::node()/parent::node()) case element(e) return
  1. {risten:dict-toHTML($hit/parent::node()/parent::node())}
  2. case element(entry) return
  3. {risten:term-article($hit/parent::node()/parent::node())}
  4. default return () else () }
) }; (:~ Convert an e-element to html Don't show the l-element, it is already printed in risten:lemma-toHTML :) declare function risten:dict-toHTML($nodes as node()*) { for $node in $nodes return typeswitch ($node) case element(e) return
{ risten:dict-toHTML($node/node()) }
case element(l) return () case element(l_ref) return () case element(mg) return
{ risten:dict-toHTML($node/*) }
case element(t) return
{ risten:dict-toHTML($node/node()) }
case element(xg) return case element(x) return
  • { risten:dict-toHTML($node/node()) }
  • case element(xt) return
  • { risten:dict-toHTML($node/node()) }
  • case element() return risten:dict-toHTML($node/node()) default return $node }; (:~ Convert an entry-element to html :) declare function risten:term-toHTML($nodes as node()*) { for $node in $nodes return typeswitch ($node) case element(entry) return risten:term-toHTML($node/node()) case element(head) return
    { risten:term-toHTML($node/node()) } ({ string($node/parent::node()/parent::node()/parent::node()/@xml:lang) })
    case element(senses) return risten:term-toHTML($node/*) case element(def) return
    { risten:term-toHTML($node/node()) }
    case element(infl) return
    { risten:term-toHTML($node/node()) }
    case element() return risten:term-toHTML($node/node()) default return $node }; (:~ Convert term articles with the same idref to html Don't convert the article that was the origin for the search :) declare function risten:term-article($theterm as node()) { let $scope := collection($config:data)/terminology/entry let $idref := string($theterm/senses/sense/@idref) let $hits := for $hit in $scope[./senses/sense[@idref = $idref]] where not($theterm = $hit) return $hit return
    { for $hit in $hits return risten:term-toHTML($hit) }
    };