1 <?xml version=
"1.0" encoding=
"utf-8"?>
2 <!-- ********************************************************************
3 $Id: lib.xsl,v 1.1 2007/03/10 05:15:34 scott Exp $
4 ********************************************************************
6 This file is part of the XSL DocBook Stylesheet distribution.
7 See ../README or http://nwalsh.com/docbook/xsl/ for copyright
10 This module implements DTD-independent functions
12 ******************************************************************** -->
14 <xsl:stylesheet xmlns:
xsl=
"http://www.w3.org/1999/XSL/Transform" xmlns:
src=
"http://nwalsh.com/xmlns/litprog/fragment" xmlns:
dyn=
"http://exslt.org/dynamic" xmlns:
saxon=
"http://icl.com/saxon" exclude-result-prefixes=
"src" version=
"1.0">
16 <xsl:template name=
"dot.count">
17 <!-- Returns the number of "." characters in a string -->
18 <xsl:param name=
"string"/>
19 <xsl:param name=
"count" select=
"0"/>
21 <xsl:when test=
"contains($string, '.')">
22 <xsl:call-template name=
"dot.count">
23 <xsl:with-param name=
"string" select=
"substring-after($string, '.')"/>
24 <xsl:with-param name=
"count" select=
"$count+1"/>
28 <xsl:value-of select=
"$count"/>
32 <xsl:template name=
"copy-string">
33 <!-- returns 'count' copies of 'string' -->
34 <xsl:param name=
"string"/>
35 <xsl:param name=
"count" select=
"0"/>
36 <xsl:param name=
"result"/>
39 <xsl:when test=
"$count>0">
40 <xsl:call-template name=
"copy-string">
41 <xsl:with-param name=
"string" select=
"$string"/>
42 <xsl:with-param name=
"count" select=
"$count - 1"/>
43 <xsl:with-param name=
"result">
44 <xsl:value-of select=
"$result"/>
45 <xsl:value-of select=
"$string"/>
50 <xsl:value-of select=
"$result"/>
54 <xsl:template name=
"string.subst">
55 <xsl:param name=
"string"/>
56 <xsl:param name=
"target"/>
57 <xsl:param name=
"replacement"/>
60 <xsl:when test=
"contains($string, $target)">
61 <xsl:variable name=
"rest">
62 <xsl:call-template name=
"string.subst">
63 <xsl:with-param name=
"string" select=
"substring-after($string, $target)"/>
64 <xsl:with-param name=
"target" select=
"$target"/>
65 <xsl:with-param name=
"replacement" select=
"$replacement"/>
68 <xsl:value-of select=
"concat(substring-before($string, $target), $replacement, $rest)"/>
71 <xsl:value-of select=
"$string"/>
75 <xsl:template name=
"xpointer.idref">
76 <xsl:param name=
"xpointer">http://...
</xsl:param>
78 <xsl:when test=
"starts-with($xpointer, '#xpointer(id(')">
79 <xsl:variable name=
"rest" select=
"substring-after($xpointer, '#xpointer(id(')"/>
80 <xsl:variable name=
"quote" select=
"substring($rest, 1, 1)"/>
81 <xsl:value-of select=
"substring-before(substring-after($xpointer, $quote), $quote)"/>
83 <xsl:when test=
"starts-with($xpointer, '#')">
84 <xsl:value-of select=
"substring-after($xpointer, '#')"/>
86 <!-- otherwise it's a pointer to some other document -->
89 <xsl:template name=
"length-magnitude">
90 <xsl:param name=
"length" select=
"'0pt'"/>
93 <xsl:when test=
"string-length($length) = 0"/>
94 <xsl:when test=
"substring($length,1,1) = '0' or substring($length,1,1) = '1' or substring($length,1,1) = '2' or substring($length,1,1) = '3' or substring($length,1,1) = '4' or substring($length,1,1) = '5' or substring($length,1,1) = '6' or substring($length,1,1) = '7' or substring($length,1,1) = '8' or substring($length,1,1) = '9' or substring($length,1,1) = '.'">
95 <xsl:value-of select=
"substring($length,1,1)"/>
96 <xsl:call-template name=
"length-magnitude">
97 <xsl:with-param name=
"length" select=
"substring($length,2)"/>
102 <xsl:template name=
"length-units">
103 <xsl:param name=
"length" select=
"'0pt'"/>
104 <xsl:param name=
"default.units" select=
"'px'"/>
105 <xsl:variable name=
"magnitude">
106 <xsl:call-template name=
"length-magnitude">
107 <xsl:with-param name=
"length" select=
"$length"/>
111 <xsl:variable name=
"units">
112 <xsl:value-of select=
"substring($length, string-length($magnitude)+1)"/>
116 <xsl:when test=
"$units = ''">
117 <xsl:value-of select=
"$default.units"/>
120 <xsl:value-of select=
"$units"/>
124 <xsl:template name=
"length-spec">
125 <xsl:param name=
"length" select=
"'0pt'"/>
126 <xsl:param name=
"default.units" select=
"'px'"/>
128 <xsl:variable name=
"magnitude">
129 <xsl:call-template name=
"length-magnitude">
130 <xsl:with-param name=
"length" select=
"$length"/>
134 <xsl:variable name=
"units">
135 <xsl:value-of select=
"substring($length, string-length($magnitude)+1)"/>
138 <xsl:value-of select=
"$magnitude"/>
140 <xsl:when test=
"$units='cm' or $units='mm' or $units='in' or $units='pt' or $units='pc' or $units='px' or $units='em'">
141 <xsl:value-of select=
"$units"/>
143 <xsl:when test=
"$units = ''">
144 <xsl:value-of select=
"$default.units"/>
148 <xsl:text>Unrecognized unit of measure:
</xsl:text>
149 <xsl:value-of select=
"$units"/>
150 <xsl:text>.
</xsl:text>
155 <xsl:template name=
"length-in-points">
156 <xsl:param name=
"length" select=
"'0pt'"/>
157 <xsl:param name=
"em.size" select=
"10"/>
158 <xsl:param name=
"pixels.per.inch" select=
"90"/>
160 <xsl:variable name=
"magnitude">
161 <xsl:call-template name=
"length-magnitude">
162 <xsl:with-param name=
"length" select=
"$length"/>
166 <xsl:variable name=
"units">
167 <xsl:value-of select=
"substring($length, string-length($magnitude)+1)"/>
171 <xsl:when test=
"$units = 'pt'">
172 <xsl:value-of select=
"$magnitude"/>
174 <xsl:when test=
"$units = 'cm'">
175 <xsl:value-of select=
"$magnitude div 2.54 * 72.0"/>
177 <xsl:when test=
"$units = 'mm'">
178 <xsl:value-of select=
"$magnitude div 25.4 * 72.0"/>
180 <xsl:when test=
"$units = 'in'">
181 <xsl:value-of select=
"$magnitude * 72.0"/>
183 <xsl:when test=
"$units = 'pc'">
184 <xsl:value-of select=
"$magnitude * 12.0"/>
186 <xsl:when test=
"$units = 'px'">
187 <xsl:value-of select=
"$magnitude div $pixels.per.inch * 72.0"/>
189 <xsl:when test=
"$units = 'em'">
190 <xsl:value-of select=
"$magnitude * $em.size"/>
194 <xsl:text>Unrecognized unit of measure:
</xsl:text>
195 <xsl:value-of select=
"$units"/>
196 <xsl:text>.
</xsl:text>
201 <xsl:template name=
"pi-attribute">
202 <xsl:param name=
"pis" select=
"processing-instruction('BOGUS_PI')"/>
203 <xsl:param name=
"attribute">filename
</xsl:param>
204 <xsl:param name=
"count">1</xsl:param>
207 <xsl:when test=
"$count>count($pis)">
211 <xsl:variable name=
"pi">
212 <xsl:value-of select=
"$pis[$count]"/>
214 <xsl:variable name=
"pivalue">
215 <xsl:value-of select=
"concat(' ', normalize-space($pi))"/>
218 <xsl:when test=
"contains($pivalue,concat(' ', $attribute, '='))">
219 <xsl:variable name=
"rest" select=
"substring-after($pivalue,concat(' ', $attribute,'='))"/>
220 <xsl:variable name=
"quote" select=
"substring($rest,1,1)"/>
221 <xsl:value-of select=
"substring-before(substring($rest,2),$quote)"/>
224 <xsl:call-template name=
"pi-attribute">
225 <xsl:with-param name=
"pis" select=
"$pis"/>
226 <xsl:with-param name=
"attribute" select=
"$attribute"/>
227 <xsl:with-param name=
"count" select=
"$count + 1"/>
234 <xsl:template name=
"lookup.key">
235 <xsl:param name=
"key" select=
"''"/>
236 <xsl:param name=
"table" select=
"''"/>
238 <xsl:if test=
"contains($table, ' ')">
240 <xsl:when test=
"substring-before($table, ' ') = $key">
241 <xsl:variable name=
"rest" select=
"substring-after($table, ' ')"/>
243 <xsl:when test=
"contains($rest, ' ')">
244 <xsl:value-of select=
"substring-before($rest, ' ')"/>
247 <xsl:value-of select=
"$rest"/>
252 <xsl:call-template name=
"lookup.key">
253 <xsl:with-param name=
"key" select=
"$key"/>
254 <xsl:with-param name=
"table" select=
"substring-after(substring-after($table,' '), ' ')"/>
260 <xsl:template name=
"xpath.location">
261 <xsl:param name=
"node" select=
"."/>
262 <xsl:param name=
"path" select=
"''"/>
264 <xsl:variable name=
"next.path">
265 <xsl:value-of select=
"local-name($node)"/>
266 <xsl:if test=
"$path != ''">/
</xsl:if>
267 <xsl:value-of select=
"$path"/>
271 <xsl:when test=
"$node/parent::*">
272 <xsl:call-template name=
"xpath.location">
273 <xsl:with-param name=
"node" select=
"$node/parent::*"/>
274 <xsl:with-param name=
"path" select=
"$next.path"/>
278 <xsl:text>/
</xsl:text>
279 <xsl:value-of select=
"$next.path"/>
283 <xsl:template name=
"comment-escape-string">
284 <xsl:param name=
"string" select=
"''"/>
286 <xsl:if test=
"starts-with($string, '-')">
287 <xsl:text> </xsl:text>
290 <xsl:call-template name=
"comment-escape-string.recursive">
291 <xsl:with-param name=
"string" select=
"$string"/>
294 <xsl:if test=
"substring($string, string-length($string), 1) = '-'">
295 <xsl:text> </xsl:text>
298 <xsl:template name=
"comment-escape-string.recursive">
299 <xsl:param name=
"string" select=
"''"/>
301 <xsl:when test=
"contains($string, '--')">
302 <xsl:value-of select=
"substring-before($string, '--')"/>
303 <xsl:value-of select=
"'- -'"/>
304 <xsl:call-template name=
"comment-escape-string.recursive">
305 <xsl:with-param name=
"string" select=
"substring-after($string, '--')"/>
309 <xsl:value-of select=
"$string"/>
313 <xsl:template name=
"prepend-pad">
314 <!-- recursive template to right justify and prepend-->
315 <!-- the value with whatever padChar is passed in -->
316 <xsl:param name=
"padChar" select=
"' '"/>
317 <xsl:param name=
"padVar"/>
318 <xsl:param name=
"length"/>
320 <xsl:when test=
"string-length($padVar) < $length">
321 <xsl:call-template name=
"prepend-pad">
322 <xsl:with-param name=
"padChar" select=
"$padChar"/>
323 <xsl:with-param name=
"padVar" select=
"concat($padChar,$padVar)"/>
324 <xsl:with-param name=
"length" select=
"$length"/>
328 <xsl:value-of select=
"substring($padVar,string-length($padVar) - $length + 1)"/>
333 <xsl:template name=
"str.tokenize.keep.delimiters">
334 <xsl:param name=
"string" select=
"''"/>
335 <xsl:param name=
"delimiters" select=
"' '"/>
337 <xsl:when test=
"not($string)"/>
338 <xsl:when test=
"not($delimiters)">
339 <xsl:call-template name=
"str.tokenize.keep.delimiters-characters">
340 <xsl:with-param name=
"string" select=
"$string"/>
344 <xsl:call-template name=
"str.tokenize.keep.delimiters-delimiters">
345 <xsl:with-param name=
"string" select=
"$string"/>
346 <xsl:with-param name=
"delimiters" select=
"$delimiters"/>
352 <xsl:template name=
"str.tokenize.keep.delimiters-characters">
353 <xsl:param name=
"string"/>
354 <xsl:if test=
"$string">
355 <token><xsl:value-of select=
"substring($string, 1, 1)"/></token>
356 <xsl:call-template name=
"str.tokenize.keep.delimiters-characters">
357 <xsl:with-param name=
"string" select=
"substring($string, 2)"/>
362 <xsl:template name=
"str.tokenize.keep.delimiters-delimiters">
363 <xsl:param name=
"string"/>
364 <xsl:param name=
"delimiters"/>
365 <xsl:variable name=
"delimiter" select=
"substring($delimiters, 1, 1)"/>
367 <xsl:when test=
"not($delimiter)">
368 <token><xsl:value-of select=
"$string"/></token>
370 <xsl:when test=
"contains($string, $delimiter)">
371 <xsl:if test=
"not(starts-with($string, $delimiter))">
372 <xsl:call-template name=
"str.tokenize.keep.delimiters-delimiters">
373 <xsl:with-param name=
"string" select=
"substring-before($string, $delimiter)"/>
374 <xsl:with-param name=
"delimiters" select=
"substring($delimiters, 2)"/>
377 <!-- output each delimiter -->
378 <xsl:value-of select=
"$delimiter"/>
379 <xsl:call-template name=
"str.tokenize.keep.delimiters-delimiters">
380 <xsl:with-param name=
"string" select=
"substring-after($string, $delimiter)"/>
381 <xsl:with-param name=
"delimiters" select=
"$delimiters"/>
385 <xsl:call-template name=
"str.tokenize.keep.delimiters-delimiters">
386 <xsl:with-param name=
"string" select=
"$string"/>
387 <xsl:with-param name=
"delimiters" select=
"substring($delimiters, 2)"/>
392 <xsl:template name=
"apply-string-subst-map">
393 <xsl:param name=
"content"/>
394 <xsl:param name=
"map.contents"/>
395 <xsl:variable name=
"replaced_text">
396 <xsl:call-template name=
"string.subst">
397 <xsl:with-param name=
"string" select=
"$content"/>
398 <xsl:with-param name=
"target" select=
"$map.contents[1]/@oldstring"/>
399 <xsl:with-param name=
"replacement" select=
"$map.contents[1]/@newstring"/>
403 <xsl:when test=
"$map.contents[2]">
404 <xsl:call-template name=
"apply-string-subst-map">
405 <xsl:with-param name=
"content" select=
"$replaced_text"/>
406 <xsl:with-param name=
"map.contents" select=
"$map.contents[position() > 1]"/>
410 <xsl:value-of select=
"$replaced_text"/>
416 <xsl:template name=
"apply-character-map">
417 <xsl:param name=
"content"/>
418 <xsl:param name=
"map.contents"/>
419 <xsl:variable name=
"replaced_text">
420 <xsl:call-template name=
"string.subst">
421 <xsl:with-param name=
"string" select=
"$content"/>
422 <xsl:with-param name=
"target" select=
"$map.contents[1]/@character"/>
423 <xsl:with-param name=
"replacement" select=
"$map.contents[1]/@string"/>
427 <xsl:when test=
"$map.contents[2]">
428 <xsl:call-template name=
"apply-character-map">
429 <xsl:with-param name=
"content" select=
"$replaced_text"/>
430 <xsl:with-param name=
"map.contents" select=
"$map.contents[position() > 1]"/>
434 <xsl:value-of select=
"$replaced_text"/>
440 <xsl:template name=
"read-character-map">
441 <xsl:param name=
"use.subset"/>
442 <xsl:param name=
"subset.profile"/>
443 <xsl:param name=
"uri"/>
445 <xsl:when test=
"$use.subset != 0">
446 <!-- use a subset of the character map instead of the full map -->
448 <!-- xsltproc and Xalan both support dyn:evaluate() -->
449 <xsl:when test=
"function-available('dyn:evaluate')">
450 <xsl:copy-of select=
"document($uri)//*[local-name()='output-character'] [dyn:evaluate($subset.profile)]"/>
452 <!-- Saxon has its own evaluate() & doesn't support dyn:evaluate() -->
453 <xsl:when test=
"function-available('saxon:evaluate')">
454 <xsl:copy-of select=
"document($uri)//*[local-name()='output-character'] [saxon:evaluate($subset.profile)]"/>
457 <xsl:message terminate=
"yes">
458 Error: To process character-map subsets, you must use an XSLT engine
459 that supports the evaluate() XSLT extension function. Your XSLT engine
466 <!-- value of $use.subset is non-zero, so use the full map -->
467 <xsl:copy-of select=
"document($uri)//*[local-name()='output-character']"/>
471 <xsl:template name=
"count.uri.path.depth">
472 <xsl:param name=
"filename" select=
"''"/>
473 <xsl:param name=
"count" select=
"0"/>
476 <xsl:when test=
"contains($filename, '/')">
477 <xsl:call-template name=
"count.uri.path.depth">
478 <xsl:with-param name=
"filename" select=
"substring-after($filename, '/')"/>
479 <xsl:with-param name=
"count" select=
"$count + 1"/>
483 <xsl:value-of select=
"$count"/>
487 <xsl:template name=
"trim.common.uri.paths">
488 <xsl:param name=
"uriA" select=
"''"/>
489 <xsl:param name=
"uriB" select=
"''"/>
490 <xsl:param name=
"return" select=
"'A'"/>
493 <xsl:when test=
"contains($uriA, '/') and contains($uriB, '/') and substring-before($uriA, '/') = substring-before($uriB, '/')">
494 <xsl:call-template name=
"trim.common.uri.paths">
495 <xsl:with-param name=
"uriA" select=
"substring-after($uriA, '/')"/>
496 <xsl:with-param name=
"uriB" select=
"substring-after($uriB, '/')"/>
497 <xsl:with-param name=
"return" select=
"$return"/>
502 <xsl:when test=
"$return = 'A'">
503 <xsl:value-of select=
"$uriA"/>
506 <xsl:value-of select=
"$uriB"/>
513 <xsl:template name=
"trim.text">
514 <xsl:param name=
"contents" select=
"."/>
515 <xsl:variable name=
"contents-left-trimmed">
516 <xsl:call-template name=
"trim-left">
517 <xsl:with-param name=
"contents" select=
"$contents"/>
520 <xsl:variable name=
"contents-trimmed">
521 <xsl:call-template name=
"trim-right">
522 <xsl:with-param name=
"contents" select=
"$contents-left-trimmed"/>
525 <xsl:value-of select=
"$contents-trimmed"/>
528 <xsl:template name=
"trim-left">
529 <xsl:param name=
"contents"/>
531 <xsl:when test=
"starts-with($contents,'
') or starts-with($contents,'
') or starts-with($contents,' ') or starts-with($contents,'	')">
532 <xsl:call-template name=
"trim-left">
533 <xsl:with-param name=
"contents" select=
"substring($contents, 2)"/>
537 <xsl:value-of select=
"$contents"/>
542 <xsl:template name=
"trim-right">
543 <xsl:param name=
"contents"/>
544 <xsl:variable name=
"last-char">
545 <xsl:value-of select=
"substring($contents, string-length($contents), 1)"/>
548 <xsl:when test=
"($last-char = '
') or ($last-char = '
') or ($last-char = ' ') or ($last-char = '	')">
549 <xsl:call-template name=
"trim-right">
550 <xsl:with-param name=
"contents" select=
"substring($contents, 1, string-length($contents) - 1)"/>
554 <xsl:value-of select=
"$contents"/>