comparison software/eXist/webapp/mpdl/presentation/functions-text.xsl @ 7:5589d865af7a

Erstellung XQL/XSL Applikation
author Josef Willenborg <jwillenborg@mpiwg-berlin.mpg.de>
date Tue, 08 Feb 2011 15:16:46 +0100
parents
children 7e883ce72fec
comparison
equal deleted inserted replaced
6:2396a569e446 7:5589d865af7a
1 <?xml version="1.0"?>
2 <xsl:stylesheet version="2.0"
3 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
4 xmlns:xlink="http://www.w3.org/1999/xlink"
5 xmlns:saxon="http://saxon.sf.net/"
6 xmlns:functx="http://www.functx.com"
7 xmlns:text="http://www.mpiwg-berlin.mpg.de/ns/mpdl/text"
8 xmlns:xs="http://www.w3.org/2001/XMLSchema">
9
10 <xsl:import href="/db/mpdl/presentation/functions-functx.xsl" />
11
12 <!-- delivers a concatenation of n chars of the given char -->
13 <xsl:function name="text:nchars">
14 <xsl:param name="count" as="xs:integer"/>
15 <xsl:param name="char" as="xs:string"/>
16 <xsl:sequence select="if ($count > 1) then concat($char, text:nchars($count - 1, $char)) else $char"/>
17 </xsl:function>
18
19 <xsl:function name="text:sortWithComma">
20 <xsl:param name="inputString" as="xs:string"/>
21 <xsl:variable name="inputStrings" select="tokenize($inputString, '\|')"/>
22 <xsl:variable name="sortedInputStrings" select="functx:sort($inputStrings)"/>
23 <xsl:variable name="result">
24 <xsl:for-each select="$sortedInputStrings">
25 <xsl:value-of select="concat(., ', ')"/>
26 </xsl:for-each>
27 </xsl:variable>
28 <xsl:variable name="length" select="string-length($result)"/>
29 <xsl:choose>
30 <xsl:when test="$length > 0">
31 <xsl:value-of select="substring($result, 0, $length - 1)"/>
32 </xsl:when>
33 <xsl:otherwise>
34 <xsl:value-of select="''"/>
35 </xsl:otherwise>
36 </xsl:choose>
37 </xsl:function>
38
39 <!-- Compares inputString1 and inputString2 and removes the duplicates in -->
40 <!-- inputString1 and gives them back -->
41 <!-- inputString1 and inputString2 contain a list of strings separated by "|" -->
42 <xsl:function name="text:removeDuplicates">
43 <xsl:param name="inputString1" as="xs:string"/>
44 <xsl:param name="inputString2" as="xs:string"/>
45 <xsl:variable name="inputStrings1" select="tokenize($inputString1, '\|')"/>
46 <xsl:variable name="inputStrings2" select="tokenize($inputString2, '\|')"/>
47 <xsl:variable name="result">
48 <xsl:for-each select="$inputStrings1">
49 <xsl:variable name="str" select="."/>
50 <xsl:if test="not(text:contained($str, $inputStrings2))"><xsl:value-of select="concat($str, '|')"/></xsl:if>
51 </xsl:for-each>
52 </xsl:variable>
53 <xsl:variable name="length" select="string-length($result)"/>
54 <xsl:choose>
55 <xsl:when test="$length > 0">
56 <xsl:value-of select="substring($result, 0, $length)"/>
57 </xsl:when>
58 <xsl:otherwise>
59 <xsl:value-of select="''"/>
60 </xsl:otherwise>
61 </xsl:choose>
62 </xsl:function>
63
64 <xsl:function name="text:contained" as="xs:boolean">
65 <xsl:param name="arg" as="xs:string?"/>
66 <xsl:param name="searchStrings" as="xs:string*"/>
67 <xsl:sequence select="some $searchString in $searchStrings satisfies compare($arg, $searchString) = 0"/>
68 </xsl:function>
69
70 <xsl:function name="text:cutStringBefore">
71 <xsl:param name="inputString" as="xs:string"/>
72 <xsl:param name="cutLength" as="xs:integer"/>
73 <xsl:variable name="length" select="string-length($inputString)"/>
74 <xsl:variable name="cutString" select="substring($inputString, $length - $cutLength)"/>
75 <xsl:choose>
76 <xsl:when test="$length &gt; $cutLength">
77 (...)
78 <xsl:value-of select="text:cutFirstWord($cutString)"/>
79 </xsl:when>
80 <xsl:otherwise><xsl:value-of select="$cutString"/></xsl:otherwise>
81 </xsl:choose>
82 </xsl:function>
83
84 <xsl:function name="text:cutStringAfter">
85 <xsl:param name="inputString" as="xs:string"/>
86 <xsl:param name="cutLength" as="xs:integer"/>
87 <xsl:variable name="length" select="string-length($inputString)"/>
88 <xsl:variable name="cutString" select="substring($inputString, 0, $cutLength)"/>
89 <xsl:choose>
90 <xsl:when test="$length &gt; $cutLength">
91 <xsl:value-of select="text:cutLastWord($cutString)"/>
92 (...)
93 </xsl:when>
94 <xsl:otherwise><xsl:value-of select="$cutString"/></xsl:otherwise>
95 </xsl:choose>
96 </xsl:function>
97
98 <xsl:function name="text:cutFirstWord">
99 <xsl:param name="inputString" as="xs:string"/>
100 <xsl:value-of select="replace($inputString, '^.*?[\s:.,;!_]', ' ', 'im')"/>
101 </xsl:function>
102
103 <xsl:function name="text:cutLastWord">
104 <xsl:param name="inputString" as="xs:string"/>
105 <xsl:value-of select="replace($inputString, '(.*)[\s:.,;!_].*$', '$1 ', 'im')"/>
106 </xsl:function>
107
108 <xsl:function name="text:trim">
109 <xsl:param name="inputString" as="xs:string"/>
110 <xsl:variable name="trimBefore" select="replace($inputString, '^\s+(.*?)', '$1')"/>
111 <xsl:value-of select="replace($trimBefore, '(.*?)\s+$', '$1')"/>
112 </xsl:function>
113
114 <!-- Word delimiter: not tested yet -->
115 <!-- TODO: bol, eol, ", &, <, > -->
116 <!-- <xsl:variable name="wordDelimRegExpr" select="'[\s\(\)\[\]\.\\\{\}\$\^\+\?\!\* ยง%:,;=/]+'"/> -->
117
118 <!-- Tokenization of a Lucene query with phrases and words to a list of query terms separated with | -->
119 <xsl:function name="text:translateLuceneToTerms">
120 <xsl:param name="inputLuceneQuery" as="xs:string" />
121 <!-- Delete all parantheses outside quotes: (a AND b) OR c -> a AND b OR c -->
122 <xsl:variable name="luceneQueryWithoutParantheses1" select="replace($inputLuceneQuery, '([^\\])[()]', '$1')" />
123 <xsl:variable name="luceneQueryWithoutParantheses2" select="replace($luceneQueryWithoutParantheses1, '^[()]', '')" />
124 <!-- Unescape special chars in Lucene query -->
125 <xsl:variable name="luceneQueryUnescaped" select="replace($luceneQueryWithoutParantheses2, '\\([-\+&amp;|!(){}\[\]\^&quot;~*?:\\])', '$1')" />
126 <!-- Escape special chars which have a meta meaning in regular expressions -->
127 <xsl:variable name="luceneQueryRegExprEscaped1" select="replace($luceneQueryUnescaped, '[*]', '###Star###')" />
128 <xsl:variable name="luceneQueryRegExprEscaped2" select="replace($luceneQueryRegExprEscaped1, '[\+]', '###Plus###')" />
129 <xsl:variable name="luceneQueryRegExprEscaped3" select="replace($luceneQueryRegExprEscaped2, '[?]', '###QM###')" />
130 <xsl:variable name="luceneQueryRegExprEscaped4" select="replace($luceneQueryRegExprEscaped3, '[\.]', '###Dot###')" />
131 <xsl:variable name="luceneQueryRegExprEscaped5" select="replace($luceneQueryRegExprEscaped4, '[\^]', '###BeginLine###')" />
132 <xsl:variable name="luceneQueryRegExprEscaped6" select="replace($luceneQueryRegExprEscaped5, '[$]', '###EndLine###')" />
133 <xsl:variable name="luceneQueryRegExprEscaped7" select="replace($luceneQueryRegExprEscaped6, '[|]', '###Or###')" />
134 <xsl:variable name="luceneQueryRegExprEscaped8" select="replace($luceneQueryRegExprEscaped7, '[(]', '###Paranthes1Open###')" />
135 <xsl:variable name="luceneQueryRegExprEscaped9" select="replace($luceneQueryRegExprEscaped8, '[)]', '###Paranthes1Close###')" />
136 <xsl:variable name="luceneQueryRegExprEscaped10" select="replace($luceneQueryRegExprEscaped9, '[{]', '###Paranthes2Open###')" />
137 <xsl:variable name="luceneQueryRegExprEscaped11" select="replace($luceneQueryRegExprEscaped10, '[}]', '###Paranthes2Close###')" />
138 <xsl:variable name="luceneQueryRegExprEscaped12" select="replace($luceneQueryRegExprEscaped11, '[\[]', '###Paranthes3Open###')" />
139 <xsl:variable name="luceneQueryRegExprEscaped13" select="replace($luceneQueryRegExprEscaped12, '[\]]', '###Paranthes3Close###')" />
140 <xsl:variable name="luceneQueryRegExprEscaped14" select="replace($luceneQueryRegExprEscaped13, '~[0123456789,]*', '###Tilde###')" />
141 <xsl:value-of select="text:translateLuceneQueryToTermsMain($luceneQueryRegExprEscaped14, 'DUMMYDUMMYSTART')" />
142 </xsl:function>
143
144 <!-- Tokenization of a Lucene query with phrases and words to a list of query terms separated with | -->
145 <xsl:function name="text:translateLuceneQueryToTermsMain">
146 <xsl:param name="inputString" as="xs:string" />
147 <!-- last term in previous step: used for Lucene operator NOT) -->
148 <xsl:param name="lastFetchedTerm" as="xs:string" />
149 <xsl:choose>
150 <!-- single phrase: phrase is appended -->
151 <xsl:when test="matches($inputString, '^&quot;[^&quot;]*?&quot;$')">
152 <xsl:variable name="withoutSurroundingQuotes" select="substring-before(substring-after($inputString, '&quot;'), '&quot;')"/>
153 <xsl:variable name="termEscaped" select="text:escapeLucenePhraseForRegExpr($withoutSurroundingQuotes)" />
154 <xsl:variable name="term" select="text:translateLuceneQueryTermToTerm($termEscaped, $lastFetchedTerm)" />
155 <xsl:value-of select="$term" />
156 </xsl:when>
157 <!-- "+" followd by a single phrase: phrase is appended -->
158 <xsl:when test="matches($inputString, '^###Plus###&quot;[^&quot;]*?&quot;$')">
159 <xsl:variable name="length" select="string-length($inputString)"/>
160 <xsl:variable name="withoutSurroundingQuotes" select="substring($inputString, 12, $length - 12)"/>
161 <xsl:variable name="termEscaped" select="text:escapeLucenePhraseForRegExpr($withoutSurroundingQuotes)" />
162 <xsl:variable name="term" select="text:translateLuceneQueryTermToTerm($termEscaped, $lastFetchedTerm)" />
163 <xsl:value-of select="$term" />
164 </xsl:when>
165 <!-- "-" followd by a single phrase: phrase is not appended -->
166 <xsl:when test="matches($inputString, '^-&quot;[^&quot;]*?&quot;$')">
167 <xsl:value-of select="'DUMMYDUMMYMINUS'" />
168 </xsl:when>
169 <!-- TODO: single phrase followed by near operator (~[0123456789]+): determine distance between -->
170 <xsl:when test="matches($inputString, '^&quot;[^&quot;]*?&quot;~[0123456789]+$')">
171 <xsl:value-of select="$inputString" />
172 </xsl:when>
173 <!-- phrase followed by something: phrase is appended -->
174 <xsl:when test="matches($inputString, '^&quot;.*?&quot;\s')">
175 <xsl:variable name="afterFirstTerm" select="replace($inputString, '^&quot;.*?&quot;\s', '')"/>
176 <xsl:variable name="length" select="string-length($inputString)"/>
177 <xsl:variable name="afterFirstTermLength" select="string-length($afterFirstTerm)"/>
178 <xsl:variable name="firstTerm" select="substring($inputString, 1, $length - $afterFirstTermLength)"/>
179 <xsl:variable name="afterFirstTermTrimmed" select="text:trim($afterFirstTerm)"/>
180 <xsl:variable name="firstTermWithoutSurroundingQuotes" select="substring-before(substring-after($firstTerm, '&quot;'), '&quot;')"/>
181 <xsl:variable name="firstTermEscaped" select="text:escapeLucenePhraseForRegExpr($firstTermWithoutSurroundingQuotes)" />
182 <xsl:variable name="term" select="text:translateLuceneQueryTermToTerm($firstTermEscaped, $lastFetchedTerm)" />
183 <xsl:value-of select="concat($term, '|')" />
184 <!-- Recursive call of this function with the substring after the first term -->
185 <xsl:value-of select="text:translateLuceneQueryToTermsMain($afterFirstTermTrimmed, $term)"/>
186 </xsl:when>
187 <!-- + sign followd by phrase followed by something: phrase is appended -->
188 <xsl:when test="matches($inputString, '^###Plus###&quot;.*?&quot;\s')">
189 <xsl:variable name="afterFirstTerm" select="replace($inputString, '^###Plus###&quot;.*?&quot;\s', '')"/>
190 <xsl:variable name="length" select="string-length($inputString)"/>
191 <xsl:variable name="afterFirstTermLength" select="string-length($afterFirstTerm)"/>
192 <xsl:variable name="firstTerm" select="substring($inputString, 1, $length - $afterFirstTermLength)"/>
193 <xsl:variable name="afterFirstTermTrimmed" select="text:trim($afterFirstTerm)"/>
194 <xsl:variable name="firstTermWithoutSurroundingQuotes" select="substring-before(substring-after($firstTerm, '&quot;'), '&quot;')"/>
195 <xsl:variable name="firstTermEscaped" select="text:escapeLucenePhraseForRegExpr($firstTermWithoutSurroundingQuotes)" />
196 <xsl:variable name="term" select="text:translateLuceneQueryTermToTerm($firstTermEscaped, $lastFetchedTerm)" />
197 <xsl:value-of select="concat($term, '|')" />
198 <!-- Recursive call of this function with the substring after the first term -->
199 <xsl:value-of select="text:translateLuceneQueryToTermsMain($afterFirstTermTrimmed, $term)"/>
200 </xsl:when>
201 <!-- "-" followd by phrase followed by something: phrase is not appended -->
202 <xsl:when test="matches($inputString, '^-&quot;.*?&quot;\s')">
203 <xsl:variable name="afterFirstTerm" select="replace($inputString, '^-&quot;.*?&quot;\s', '')"/>
204 <xsl:variable name="afterFirstTermTrimmed" select="text:trim($afterFirstTerm)"/>
205 <!-- Recursive call of this function with the substring after the first term -->
206 <xsl:value-of select="text:translateLuceneQueryToTermsMain($afterFirstTermTrimmed, 'DUMMYDUMMYMINUS')"/>
207 </xsl:when>
208 <!-- single word: without quotes and spaces: word is appended -->
209 <xsl:when test="matches($inputString, '^[^&quot;\s]*$')">
210 <xsl:variable name="termEscaped" select="text:escapeLuceneTermForRegExpr($inputString)" />
211 <xsl:variable name="term" select="text:translateLuceneQueryTermToTerm($termEscaped, $lastFetchedTerm)"/>
212 <xsl:value-of select="$term" />
213 </xsl:when>
214 <!-- word followed by something: word is appended -->
215 <xsl:when test="matches($inputString, '^[^&quot;\s]*?\s')">
216 <xsl:variable name="afterFirstTerm" select="replace($inputString, '^[^&quot;\s]*?\s', '')"/>
217 <xsl:variable name="length" select="string-length($inputString)"/>
218 <xsl:variable name="afterFirstTermLength" select="string-length($afterFirstTerm)"/>
219 <xsl:variable name="firstTerm" select="substring($inputString, 1, $length - $afterFirstTermLength)"/>
220 <xsl:variable name="firstTermTrimmed" select="text:trim($firstTerm)"/>
221 <xsl:variable name="afterFirstTermTrimmed" select="text:trim($afterFirstTerm)"/>
222 <!-- treat single Lucene term: special Lucene characters in query term ("*", "+", ".", "-") -->
223 <xsl:variable name="termEscaped" select="text:escapeLuceneTermForRegExpr($firstTermTrimmed)" />
224 <xsl:variable name="term" select="text:translateLuceneQueryTermToTerm($termEscaped, $lastFetchedTerm)" />
225 <xsl:value-of select="concat($term, '|')" />
226 <!-- Recursive call of this function with the substring after the first term -->
227 <xsl:value-of select="text:translateLuceneQueryToTermsMain($afterFirstTermTrimmed, $term)"/>
228 </xsl:when>
229 <xsl:otherwise>
230 <xsl:value-of select="''"/>
231 </xsl:otherwise>
232 </xsl:choose>
233 </xsl:function>
234
235 <xsl:function name="text:escapeLuceneTermForRegExpr">
236 <xsl:param name="inputString" as="xs:string" />
237 <!-- replace special Lucene characters: "*", "+", "~" were escaped for regular expression -->
238 <xsl:variable name="termWithoutLuceneSymbols1" select="replace($inputString, '###Star###', '')" />
239 <xsl:variable name="termWithoutLuceneSymbols2" select="replace($termWithoutLuceneSymbols1, '###Plus###', '')" />
240 <xsl:variable name="termWithoutLuceneSymbols3" select="replace($termWithoutLuceneSymbols2, '###Tilde###', '')" />
241 <!-- Lucene mask symbol "?" is replaced with regular expression symbol "." -->
242 <xsl:variable name="term" select="replace($termWithoutLuceneSymbols3, '###QM###', '.')" />
243 <xsl:value-of select="$term" />
244 </xsl:function>
245
246 <xsl:function name="text:escapeLucenePhraseForRegExpr">
247 <xsl:param name="inputString" as="xs:string" />
248 <!-- replace special Lucene characters: "*" and "+" were escaped for regular expression -->
249 <xsl:variable name="termWithoutLuceneSymbols1" select="replace($inputString, '###Star###', '\\*')" />
250 <xsl:variable name="termWithoutLuceneSymbols2" select="replace($termWithoutLuceneSymbols1, '###Plus###', '')" />
251 <!-- Lucene mask symbol "?" is replaced with regular expression symbol "." -->
252 <xsl:variable name="term" select="replace($termWithoutLuceneSymbols2, '###QM###', '\\?')" />
253 <xsl:value-of select="$term" />
254 </xsl:function>
255
256 <!-- last special char replacements and logical operator handling -->
257 <xsl:function name="text:translateLuceneQueryTermToTerm">
258 <xsl:param name="inputString" as="xs:string" />
259 <!-- last term in previous step: used for Lucene operator NOT) -->
260 <xsl:param name="lastFetchedTerm" as="xs:string" />
261 <xsl:variable name="termEscaped1" select="replace($inputString, '###Dot###', '\\.')" />
262 <xsl:variable name="termEscaped2" select="replace($termEscaped1, '###BeginLine###', '\\^')" />
263 <xsl:variable name="termEscaped3" select="replace($termEscaped2, '###EndLine###', '\\DollarSign')" /> <!-- TODO -->
264 <xsl:variable name="termEscaped4" select="replace($termEscaped3, '###Or###', '\\|')" />
265 <xsl:variable name="termEscaped5" select="replace($termEscaped4, '###Paranthes1Open###', '\\(')" />
266 <xsl:variable name="termEscaped6" select="replace($termEscaped5, '###Paranthes1Close###', '\\)')" />
267 <xsl:variable name="termEscaped7" select="replace($termEscaped6, '###Paranthes2Open###', '\\{')" />
268 <xsl:variable name="termEscaped8" select="replace($termEscaped7, '###Paranthes1Close###', '\\}')" />
269 <xsl:variable name="termEscaped9" select="replace($termEscaped8, '###Paranthes3Open###', '\\[')" />
270 <xsl:variable name="term" select="replace($termEscaped9, '###Paranthes3Close###', '\\]')" />
271 <xsl:choose>
272 <xsl:when test="($term != 'AND') and ($term != 'OR') and ($term != 'NOT') and (substring($term, 1, 1) != '-') and (($lastFetchedTerm = 'DUMMYDUMMYSTART') or ($lastFetchedTerm != 'DUMMYDUMMYNOT'))">
273 <xsl:value-of select="$term" />
274 </xsl:when>
275 <xsl:otherwise>
276 <xsl:value-of select="concat('DUMMYDUMMY', $term)"/>
277 </xsl:otherwise>
278 </xsl:choose>
279 </xsl:function>
280
281 <!-- Highlight all term occurrences. Result is a sequence of text and highlighted nodes (with span).
282 Example: LE<span ...>MECHANICHE</span>...<span ...>Mechaniche</span>... -->
283 <xsl:function name="text:highlight">
284 <xsl:param name="inputStr" as="xs:string" />
285 <xsl:param name="terms" as="xs:string" />
286 <xsl:param name="words" as="xs:string" />
287 <xsl:param name="clipped" as="xs:string" />
288 <xsl:variable name="hitBeginStr" select="'XXhitStartXX'"/>
289 <xsl:variable name="hitEndStr" select="'XXhitEndXX'"/>
290 <xsl:variable name="inputStringTemp" select="replace($inputStr, '\n', '')"/>
291 <!-- replace all term or word occurences with surrounding begin and end marks (string operation) -->
292 <xsl:choose>
293 <xsl:when test="$terms != '' and $words != ''">
294 <xsl:variable name="inputStringWithMarksForTerms" select="replace($inputStringTemp, concat('(', $terms, ')'), concat($hitBeginStr, '$1', $hitEndStr), 'im')"/>
295 <xsl:variable name="inputStringWithMarksForWords" select="replace($inputStringWithMarksForTerms, concat('([\s:.,;!_]+|^)', '(', $words, ')', '([\s:.,;!_]+|$)'), concat('$1', $hitBeginStr, '$2', $hitEndStr, '$3'), 'im')"/>
296 <xsl:sequence select="text:highlightTerms($inputStringWithMarksForWords, $clipped, $hitBeginStr, $hitEndStr)" />
297 </xsl:when>
298 <xsl:when test="$terms != '' and $words = ''">
299 <xsl:variable name="inputStringWithMarksForTerms" select="replace($inputStringTemp, concat('(', $terms, ')'), concat($hitBeginStr, '$1', $hitEndStr), 'im')"/>
300 <xsl:sequence select="text:highlightTerms($inputStringWithMarksForTerms, $clipped, $hitBeginStr, $hitEndStr)" />
301 </xsl:when>
302 <xsl:when test="$terms = '' and $words != ''">
303 <xsl:variable name="inputStringWithMarksForWords" select="replace($inputStringTemp, concat('([\s:.,;!_]+|^)', '(', $words, ')', '([\s:.,;!_]+)'), concat('$1', $hitBeginStr, '$2', $hitEndStr, '$3'), 'im')"/>
304 <xsl:sequence select="text:highlightTerms($inputStringWithMarksForWords, $clipped, $hitBeginStr, $hitEndStr)" />
305 </xsl:when>
306 <xsl:otherwise>
307 <xsl:sequence select="$inputStr"/>
308 </xsl:otherwise>
309 </xsl:choose>
310 </xsl:function>
311
312 <!-- Convert an input string with hits (marked with begin and end marks) to a sequence of text nodes with highlight span nodes -->
313 <xsl:function name="text:highlightTerms">
314 <xsl:param name="inputString" as="xs:string" />
315 <xsl:param name="clipped" as="xs:string" />
316 <xsl:param name="hitBeginStr" />
317 <xsl:param name="hitEndStr" />
318 <xsl:variable name="substringBefore" select="substring-before($inputString, $hitEndStr)"/>
319 <xsl:variable name="substringAfter" select="substring-after($inputString, $hitEndStr)"/>
320 <xsl:variable name="beforeHitBeginString" select="substring-before($substringBefore, $hitBeginStr)"/>
321 <xsl:variable name="hitTerm" select="substring-after($substringBefore, $hitBeginStr)"/>
322 <xsl:choose>
323 <xsl:when test="contains($inputString, $hitEndStr)">
324 <!-- Prints the original part of the substring up to the first occurrence of a hit -->
325 <xsl:choose>
326 <xsl:when test="$clipped='true'">
327 <xsl:value-of select="text:cutStringBefore($beforeHitBeginString, 70)"/>
328 </xsl:when>
329 <xsl:otherwise>
330 <xsl:value-of select="$beforeHitBeginString"/>
331 </xsl:otherwise>
332 </xsl:choose>
333 <!-- Highlight the hit -->
334 <span class="hit highlight">
335 <xsl:value-of select="$hitTerm"/>
336 </span>
337 <!-- Recursive call of this function with the substring after the first occurrence of the hit: further occurrences of hits -->
338 <xsl:sequence select="text:highlightTerms($substringAfter, $clipped, $hitBeginStr, $hitEndStr)"/>
339 </xsl:when>
340 <!-- if no occurrence of a hit could be found the whole string is printed -->
341 <xsl:otherwise>
342 <xsl:choose>
343 <xsl:when test="$clipped='true'">
344 <xsl:value-of select="text:cutStringAfter($inputString, 70)"/>
345 </xsl:when>
346 <xsl:otherwise>
347 <xsl:value-of select="$inputString"/>
348 </xsl:otherwise>
349 </xsl:choose>
350 </xsl:otherwise>
351 </xsl:choose>
352 </xsl:function>
353
354 </xsl:stylesheet>