@@ -3,13 +3,15 @@ xquery version "3.0";
33(:~ ================================================
44 Implements the documentation search.
55 ================================================ :)
6- module namespace dq= "http://exist-db.org/xquery/documentation/search" ;
6+ module namespace dq = "http://exist-db.org/xquery/documentation/search" ;
77
8- import module namespace config= "http://exist-db.org/xquery/apps/config" at "config.xqm" ;
8+ import module namespace config = "http://exist-db.org/xquery/apps/config" at "config.xqm" ;
99
10- import module namespace kwic="http://exist-db.org/xquery/kwic" ;
10+ import module namespace kwic = "http://exist-db.org/xquery/kwic" ;
11+ import module namespace util = "http://exist-db.org/xquery/util" ;
1112
12- declare namespace templates="http://exist-db.org/xquery/templates" ;
13+ declare namespace db5 = "http://docbook.org/ns/docbook" ;
14+ declare namespace templates = "http://exist-db.org/xquery/templates" ;
1315
1416declare option exist:serialize "method=html media-type=text/html expand-xincludes=yes" ;
1517
@@ -20,54 +22,142 @@ declare variable $dq:CHARS_KWIC := 80;
2022 Templating function: process the query.
2123:)
2224declare
23- %public %templates:default("field" , "all" ) %templates:default("view" , "summary" )
24- function dq:query ($node as node ()*, $model as map (*), $q as xs:string?, $field as xs:string, $view as xs:string) {
25+ %public
26+ %templates:default("field" , "all" )
27+ %templates:default("view" , "summary" )
28+ function dq:query ($node as node ()*, $model as map (*), $q as xs:string?, $field as xs:string, $view as xs:string) as element (div )? {
2529 if ($q) then
2630 let $hits := dq:do-query (collection ($config:data-root), $q, $field)
27- let $search-params :=
28- string-join (
29- map-pairs (function ($k, $v) { $k || "=" || $v }, ("q" , "field" ), ($q, $field)),
30- "& "
31- )
3231 return
3332 <div id = "f-search" >
34- {dq:print-results ($hits, $search-params, $view)}
33+ {
34+ dq:print-results ($hits, map { "q" : $q, "field" : $field}, $view)
35+ }
3536 </div>
3637 else
3738 ()
3839};
3940
41+ (:~
42+ : Returns the elements for which the $query matches.
43+ :
44+ : @param context the nodes to search
45+ : @param query the full-text query
46+ : @param field the name of a field, if the query should be restricted to a specific field
47+ :
48+ : @return The elements that match the query, typically one of:
49+ : db5:title, db5:keyword, db5:para, db5:sect1, db5:sect2, db5:sect3.
50+ :)
51+ declare
52+ %public
53+ function dq:do-query ($context as node ()*, $query as xs:string?, $field as xs:string?) as element ()* {
54+ switch ($field)
55+ case "title" return
56+ $context/db5:article/db5:info/db5:title[ft:query (., $query)]
57+ |
58+ $context//(db5:sect3|db5:sect2|db5:sect1)/db5:title[ft:query (., $query)]
59+
60+ default return
61+ $context//db5:keyword[ft:query (., $query)]
62+ |
63+ $context/db5:article/(db5:info/db5:title|db5:para)[ft:query (., $query)]
64+ |
65+ $context//(db5:sect3|db5:sect2|db5:sect1)/db5:title[ft:query (., $query)]
66+ |
67+ $context//(db5:sect3|db5:sect2|db5:sect1)[ft:query (., $query)]
68+ };
69+
70+ (:~
71+ Display the query results.
72+ :)
73+ declare
74+ %private
75+ function dq:print-results ($hits as element ()*, $search-params as map (xs:string, xs:string), $view as xs:string) {
76+ <div id = "f-results" >
77+ <p class = "heading" >Found {count ($hits)} result{if (count ($hits) eq 1 ) then "" else "s" }.</p>
78+ {
79+ if ($view eq 'summary' ) then
80+ for $hit in $hits
81+ let $score := ft:score ($hit)
82+ order by $score descending
83+ return
84+ <div class = "section" >
85+ <span class = "score" >Score: {round-half-to-even ($score, 2 )}</span>
86+ <div class = "headings" >{ dq:print-headings ($hit, $search-params) }</div>
87+ { dq:print ($hit, $search-params, $view) }
88+ </div>
89+ else
90+ <table class = "kwic" >
91+ {
92+ for $hit in $hits
93+ order by ft:score ($hit) descending
94+ return (
95+ <tr>
96+ <td class = "headings" colspan = "3" >
97+ {dq:print-headings ($hit, $search-params)}
98+ </td>
99+ </tr>,
100+ dq:print ($hit, $search-params, $view)
101+ )
102+ }
103+ </table>
104+ }
105+ </div>
106+ };
107+
108+ (:~
109+ Print the hierarchical context of a hit.
110+ :)
111+ declare
112+ %private
113+ function dq:print-headings ($hit as element (), $search-params as map (xs:string, xs:string)) {
114+ let $search-params-uri-query := dq:to-uri-query ($search-params)
115+ let $uri := util:document-name (root ($hit)) || "?" || $search-params-uri-query || "& id=D" || util:node-id ($hit)
116+ return
117+ (
118+ <a href = "{$uri} " >{$hit/ancestor-or-self::db5:article/db5:info/db5:title/text ()}</a>
119+ ,
120+ for $sect at $pos in $hit/(ancestor-or-self::db5:sect3|ancestor-or-self::db5:sect2|ancestor-or-self::db5:sect1)
121+ let $nodeId := util:node-id ($sect)
122+ let $uri := util:document-name (root ($sect)) || "?" || $search-params-uri-query || "& id=D" || $nodeId || "#D" || $nodeId
123+ return
124+ (" > " , <a href = "{$uri} " >{$sect/db5:title/text ()}</a>)
125+ )
126+ };
127+
128+
40129(:~
41130 Display the hits: this function iterates through all hits and calls
42131 kwic:summarize to print out a summary of each match.
43132:)
44- declare %private function dq:print ($hit as element (), $search-params as xs:string, $view as xs:string)
45- as element ()* {
46- let $nodeId := util:node-id ($hit)
47- let $uri := util:document-name (root ($hit)) || "?" ||
48- $search-params || "& id=D" || $nodeId || "#D" || $nodeId
49- let $config :=
50- <config xmlns = "" width = "{if ($view eq 'summary' ) then $dq:CHARS_SUMMARY else $dq:CHARS_KWIC} "
51- table = "{if ($view eq 'summary' ) then 'no' else 'yes' } "
52- link = "{$uri} " />
133+ declare
134+ %private
135+ function dq:print ($hit as element (), $search-params as map (xs:string, xs:string), $view as xs:string) as element ()* {
53136 let $matches := kwic:get-matches ($hit)
54137 return
55138 if ($view eq "kwic" ) then
56- for $ancestor in ($matches/ancestor::para | $matches/ancestor::title | $matches/ancestor::td | $matches/ancestor::note[not (para)])
139+ let $nodeId := util:node-id ($hit)
140+ let $uri := util:document-name (root ($hit)) || "?" || dq:to-uri-query ($search-params) || "& id=D" || $nodeId || "#D" || $nodeId
141+ let $config :=
142+ <config xmlns = "" width = "{if ($view eq 'summary' ) then $dq:CHARS_SUMMARY else $dq:CHARS_KWIC} "
143+ table = "{if ($view eq 'summary' ) then 'no' else 'yes' } "
144+ link = "{$uri} " />
145+
146+ for $ancestor in ($matches/ancestor::db5:para | $matches/ancestor::db5:title | $matches/ancestor::db5:td | $matches/ancestor::db5:note[not (db5:para)])
57147 for $match in $ancestor//exist:match
58148 return
59149 kwic:get-summary ($ancestor, $match, $config)
60150 else
61- let $ancestors := ($matches/ancestor::para | $matches/ancestor::title | $matches/ancestor::td | $matches/ancestor::note[not (para)])
151+ let $ancestors := ($matches/ancestor::db5: para | $matches/ancestor::db5: title | $matches/ancestor::db5: td | $matches/ancestor::db5: note[not (db5: para)])
62152 return
63153 for $ancestor in $ancestors
64154 return
65155 dq:match-to-copy ($ancestor)
66156};
67157
68- declare function dq:match-to-copy ($element as element ())
69- as element ()
70- {
158+ declare
159+ %private
160+ function dq:match-to-copy ($element as element ()) as element () {
71161 element { node-name ($element) } {
72162 $element/@*,
73163 for $child in $element/node ()
@@ -82,72 +172,11 @@ as element()
82172 }
83173};
84174
85- (:~
86- Print the hierarchical context of a hit.
87- :)
88- declare %private function dq:print-headings ($section as element ()*, $search-params as xs:string) {
89- let $log := util:log ("DEBUG" , ("##$search-paramsxxx): " , $search-params))
90- let $nodeId := util:node-id ($section)
91- let $uri :=
92- util:document-name (root ($section)) || "?" || $search-params || "& id=D" || $nodeId
93- return
94- <a href = "{$uri} " >{$section/ancestor-or-self::chapter/title/text ()}</a>,
95- for $s at $p in $section/ancestor-or-self::section
96- let $nodeId := util:node-id ($s)
97- let $uri :=
98- util:document-name (root ($s)) || "?" || $search-params || "& id=D" || $nodeId || "#D" || $nodeId
99- return
100- (" > " , <a href = "{$uri} " >{$s/title/text ()}</a>)
101- };
102-
103- (:~
104- Display the query results.
105- :)
106- declare %private function dq:print-results ($hits as element ()*, $search-params as xs:string, $view as xs:string) {
107- <div id = "f-results" >
108- <p class = "heading" >Found {count ($hits)} result{
109- if (count ($hits) eq 1 ) then "" else "s" }.</p>
110- {
111- if ($view eq 'summary' ) then
112- for $section in $hits
113- let $score := ft:score ($section)
114- order by $score descending
115- return
116- <div class = "section" >
117- <span class = "score" >Score: {round-half-to-even ($score, 2 )}</span>
118- <div class = "headings" >{ dq:print-headings ($section, $search-params) }</div>
119- { dq:print ($section, $search-params, $view) }
120- </div>
121- else
122- <table class = "kwic" >
123- {
124- for $section in $hits
125- order by ft:score ($section) descending
126- return (
127- <tr>
128- <td class = "headings" colspan = "3" >
129- {dq:print-headings ($section, $search-params)}
130- </td>
131- </tr>,
132- dq:print ($section, $search-params, $view)
133- )
134- }
135- </table>
136- }
137- </div>
138- };
139-
140- declare %public function dq:do-query ($context as node ()*, $query as xs:string, $field as xs:string) {
141- if (count ($context) > 1 ) then
142- switch ($field)
143- case "title" return
144- $context//section[ft:query (.//title, $query)]
145- default return
146- $context//section[ft:query (.//title, $query)] | $context//section[ft:query (., $query)][not (section)]
147- else
148- switch ($field)
149- case "title" return
150- $context[.//section[ft:query (.//title, $query)]]
151- default return
152- $context[.//section[ft:query (.//title, $query)] or .//section[ft:query (., $query)][not (section)]]
175+ declare
176+ %private
177+ function dq:to-uri-query ($search-params as map (xs:string, xs:string)) as xs:string {
178+ string-join (
179+ map:for-each ($search-params, function ($k, $v) { $k || "=" || $v }),
180+ "& "
181+ )
153182};
0 commit comments