root/docs/docbook-xsl/lib/lib.xweb

Revision 23dea7e00df87480acb58bb3398283c2bb227949, 40.0 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 3 years ago)

pull docs into master

  • Property mode set to 100644
Line 
1 <?xml version="1.0" encoding="utf-8"?>
2 <book xmlns:src="http://nwalsh.com/xmlns/litprog/fragment"
3       xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
4       xmlns:dyn="http://exslt.org/dynamic"
5       xmlns:saxon="http://icl.com/saxon">
6 <bookinfo>
7 <title>XSL Library Template Reference</title>
8 <releaseinfo role="cvs">$Id: lib.xweb,v 1.13 2005/07/08 10:35:55 xmldoc Exp $
9 </releaseinfo>
10 <corpauthor>DocBook Open Repository Team</corpauthor>
11 <copyright>
12   <year>1999</year>
13   <year>2000</year>
14   <year>2001</year>
15   <year>2002</year>
16   <year>2005</year>
17   <holder>Norman Walsh</holder>
18 </copyright>
19 </bookinfo>
20
21 <preface><title>Introduction</title>
22
23 <para>This is technical reference documentation for the DocBook XSL
24 Stylesheets; it documents (some of) the parameters, templates, and
25 other elements of the stylesheets.</para>
26
27 <para>This is not intended to be <quote>user</quote> documentation.
28 It is provided for developers writing customization layers for the
29 stylesheets, and for anyone who's interested in <quote>how it
30 works</quote>.</para>
31
32 <para>Although I am trying to be thorough, this documentation is known
33 to be incomplete. Don't forget to read the source, too :-)</para>
34
35 </preface>
36
37 <reference>
38 <title>General Library Templates</title>
39
40 <refentry id="dot.count">
41 <refnamediv>
42 <refname>dot.count</refname>
43 <refpurpose>Returns the number of <quote>.</quote> characters in a string</refpurpose>
44 </refnamediv>
45
46 <refsect1><title>Description</title>
47
48 <programlisting><src:fragment id='dot.count.frag'>
49 <xsl:template name="dot.count">
50   <!-- Returns the number of "." characters in a string -->
51   <xsl:param name="string"></xsl:param>
52   <xsl:param name="count" select="0"/>
53   <xsl:choose>
54     <xsl:when test="contains($string, '.')">
55       <xsl:call-template name="dot.count">
56         <xsl:with-param name="string" select="substring-after($string, '.')"/>
57         <xsl:with-param name="count" select="$count+1"/>
58       </xsl:call-template>
59     </xsl:when>
60     <xsl:otherwise>
61       <xsl:value-of select="$count"/>
62     </xsl:otherwise>
63   </xsl:choose>
64 </xsl:template>
65 </src:fragment></programlisting>
66
67 </refsect1>
68 </refentry>
69
70 <!-- ================================================================== -->
71
72 <refentry id="copy-string">
73 <refnamediv>
74 <refname>copy-string</refname>
75 <refpurpose>Returns <quote>count</quote> copies of a string</refpurpose>
76 </refnamediv>
77
78 <refsect1><title>Description</title>
79
80 <programlisting><src:fragment id='copy-string.frag'>
81 <xsl:template name="copy-string">
82   <!-- returns 'count' copies of 'string' -->
83   <xsl:param name="string"></xsl:param>
84   <xsl:param name="count" select="0"/>
85   <xsl:param name="result"></xsl:param>
86
87   <xsl:choose>
88     <xsl:when test="$count>0">
89       <xsl:call-template name="copy-string">
90         <xsl:with-param name="string" select="$string"/>
91         <xsl:with-param name="count" select="$count - 1"/>
92         <xsl:with-param name="result">
93           <xsl:value-of select="$result"/>
94           <xsl:value-of select="$string"/>
95         </xsl:with-param>
96       </xsl:call-template>
97     </xsl:when>
98     <xsl:otherwise>
99       <xsl:value-of select="$result"/>
100     </xsl:otherwise>
101   </xsl:choose>
102 </xsl:template>
103 </src:fragment></programlisting>
104
105 </refsect1>
106 </refentry>
107
108 <!-- ====================================================================== -->
109
110 <refentry id="string.subst">
111 <refnamediv>
112 <refname>string.subst</refname>
113 <refpurpose>Substitute one text string for another in a string</refpurpose>
114 </refnamediv>
115
116 <refsect1><title>Description</title>
117
118 <para>The <function>string.subst</function> template replaces all
119 occurances of <parameter>target</parameter> in <parameter>string</parameter>
120 with <parameter>replacement</parameter> and returns the result.
121 </para>
122
123 <programlisting><src:fragment id='string.subst.frag'>
124 <xsl:template name="string.subst">
125   <xsl:param name="string"></xsl:param>
126   <xsl:param name="target"></xsl:param>
127   <xsl:param name="replacement"></xsl:param>
128
129   <xsl:choose>
130     <xsl:when test="contains($string, $target)">
131       <xsl:variable name="rest">
132         <xsl:call-template name="string.subst">
133           <xsl:with-param name="string"
134                           select="substring-after($string, $target)"/>
135           <xsl:with-param name="target" select="$target"/>
136           <xsl:with-param name="replacement" select="$replacement"/>
137         </xsl:call-template>
138       </xsl:variable>
139       <xsl:value-of select="concat(substring-before($string, $target),
140                                    $replacement,
141                                    $rest)"/>
142     </xsl:when>
143     <xsl:otherwise>
144       <xsl:value-of select="$string"/>
145     </xsl:otherwise>
146   </xsl:choose>
147 </xsl:template>
148 </src:fragment></programlisting>
149
150 </refsect1>
151 </refentry>
152
153 <!-- ================================================================== -->
154
155 <refentry id="xpointer.idref">
156 <refnamediv>
157 <refname>xpointer.idref</refname>
158 <refpurpose>Extract IDREF from an XPointer</refpurpose>
159 </refnamediv>
160
161 <refsect1><title>Description</title>
162
163 <para>The <function>xpointer.idref</function> template returns the
164 ID portion of an XPointer which is a pointer to an ID within the current
165 document, or the empty string if it is not.</para>
166 <para>In other words, <function>xpointer.idref</function> returns
167 <quote>foo</quote> when passed either <literal>#foo</literal>
168 or <literal>#xpointer(id('foo'))</literal>, otherwise it returns
169 the empty string.</para>
170
171 <programlisting><src:fragment id='xpointer.idref.frag'>
172 <xsl:template name="xpointer.idref">
173   <xsl:param name="xpointer">http://...</xsl:param>
174   <xsl:choose>
175     <xsl:when test="starts-with($xpointer, '#xpointer(id(')">
176       <xsl:variable name="rest" select="substring-after($xpointer, '#xpointer(id(')"/>
177       <xsl:variable name="quote" select="substring($rest, 1, 1)"/>
178       <xsl:value-of select="substring-before(substring-after($xpointer, $quote), $quote)"/>
179     </xsl:when>
180     <xsl:when test="starts-with($xpointer, '#')">
181       <xsl:value-of select="substring-after($xpointer, '#')"/>
182     </xsl:when>
183     <!-- otherwise it's a pointer to some other document -->
184   </xsl:choose>
185 </xsl:template>
186 </src:fragment></programlisting>
187
188 </refsect1>
189 </refentry>
190
191
192 <!-- ================================================================== -->
193
194 <refentry id="length-magnitude">
195 <refnamediv>
196 <refname>length-magnitude</refname>
197 <refpurpose>Return the unqualified dimension from a length specification</refpurpose>
198 </refnamediv>
199
200 <refsect1><title>Description</title>
201
202 <para>The <function>length-magnitude</function> template returns the
203 unqualified length ("20" for "20pt") from a dimension.
204 </para>
205
206 <programlisting><src:fragment id='length-magnitude.frag'>
207 <xsl:template name="length-magnitude">
208   <xsl:param name="length" select="'0pt'"/>
209
210   <xsl:choose>
211     <xsl:when test="string-length($length) = 0"/>
212     <xsl:when test="substring($length,1,1) = '0'
213                     or substring($length,1,1) = '1'
214                     or substring($length,1,1) = '2'
215                     or substring($length,1,1) = '3'
216                     or substring($length,1,1) = '4'
217                     or substring($length,1,1) = '5'
218                     or substring($length,1,1) = '6'
219                     or substring($length,1,1) = '7'
220                     or substring($length,1,1) = '8'
221                     or substring($length,1,1) = '9'
222                     or substring($length,1,1) = '.'">
223       <xsl:value-of select="substring($length,1,1)"/>
224       <xsl:call-template name="length-magnitude">
225         <xsl:with-param name="length" select="substring($length,2)"/>
226       </xsl:call-template>
227     </xsl:when>
228   </xsl:choose>
229 </xsl:template>
230 </src:fragment></programlisting>
231
232 </refsect1>
233 </refentry>
234
235 <!-- ================================================================== -->
236
237 <refentry id="length-units">
238 <refnamediv>
239 <refname>length-units</refname>
240 <refpurpose>Return the units from a length specification</refpurpose>
241 </refnamediv>
242
243 <refsect1><title>Description</title>
244
245 <para>The <function>length-units</function> template returns the
246 units ("pt" for "20pt") from a length. If no units are supplied on the
247 length, the <parameter>defauilt.units</parameter> are returned.</para>
248
249 <programlisting><src:fragment id='length-units.frag'>
250 <xsl:template name="length-units">
251   <xsl:param name="length" select="'0pt'"/>
252   <xsl:param name="default.units" select="'px'"/>
253   <xsl:variable name="magnitude">
254     <xsl:call-template name="length-magnitude">
255       <xsl:with-param name="length" select="$length"/>
256     </xsl:call-template>
257   </xsl:variable>
258
259   <xsl:variable name="units">
260     <xsl:value-of select="substring($length, string-length($magnitude)+1)"/>
261   </xsl:variable>
262
263   <xsl:choose>
264     <xsl:when test="$units = ''">
265       <xsl:value-of select="$default.units"/>
266     </xsl:when>
267     <xsl:otherwise>
268       <xsl:value-of select="$units"/>
269     </xsl:otherwise>
270   </xsl:choose>
271 </xsl:template>
272 </src:fragment></programlisting>
273
274 </refsect1>
275 </refentry>
276
277 <!-- ================================================================== -->
278
279 <refentry id="length-spec">
280 <refnamediv>
281 <refname>length-spec</refname>
282 <refpurpose>Return a fully qualified length specification</refpurpose>
283 </refnamediv>
284
285 <refsect1><title>Description</title>
286
287 <para>The <function>length-spec</function> template returns the
288 qualified length from a dimension. If an unqualified length is given,
289 the <parameter>default.units</parameter> will be added to it.
290 </para>
291
292 <programlisting><src:fragment id='length-spec.frag'>
293 <xsl:template name="length-spec">
294   <xsl:param name="length" select="'0pt'"/>
295   <xsl:param name="default.units" select="'px'"/>
296
297   <xsl:variable name="magnitude">
298     <xsl:call-template name="length-magnitude">
299       <xsl:with-param name="length" select="$length"/>
300     </xsl:call-template>
301   </xsl:variable>
302
303   <xsl:variable name="units">
304     <xsl:value-of select="substring($length, string-length($magnitude)+1)"/>
305   </xsl:variable>
306
307   <xsl:value-of select="$magnitude"/>
308   <xsl:choose>
309     <xsl:when test="$units='cm'
310                     or $units='mm'
311                     or $units='in'
312                     or $units='pt'
313                     or $units='pc'
314                     or $units='px'
315                     or $units='em'">
316       <xsl:value-of select="$units"/>
317     </xsl:when>
318     <xsl:when test="$units = ''">
319       <xsl:value-of select="$default.units"/>
320     </xsl:when>
321     <xsl:otherwise>
322       <xsl:message>
323         <xsl:text>Unrecognized unit of measure: </xsl:text>
324         <xsl:value-of select="$units"/>
325         <xsl:text>.</xsl:text>
326       </xsl:message>
327     </xsl:otherwise>
328   </xsl:choose>
329 </xsl:template>
330 </src:fragment></programlisting>
331
332 </refsect1>
333 </refentry>
334
335 <!-- ================================================================== -->
336
337 <refentry id="length-in-points">
338 <refnamediv>
339 <refname>length-in-points</refname>
340 <refpurpose>Returns the size, in points, of a specified length</refpurpose>
341 </refnamediv>
342
343 <refsect1><title>Description</title>
344
345 <para>The <function>length-in-points</function> template converts a length
346 specification to points and returns that value as an unqualified
347 number.
348 </para>
349
350 <caution>
351 <para>There is no way for the template to infer the size of an
352 <literal>em</literal>. It relies on the default <parameter>em.size</parameter>
353 which is initially <literal>10</literal> (for 10pt).</para>
354
355 <para>Similarly, converting pixels to points relies on the
356 <parameter>pixels.per.inch</parameter> parameter which is initially
357 <literal>90</literal>.
358 </para>
359 </caution>
360
361 <programlisting><src:fragment id='length-in-points.frag'>
362 <xsl:template name="length-in-points">
363   <xsl:param name="length" select="'0pt'"/>
364   <xsl:param name="em.size" select="10"/>
365   <xsl:param name="pixels.per.inch" select="90"/>
366
367   <xsl:variable name="magnitude">
368     <xsl:call-template name="length-magnitude">
369       <xsl:with-param name="length" select="$length"/>
370     </xsl:call-template>
371   </xsl:variable>
372
373   <xsl:variable name="units">
374     <xsl:value-of select="substring($length, string-length($magnitude)+1)"/>
375   </xsl:variable>
376
377   <xsl:choose>
378     <xsl:when test="$units = 'pt'">
379       <xsl:value-of select="$magnitude"/>
380     </xsl:when>
381     <xsl:when test="$units = 'cm'">
382       <xsl:value-of select="$magnitude div 2.54 * 72.0"/>
383     </xsl:when>
384     <xsl:when test="$units = 'mm'">
385       <xsl:value-of select="$magnitude div 25.4 * 72.0"/>
386     </xsl:when>
387     <xsl:when test="$units = 'in'">
388       <xsl:value-of select="$magnitude * 72.0"/>
389     </xsl:when>
390     <xsl:when test="$units = 'pc'">
391       <xsl:value-of select="$magnitude * 12.0"/>
392     </xsl:when>
393     <xsl:when test="$units = 'px'">
394       <xsl:value-of select="$magnitude div $pixels.per.inch * 72.0"/>
395     </xsl:when>
396     <xsl:when test="$units = 'em'">
397       <xsl:value-of select="$magnitude * $em.size"/>
398     </xsl:when>
399     <xsl:otherwise>
400       <xsl:message>
401         <xsl:text>Unrecognized unit of measure: </xsl:text>
402         <xsl:value-of select="$units"/>
403         <xsl:text>.</xsl:text>
404       </xsl:message>
405     </xsl:otherwise>
406   </xsl:choose>
407 </xsl:template>
408 </src:fragment></programlisting>
409
410 </refsect1>
411 </refentry>
412
413 <!-- ================================================================== -->
414
415 <refentry id="pi-attribute">
416 <refnamediv>
417 <refname>pi-attribute</refname>
418 <refpurpose>Extract a pseudo-attribute from a PI</refpurpose>
419 </refnamediv>
420
421 <refsect1><title>Description</title>
422
423 <para>The <function>pi-attribute</function> template extracts a pseudo-attribute
424 from a processing instruction. For example, given the PI
425 <quote><literal>&lt;?foo bar="1" baz='red'?&gt;</literal></quote>,</para>
426 <programlisting><![CDATA[<xsl:call-template name="pi-attribute">
427   <xsl:with-param name="pis" select="processing-instruction('foo')"/>
428   <xsl:with-param name="attribute" select="'baz'"/>
429 </xsl:call-template>]]></programlisting>
430 <para>will return <quote>red</quote>. This template returns the first matching
431 attribute that it finds. Presented with processing instructions that
432 contain badly formed pseudo-attributes (missing or unbalanced quotes,
433 for example), the template may silently return erroneous results.</para>
434
435 <programlisting><src:fragment id='pi-attribute.frag'>
436 <xsl:template name="pi-attribute">
437   <xsl:param name="pis" select="processing-instruction('BOGUS_PI')"/>
438   <xsl:param name="attribute">filename</xsl:param>
439   <xsl:param name="count">1</xsl:param>
440
441   <xsl:choose>
442     <xsl:when test="$count>count($pis)">
443       <!-- not found -->
444     </xsl:when>
445     <xsl:otherwise>
446       <xsl:variable name="pi">
447         <xsl:value-of select="$pis[$count]"/>
448       </xsl:variable>
449       <xsl:variable name="pivalue">
450         <xsl:value-of select="concat(' ', normalize-space($pi))"/>
451       </xsl:variable>
452       <xsl:choose>
453         <xsl:when test="contains($pivalue,concat(' ', $attribute, '='))">
454           <xsl:variable name="rest" select="substring-after($pivalue,concat(' ', $attribute,'='))"/>
455           <xsl:variable name="quote" select="substring($rest,1,1)"/>
456           <xsl:value-of select="substring-before(substring($rest,2),$quote)"/>
457         </xsl:when>
458         <xsl:otherwise>
459           <xsl:call-template name="pi-attribute">
460             <xsl:with-param name="pis" select="$pis"/>
461             <xsl:with-param name="attribute" select="$attribute"/>
462             <xsl:with-param name="count" select="$count + 1"/>
463           </xsl:call-template>
464         </xsl:otherwise>
465       </xsl:choose>
466     </xsl:otherwise>
467   </xsl:choose>
468 </xsl:template>
469 </src:fragment></programlisting>
470
471 </refsect1>
472 </refentry>
473
474 <!-- ================================================================== -->
475
476 <refentry id="lookup.key">
477 <refnamediv>
478 <refname>lookup.key</refname>
479 <refpurpose>Retrieve the value associated with a particular key in a table</refpurpose>
480 </refnamediv>
481
482 <refsect1><title>Description</title>
483
484 <para>Given a table of space-delimited key/value pairs,
485 the <function>lookup.key</function> template extracts the value associated
486 with a particular key.</para>
487
488 <programlisting><src:fragment id='lookup.key.frag'>
489 <xsl:template name="lookup.key">
490   <xsl:param name="key" select="''"/>
491   <xsl:param name="table" select="''"/>
492
493   <xsl:if test="contains($table, ' ')">
494     <xsl:choose>
495       <xsl:when test="substring-before($table, ' ') = $key">
496         <xsl:variable name="rest" select="substring-after($table, ' ')"/>
497         <xsl:choose>
498           <xsl:when test="contains($rest, ' ')">
499             <xsl:value-of select="substring-before($rest, ' ')"/>
500           </xsl:when>
501           <xsl:otherwise>
502             <xsl:value-of select="$rest"/>
503           </xsl:otherwise>
504         </xsl:choose>
505       </xsl:when>
506       <xsl:otherwise>
507         <xsl:call-template name="lookup.key">
508           <xsl:with-param name="key" select="$key"/>
509           <xsl:with-param name="table"
510                             select="substring-after(substring-after($table,' '), ' ')"/>
511         </xsl:call-template>
512       </xsl:otherwise>
513     </xsl:choose>
514   </xsl:if>
515 </xsl:template>
516 </src:fragment></programlisting>
517
518 </refsect1>
519 </refentry>
520
521 <!-- ================================================================== -->
522
523 <refentry id="xpath.location">
524 <refnamediv>
525 <refname>xpath.location</refname>
526 <refpurpose>Calculate the XPath child-sequence to the current node</refpurpose>
527 </refnamediv>
528
529 <refsect1><title>Description</title>
530
531 <para>The <function>xpath.location</function> template calculates the
532 absolute path from the root of the tree to the current element node.
533 </para>
534
535 <programlisting><src:fragment id='xpath.location.frag'>
536 <xsl:template name="xpath.location">
537   <xsl:param name="node" select="."/>
538   <xsl:param name="path" select="''"/>
539
540   <xsl:variable name="next.path">
541     <xsl:value-of select="local-name($node)"/>
542     <xsl:if test="$path != ''">/</xsl:if>
543     <xsl:value-of select="$path"/>
544   </xsl:variable>
545
546   <xsl:choose>
547     <xsl:when test="$node/parent::*">
548       <xsl:call-template name="xpath.location">
549         <xsl:with-param name="node" select="$node/parent::*"/>
550         <xsl:with-param name="path" select="$next.path"/>
551       </xsl:call-template>
552     </xsl:when>
553     <xsl:otherwise>
554       <xsl:text>/</xsl:text>
555       <xsl:value-of select="$next.path"/>
556     </xsl:otherwise>
557   </xsl:choose>
558 </xsl:template>
559 </src:fragment></programlisting>
560
561 </refsect1>
562 </refentry>
563
564 <!-- ================================================================== -->
565
566 <refentry id="comment-escape-string">
567 <refnamediv>
568 <refname>comment-escape-string</refname>
569 <refpurpose>Prepare a string for inclusion in an XML comment</refpurpose>
570 </refnamediv>
571
572 <refsect1><title>Description</title>
573
574 <para>The <function>comment-escape-string</function> template returns a string
575 that has been transformed so that it can safely be output as an XML comment.
576 Internal occurrences of "--" will be replaced with "- -" and a leading and/or
577 trailing space will be added to the string, if necessary.</para>
578
579 <programlisting><src:fragment id='comment-escape-string'>
580 <xsl:template name="comment-escape-string">
581   <xsl:param name="string" select="''"/>
582
583   <xsl:if test="starts-with($string, '-')">
584     <xsl:text> </xsl:text>
585   </xsl:if>
586
587   <xsl:call-template name="comment-escape-string.recursive">
588     <xsl:with-param name="string" select="$string"/>
589   </xsl:call-template>
590
591   <xsl:if test="substring($string, string-length($string), 1) = '-'">
592     <xsl:text> </xsl:text>
593   </xsl:if>
594 </xsl:template>
595 </src:fragment></programlisting>
596
597 </refsect1>
598 </refentry>
599
600 <!-- ================================================================== -->
601
602 <refentry id="comment-escape-string.recursive">
603 <refnamediv>
604 <refname>comment-escape-string.recursive</refname>
605 <refpurpose>Internal function used by comment-escape-string</refpurpose>
606 </refnamediv>
607
608 <refsect1><title>Description</title>
609
610 <para>The <function>comment-escape-string.recursive</function> template is used
611 by <function>comment-escape-string</function>.</para>
612
613 <programlisting><src:fragment id="comment-escape-string.recursive">
614 <xsl:template name="comment-escape-string.recursive">
615   <xsl:param name="string" select="''"/>
616   <xsl:choose>
617     <xsl:when test="contains($string, '--')">
618       <xsl:value-of select="substring-before($string, '--')"/>
619       <xsl:value-of select="'- -'"/>
620       <xsl:call-template name="comment-escape-string.recursive">
621         <xsl:with-param name="string" select="substring-after($string, '--')"/>
622       </xsl:call-template>
623     </xsl:when>
624     <xsl:otherwise>
625       <xsl:value-of select="$string"/>
626     </xsl:otherwise>
627   </xsl:choose>
628 </xsl:template>
629 </src:fragment></programlisting>
630 </refsect1>
631 </refentry>
632
633 <!-- ================================================================== -->
634
635 <refentry id="prepend-pad">
636 <refnamediv>
637 <refname>prepend-pad</refname>
638 <refpurpose>Right-pad a string out to a certain length</refpurpose>
639 </refnamediv>
640
641 <refsect1><title>Description</title>
642
643 <para>This function takes string <parameter>padVar</parameter> and
644 pads it out to the string-length <parameter>length</parameter>, using
645 string <parameter>padChar</parameter> (a space character by default)
646 as the padding string (note that <parameter>padChar</parameter> can be
647 a string; it is not limited to just being a single character).</para>
648
649   <note>
650     <para>This function is a copy of Nate Austin's
651     <function>prepend-pad</function> function in the <ulink
652     url="http://www.dpawson.co.uk/xsl/sect2/padding.html" >Padding
653     Content</ulink> section of Dave Pawson's <ulink
654     url="http://www.dpawson.co.uk/xsl/index.html" >XSLT
655     FAQ</ulink>.</para>
656   </note>
657
658 <programlisting><src:fragment id='prepend-pad.frag'>
659   <xsl:template name="prepend-pad">   
660   <!-- recursive template to right justify and prepend-->
661   <!-- the value with whatever padChar is passed in   -->
662     <xsl:param name="padChar" select="' '"/>
663     <xsl:param name="padVar"/>
664     <xsl:param name="length"/>
665     <xsl:choose>
666       <xsl:when test="string-length($padVar) &lt; $length">
667         <xsl:call-template name="prepend-pad">
668           <xsl:with-param name="padChar" select="$padChar"/>
669           <xsl:with-param name="padVar" select="concat($padChar,$padVar)"/>
670           <xsl:with-param name="length" select="$length"/>
671         </xsl:call-template>
672       </xsl:when>
673       <xsl:otherwise>
674         <xsl:value-of
675           select="substring($padVar,string-length($padVar) - $length + 1)"/>
676       </xsl:otherwise>
677     </xsl:choose>
678   </xsl:template>
679 </src:fragment></programlisting>
680
681 </refsect1>
682 </refentry>
683
684 <!-- ================================================================== -->
685
686 <refentry id="str.tokenize.keep.delimiters">
687 <refnamediv>
688 <refname>str.tokenize.keep.delimiters</refname>
689 <refpurpose>Tokenize a string while preserving any delimiters</refpurpose>
690 </refnamediv>
691
692 <refsect1><title>Description</title>
693
694 <para>Based on the occurrence of one or more delimiter characters,
695 this function breaks a string into a list of tokens and delimiters,
696 marking up each of the tokens with a <sgmltag>token</sgmltag> element
697 and preserving the delimiters as text nodes between the tokens.</para>
698
699 <note>
700   <para>This function is a very slightly modified version of a
701   function from the <ulink url="http://www.exslt.org/">EXSLT
702   site</ulink>. The original is available at:
703
704   <blockquote><para><ulink url="http://www.exslt.org/str/functions/tokenize/str.tokenize.template.xsl"/></para></blockquote>
705
706   The <function>str.tokenize.keep.delimiters</function> function
707   differs only in that it preserves the delimiters instead of
708   discarding them.</para>
709 </note>
710
711 <programlisting><src:fragment id='str.tokenize.keep.delimiters.frag'>
712
713   <xsl:template name="str.tokenize.keep.delimiters">
714     <xsl:param name="string" select="''" />
715     <xsl:param name="delimiters" select="' '" />
716     <xsl:choose>
717       <xsl:when test="not($string)" />
718       <xsl:when test="not($delimiters)">
719         <xsl:call-template name="str.tokenize.keep.delimiters-characters">
720           <xsl:with-param name="string" select="$string" />
721         </xsl:call-template>
722       </xsl:when>
723       <xsl:otherwise>
724         <xsl:call-template name="str.tokenize.keep.delimiters-delimiters">
725           <xsl:with-param name="string" select="$string" />
726           <xsl:with-param name="delimiters" select="$delimiters" />
727         </xsl:call-template>
728       </xsl:otherwise>
729     </xsl:choose>
730   </xsl:template>
731  
732   <xsl:template name="str.tokenize.keep.delimiters-characters">
733     <xsl:param name="string" />
734     <xsl:if test="$string">
735       <token><xsl:value-of select="substring($string, 1, 1)" /></token>
736       <xsl:call-template name="str.tokenize.keep.delimiters-characters">
737         <xsl:with-param name="string" select="substring($string, 2)" />
738       </xsl:call-template>
739     </xsl:if>
740   </xsl:template>
741  
742   <xsl:template name="str.tokenize.keep.delimiters-delimiters">
743     <xsl:param name="string" />
744     <xsl:param name="delimiters" />
745     <xsl:variable name="delimiter" select="substring($delimiters, 1, 1)" />
746     <xsl:choose>
747       <xsl:when test="not($delimiter)">
748         <token><xsl:value-of select="$string" /></token>
749       </xsl:when>
750       <xsl:when test="contains($string, $delimiter)">
751         <xsl:if test="not(starts-with($string, $delimiter))">
752           <xsl:call-template name="str.tokenize.keep.delimiters-delimiters">
753             <xsl:with-param name="string" select="substring-before($string, $delimiter)" />
754             <xsl:with-param name="delimiters" select="substring($delimiters, 2)" />
755           </xsl:call-template>
756         </xsl:if>
757         <!-- output each delimiter -->
758         <xsl:value-of select="$delimiter"/>
759         <xsl:call-template name="str.tokenize.keep.delimiters-delimiters">
760           <xsl:with-param name="string" select="substring-after($string, $delimiter)" />
761           <xsl:with-param name="delimiters" select="$delimiters" />
762         </xsl:call-template>
763       </xsl:when>
764       <xsl:otherwise>
765         <xsl:call-template name="str.tokenize.keep.delimiters-delimiters">
766           <xsl:with-param name="string" select="$string" />
767           <xsl:with-param name="delimiters" select="substring($delimiters, 2)" />
768         </xsl:call-template>
769       </xsl:otherwise>
770     </xsl:choose>
771   </xsl:template>
772 </src:fragment></programlisting>
773
774 </refsect1>
775 </refentry>
776
777 <!-- ================================================================== -->
778
779 <refentry id="apply-string-subst-map">
780   <refnamediv>
781     <refname>apply-string-subst-map</refname>
782     <refpurpose>Apply a string-substitution map</refpurpose>
783   </refnamediv>
784
785   <refsect1><title>Description</title>
786
787   <para>This function applies a "string substitution" map. Use it when
788   you want to do multiple string substitutions on the same target
789   content. It reads in two things: <parameter>content</parameter>, the
790   content on which to perform the substitution, and
791   <parameter>map.contents</parameter>, a node set of
792   elements (the names of the elements don't matter), with each element
793   having the following attributes:
794   <itemizedlist>
795     <listitem>
796       <simpara><tag class="attribute">oldstring</tag>, a string to
797       be replaced</simpara>
798     </listitem>
799     <listitem>
800       <simpara><tag class="attribute">newstring</tag>, a string with
801       which to replace <tag class="attribute">oldstring</tag></simpara>
802     </listitem>
803   </itemizedlist>
804   The function uses <parameter>map.contents</parameter> to
805   do substitution on <parameter>content</parameter>, and then
806   returns the modified contents.</para>
807
808   <note>
809     <para>This function is a very slightly modified version of Jeni
810     Tennison's <function>replace_strings</function> function in the
811     <ulink
812     url="http://www.dpawson.co.uk/xsl/sect2/StringReplace.html#d9351e13"
813     >multiple string replacements</ulink> section of Dave Pawson's
814     <ulink url="http://www.dpawson.co.uk/xsl/index.html" >XSLT
815     FAQ</ulink>.</para>
816
817     <para>The <function>apply-string-subst-map</function> function is
818     essentially the same function as the
819     <function>apply-character-map</function> function; the only
820     difference is that in the map that
821     <function>apply-string-subst-map</function> expects, <tag
822     class="attribute">oldstring</tag> and <tag
823     class="attribute">newstring</tag> attributes are used instead of
824     <tag class="attribute">character</tag> and <tag
825     class="attribute">string</tag> attributes.</para>
826   </note>
827
828   <programlisting><src:fragment id='apply-string-subst-map.frag'>
829     <xsl:template name="apply-string-subst-map">
830       <xsl:param name="content"/>
831       <xsl:param name="map.contents"/>
832       <xsl:variable name="replaced_text">
833         <xsl:call-template name="string.subst">
834           <xsl:with-param name="string" select="$content" />
835           <xsl:with-param name="target"
836                           select="$map.contents[1]/@oldstring" />
837           <xsl:with-param name="replacement"
838                           select="$map.contents[1]/@newstring" />
839         </xsl:call-template>
840       </xsl:variable>
841       <xsl:choose>
842         <xsl:when test="$map.contents[2]">
843           <xsl:call-template name="apply-string-subst-map">
844             <xsl:with-param name="content" select="$replaced_text" />
845             <xsl:with-param name="map.contents"
846                             select="$map.contents[position() > 1]" />
847           </xsl:call-template>
848         </xsl:when>
849         <xsl:otherwise>
850           <xsl:value-of select="$replaced_text" />
851         </xsl:otherwise>
852       </xsl:choose>
853     </xsl:template>
854
855   </src:fragment></programlisting>
856   </refsect1>
857 </refentry>
858
859 <!-- ================================================================== -->
860
861 <refentry id="apply-character-map">
862   <refnamediv>
863     <refname>apply-character-map</refname>
864     <refpurpose>Apply an XSLT character map</refpurpose>
865   </refnamediv>
866
867   <refsect1><title>Description</title>
868
869   <para>This function applies an <ulink
870   url="http://www.w3.org/TR/xslt20/#character-maps">XSLT character
871   map</ulink>; that is, it cause certain individual characters to be
872   substituted with strings of one or more characters. It is useful
873   mainly for replacing multiple "special" chararacters or symbols in
874   the same target content. It reads in two things:
875   <parameter>content</parameter>, the content on which to perform the
876   substitution, and <parameter>map.contents</parameter>, a
877   node set of elements (the names of the elements don't matter), with
878   each element having the following attributes:
879   <itemizedlist>
880     <listitem>
881       <simpara><tag class="attribute">character</tag>, a character to
882       be replaced</simpara>
883     </listitem>
884     <listitem>
885       <simpara><tag class="attribute">string</tag>, a string with
886       which to replace <tag class="attribute">character</tag></simpara>
887     </listitem>
888   </itemizedlist>
889   This function uses <parameter>map.contents</parameter> to
890   do substitution on <parameter>content</parameter>, and then returns
891   the modified contents.</para>
892
893   <note>
894     <para>This function is a very slightly modified version of Jeni
895     Tennison's <function>replace_strings</function> function in the
896     <ulink
897         url="http://www.dpawson.co.uk/xsl/sect2/StringReplace.html#d9351e13"
898         >multiple string replacements</ulink> section of Dave Pawson's
899     <ulink url="http://www.dpawson.co.uk/xsl/index.html" >XSLT
900     FAQ</ulink>.</para>
901
902     <para>The <function>apply-string-subst-map</function> function is
903     essentially the same function as the
904     <function>apply-character-map</function> function; the only
905     difference is that in the map that
906     <function>apply-string-subst-map</function> expects, <tag
907     class="attribute">oldstring</tag> and <tag
908     class="attribute">newstring</tag> attributes are used instead of
909     <tag class="attribute">character</tag> and <tag
910     class="attribute">string</tag> attributes.</para>
911   </note>
912
913   <programlisting><src:fragment id='apply-character-map.frag'>
914     <xsl:template name="apply-character-map">
915       <xsl:param name="content"/>
916       <xsl:param name="map.contents"/>
917       <xsl:variable name="replaced_text">
918         <xsl:call-template name="string.subst">
919           <xsl:with-param name="string" select="$content" />
920           <xsl:with-param name="target"
921                           select="$map.contents[1]/@character" />
922           <xsl:with-param name="replacement"
923                           select="$map.contents[1]/@string" />
924         </xsl:call-template>
925       </xsl:variable>
926       <xsl:choose>
927         <xsl:when test="$map.contents[2]">
928           <xsl:call-template name="apply-character-map">
929             <xsl:with-param name="content" select="$replaced_text" />
930             <xsl:with-param name="map.contents"
931                             select="$map.contents[position() > 1]" />
932           </xsl:call-template>
933         </xsl:when>
934         <xsl:otherwise>
935           <xsl:value-of select="$replaced_text" />
936         </xsl:otherwise>
937       </xsl:choose>
938     </xsl:template>
939
940   </src:fragment></programlisting>
941   </refsect1>
942 </refentry>
943
944 <!-- ================================================================== -->
945
946 <refentry id="read-character-map">
947 <refnamediv>
948 <refname>read-character-map</refname>
949 <refpurpose>Read in all or part of an XSLT character map</refpurpose>
950 </refnamediv>
951
952 <refsect1><title>Description</title>
953
954 <para>The XSLT 2.0 specification describes <ulink
955 url="http://www.w3.org/TR/xslt20/#character-maps">character
956 maps</ulink> and explains how they may be used to allow a specific
957 character appearing in a text or attribute node in a final results
958 tree to be substituted by a specified string of characters during
959 serialization. The <function>read-character-map</function> function
960 provides a means for reading and using character maps with XSLT
961 1.0-based tools.</para>
962
963 <para>It reads the character-map contents from
964 <parameter>uri</parameter> (in full or in part, depending on the value
965 of the <parameter>use.subset</parameter> parameter), then passes those
966 contents to the <function>apply-character-map</function> function,
967 along with <parameter>content</parameter>, the data on which to
968 perform the character substition.</para>
969
970 <para>Using the character map "in part" means that it uses only those
971 <tag>output-character</tag> elements that match the XPATH expression
972 given in the value of the <parameter>subset.profile</parameter>
973 parameter. The current implementation of that capability here relies
974 on the <function>evaluate</function> extension XSLT function.</para>
975
976 <programlisting><src:fragment id='read-character-map.frag'>
977   <xsl:template name="read-character-map">
978     <xsl:param name="use.subset"/>
979     <xsl:param name="subset.profile"/>
980     <xsl:param name="uri"/>
981     <xsl:choose>
982       <xsl:when test="$use.subset != 0">
983         <!-- use a subset of the character map instead of the full map -->
984         <xsl:choose>
985           <!-- xsltproc and Xalan both support dyn:evaluate() -->
986           <xsl:when test="function-available('dyn:evaluate')">
987             <xsl:copy-of select="document($uri)//*[local-name()='output-character']
988                                  [dyn:evaluate($subset.profile)]"/>
989           </xsl:when>
990           <!-- Saxon has its own evaluate() & doesn't support dyn:evaluate() -->
991           <xsl:when test="function-available('saxon:evaluate')">
992             <xsl:copy-of select="document($uri)//*[local-name()='output-character']
993                                  [saxon:evaluate($subset.profile)]"/>
994           </xsl:when>
995           <xsl:otherwise>
996             <xsl:message terminate="yes"
997 >
998 Error: To process character-map subsets, you must use an XSLT engine
999 that supports the evaluate() XSLT extension function. Your XSLT engine
1000 does not support it.
1001 </xsl:message>
1002           </xsl:otherwise>
1003         </xsl:choose>
1004         </xsl:when>
1005         <xsl:otherwise>
1006           <!-- value of $use.subet is non-zero, so use the full map -->
1007         <xsl:copy-of select="document($uri)//*[local-name()='output-character']"/>
1008       </xsl:otherwise>
1009     </xsl:choose>
1010   </xsl:template>
1011 </src:fragment></programlisting>
1012 </refsect1>
1013 </refentry>
1014
1015 </reference>
1016
1017 <!-- ==================================================================  -->
1018
1019 <reference>
1020 <title>Relative URI Functions</title>
1021
1022 <partintro><title>Introduction</title>
1023
1024 <para>These functions manipulate relative URI references.</para>
1025
1026 <para>The following assumptions must hold true:</para>
1027
1028 <orderedlist>
1029 <listitem>
1030 <para>All URIs are relative.</para>
1031 </listitem>
1032 <listitem>
1033 <para>No URI contains the <quote><literal>../</literal></quote> sequence
1034 which would effectively move <quote>up</quote> the hierarchy.</para>
1035 </listitem>
1036 </orderedlist>
1037
1038 <para>If these assumptions do not hold, the results are unpredictable.</para>
1039
1040 </partintro>
1041
1042 <!-- ================================================================== -->
1043
1044 <refentry id="count.uri.path.depth">
1045 <refnamediv>
1046 <refname>count.uri.path.depth</refname>
1047 <refpurpose>Count the number of path components in a relative URI</refpurpose>
1048 </refnamediv>
1049
1050 <refsect1><title>Description</title>
1051
1052 <para>This function counts the number of path components in a relative URI.</para>
1053
1054 <programlisting><src:fragment id='count.uri.path.depth.frag'>
1055 <xsl:template name="count.uri.path.depth">
1056   <xsl:param name="filename" select="''"/>
1057   <xsl:param name="count" select="0"/>
1058
1059   <xsl:choose>
1060     <xsl:when test="contains($filename, '/')">
1061       <xsl:call-template name="count.uri.path.depth">
1062         <xsl:with-param name="filename" select="substring-after($filename, '/')"/>
1063         <xsl:with-param name="count" select="$count + 1"/>
1064       </xsl:call-template>
1065     </xsl:when>
1066     <xsl:otherwise>
1067       <xsl:value-of select="$count"/>
1068     </xsl:otherwise>
1069   </xsl:choose>
1070 </xsl:template>
1071 </src:fragment></programlisting>
1072
1073 </refsect1>
1074 </refentry>
1075
1076 <!-- ================================================================== -->
1077
1078 <refentry id="trim.common.uri.paths">
1079 <refnamediv>
1080 <refname>trim.common.uri.paths</refname>
1081 <refpurpose>Trim common leading path components from a relative URI</refpurpose>
1082 </refnamediv>
1083
1084 <refsect1><title>Description</title>
1085
1086 <para>This function trims common leading path components from a relative URI.</para>
1087
1088 <programlisting><src:fragment id='trim.common.uri.paths.frag'>
1089 <xsl:template name="trim.common.uri.paths">
1090   <xsl:param name="uriA" select="''"/>
1091   <xsl:param name="uriB" select="''"/>
1092   <xsl:param name="return" select="'A'"/>
1093
1094   <xsl:choose>
1095     <xsl:when test="contains($uriA, '/') and contains($uriB, '/')
1096                     and substring-before($uriA, '/') = substring-before($uriB, '/')">
1097       <xsl:call-template name="trim.common.uri.paths">
1098         <xsl:with-param name="uriA" select="substring-after($uriA, '/')"/>
1099         <xsl:with-param name="uriB" select="substring-after($uriB, '/')"/>
1100         <xsl:with-param name="return" select="$return"/>
1101       </xsl:call-template>
1102     </xsl:when>
1103     <xsl:otherwise>
1104       <xsl:choose>
1105         <xsl:when test="$return = 'A'">
1106           <xsl:value-of select="$uriA"/>
1107         </xsl:when>
1108         <xsl:otherwise>
1109           <xsl:value-of select="$uriB"/>
1110         </xsl:otherwise>
1111       </xsl:choose>
1112     </xsl:otherwise>
1113   </xsl:choose>
1114 </xsl:template>
1115 </src:fragment></programlisting>
1116
1117 </refsect1>
1118 </refentry>
1119
1120 </reference>
1121
1122 <!-- ================================================================== -->
1123
1124 <appendix><title>The Stylesheet</title>
1125
1126 <para>The <filename>lib.xsl</filename> stylesheet is just a wrapper
1127 around these functions.</para>
1128
1129 <src:fragment id="top" mundane-result-prefixes="xsl">
1130
1131 <!-- ********************************************************************
1132      $Id: lib.xweb,v 1.13 2005/07/08 10:35:55 xmldoc Exp $
1133      ********************************************************************
1134
1135      This file is part of the XSL DocBook Stylesheet distribution.
1136      See ../README or http://nwalsh.com/docbook/xsl/ for copyright
1137      and other information.
1138
1139      This module implements DTD-independent functions
1140
1141      ******************************************************************** -->
1142
1143 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1144                 xmlns:src="http://nwalsh.com/xmlns/litprog/fragment"
1145                 exclude-result-prefixes="src"
1146                 version='1.0'>
1147
1148 <src:fragref linkend="dot.count.frag"/>
1149 <src:fragref linkend="copy-string.frag"/>
1150 <src:fragref linkend="string.subst.frag"/>
1151 <src:fragref linkend="xpointer.idref.frag"/>
1152 <src:fragref linkend="length-magnitude.frag"/>
1153 <src:fragref linkend="length-units.frag"/>
1154 <src:fragref linkend="length-spec.frag"/>
1155 <src:fragref linkend="length-in-points.frag"/>
1156 <src:fragref linkend="pi-attribute.frag"/>
1157 <src:fragref linkend="lookup.key.frag"/>
1158 <src:fragref linkend="xpath.location.frag"/>
1159 <src:fragref linkend="comment-escape-string"/>
1160 <src:fragref linkend="comment-escape-string.recursive"/>
1161 <src:fragref linkend="prepend-pad.frag"/>
1162 <src:fragref linkend="str.tokenize.keep.delimiters.frag"/>
1163 <src:fragref linkend="apply-string-subst-map.frag"/>
1164 <src:fragref linkend="apply-character-map.frag"/>
1165 <src:fragref linkend="read-character-map.frag"/>
1166 <src:fragref linkend="count.uri.path.depth.frag"/>
1167 <src:fragref linkend="trim.common.uri.paths.frag"/>
1168
1169 </xsl:stylesheet>
1170 </src:fragment>
1171
1172 </appendix>
1173 </book>
Note: See TracBrowser for help on using the browser.