Mercurial > hg > mpdl-group
comparison software/eXist/webapp/mpdl/_stuff/futureDev/html2fop.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 |
comparison
equal
deleted
inserted
replaced
6:2396a569e446 | 7:5589d865af7a |
---|---|
1 <?xml version="1.0"?> | |
2 <xsl:stylesheet | |
3 version="1.0" | |
4 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" | |
5 xmlns:fo="http://www.w3.org/1999/XSL/Format" | |
6 xmlns:fox="http://xml.apache.org/fop/extensions"> | |
7 | |
8 <!-- ============================================ | |
9 This stylesheet transforms most of the common | |
10 HTML elements into XSL formatting objects. | |
11 | |
12 This version written 1 November 2002 by | |
13 Doug Tidwell, dtidwell@us.ibm.com. | |
14 | |
15 Brought to you by your friends at developerWorks: | |
16 ibm.com/developerWorks. | |
17 =============================================== --> | |
18 | |
19 <!-- ============================================ | |
20 This variable sets the size of the page. If | |
21 it's 'ltr', we an 8.5 x 11 inch page; otherwise, | |
22 we use an A4-sized page. 'ltr' is the default. | |
23 To change the value, you can make the following | |
24 line read select="'A4'", or you can check the | |
25 documentation for your XSLT processor to see | |
26 how to set variables externally to the style | |
27 sheet. (For Xalan, add "-PARAM page-size a4" | |
28 to the command.) | |
29 =============================================== --> | |
30 | |
31 <xsl:variable name="page-size" select="'ltr'"/> | |
32 | |
33 <xsl:template match="html"> | |
34 | |
35 <!-- ============================================ | |
36 Because character entities aren't built into | |
37 the XSL-FO vocabulary, they're included here. | |
38 =============================================== --> | |
39 | |
40 <xsl:text disable-output-escaping="yes"> | |
41 <!DOCTYPE fo:root [ | |
42 <!ENTITY tilde "&#126;"> | |
43 <!ENTITY florin "&#131;"> | |
44 <!ENTITY elip "&#133;"> | |
45 <!ENTITY dag "&#134;"> | |
46 <!ENTITY ddag "&#135;"> | |
47 <!ENTITY cflex "&#136;"> | |
48 <!ENTITY permil "&#137;"> | |
49 <!ENTITY uscore "&#138;"> | |
50 <!ENTITY OElig "&#140;"> | |
51 <!ENTITY lsquo "&#145;"> | |
52 <!ENTITY rsquo "&#146;"> | |
53 <!ENTITY ldquo "&#147;"> | |
54 <!ENTITY rdquo "&#148;"> | |
55 <!ENTITY bullet "&#149;"> | |
56 <!ENTITY endash "&#150;"> | |
57 <!ENTITY emdash "&#151;"> | |
58 <!ENTITY trade "&#153;"> | |
59 <!ENTITY oelig "&#156;"> | |
60 <!ENTITY Yuml "&#159;"> | |
61 | |
62 <!ENTITY nbsp "&#160;"> | |
63 <!ENTITY iexcl "&#161;"> | |
64 <!ENTITY cent "&#162;"> | |
65 <!ENTITY pound "&#163;"> | |
66 <!ENTITY curren "&#164;"> | |
67 <!ENTITY yen "&#165;"> | |
68 <!ENTITY brvbar "&#166;"> | |
69 <!ENTITY sect "&#167;"> | |
70 <!ENTITY uml "&#168;"> | |
71 <!ENTITY copy "&#169;"> | |
72 <!ENTITY ordf "&#170;"> | |
73 <!ENTITY laquo "&#171;"> | |
74 <!ENTITY not "&#172;"> | |
75 <!ENTITY shy "&#173;"> | |
76 <!ENTITY reg "&#174;"> | |
77 <!ENTITY macr "&#175;"> | |
78 <!ENTITY deg "&#176;"> | |
79 <!ENTITY plusmn "&#177;"> | |
80 <!ENTITY sup2 "&#178;"> | |
81 <!ENTITY sup3 "&#179;"> | |
82 <!ENTITY acute "&#180;"> | |
83 <!ENTITY micro "&#181;"> | |
84 <!ENTITY para "&#182;"> | |
85 <!ENTITY middot "&#183;"> | |
86 <!ENTITY cedil "&#184;"> | |
87 <!ENTITY sup1 "&#185;"> | |
88 <!ENTITY ordm "&#186;"> | |
89 <!ENTITY raquo "&#187;"> | |
90 <!ENTITY frac14 "&#188;"> | |
91 <!ENTITY frac12 "&#189;"> | |
92 <!ENTITY frac34 "&#190;"> | |
93 <!ENTITY iquest "&#191;"> | |
94 <!ENTITY Agrave "&#192;"> | |
95 <!ENTITY Aacute "&#193;"> | |
96 <!ENTITY Acirc "&#194;"> | |
97 <!ENTITY Atilde "&#195;"> | |
98 <!ENTITY Auml "&#196;"> | |
99 <!ENTITY Aring "&#197;"> | |
100 <!ENTITY AElig "&#198;"> | |
101 <!ENTITY Ccedil "&#199;"> | |
102 <!ENTITY Egrave "&#200;"> | |
103 <!ENTITY Eacute "&#201;"> | |
104 <!ENTITY Ecirc "&#202;"> | |
105 <!ENTITY Euml "&#203;"> | |
106 <!ENTITY Igrave "&#204;"> | |
107 <!ENTITY Iacute "&#205;"> | |
108 <!ENTITY Icirc "&#206;"> | |
109 <!ENTITY Iuml "&#207;"> | |
110 <!ENTITY ETH "&#208;"> | |
111 <!ENTITY Ntilde "&#209;"> | |
112 <!ENTITY Ograve "&#210;"> | |
113 <!ENTITY Oacute "&#211;"> | |
114 <!ENTITY Ocirc "&#212;"> | |
115 <!ENTITY Otilde "&#213;"> | |
116 <!ENTITY Ouml "&#214;"> | |
117 <!ENTITY times "&#215;"> | |
118 <!ENTITY Oslash "&#216;"> | |
119 <!ENTITY Ugrave "&#217;"> | |
120 <!ENTITY Uacute "&#218;"> | |
121 <!ENTITY Ucirc "&#219;"> | |
122 <!ENTITY Uuml "&#220;"> | |
123 <!ENTITY Yacute "&#221;"> | |
124 <!ENTITY THORN "&#222;"> | |
125 <!ENTITY szlig "&#223;"> | |
126 <!ENTITY agrave "&#224;"> | |
127 <!ENTITY aacute "&#225;"> | |
128 <!ENTITY acirc "&#226;"> | |
129 <!ENTITY atilde "&#227;"> | |
130 <!ENTITY auml "&#228;"> | |
131 <!ENTITY aring "&#229;"> | |
132 <!ENTITY aelig "&#230;"> | |
133 <!ENTITY ccedil "&#231;"> | |
134 <!ENTITY egrave "&#232;"> | |
135 <!ENTITY eacute "&#233;"> | |
136 <!ENTITY ecirc "&#234;"> | |
137 <!ENTITY euml "&#235;"> | |
138 <!ENTITY igrave "&#236;"> | |
139 <!ENTITY iacute "&#237;"> | |
140 <!ENTITY icirc "&#238;"> | |
141 <!ENTITY iuml "&#239;"> | |
142 <!ENTITY eth "&#240;"> | |
143 <!ENTITY ntilde "&#241;"> | |
144 <!ENTITY ograve "&#242;"> | |
145 <!ENTITY oacute "&#243;"> | |
146 <!ENTITY ocirc "&#244;"> | |
147 <!ENTITY otilde "&#245;"> | |
148 <!ENTITY ouml "&#246;"> | |
149 <!ENTITY oslash "&#248;"> | |
150 <!ENTITY ugrave "&#249;"> | |
151 <!ENTITY uacute "&#250;"> | |
152 <!ENTITY ucirc "&#251;"> | |
153 <!ENTITY uuml "&#252;"> | |
154 <!ENTITY yacute "&#253;"> | |
155 <!ENTITY thorn "&#254;"> | |
156 <!ENTITY yuml "&#255;"> | |
157 ]> | |
158 </xsl:text> | |
159 | |
160 <!-- ============================================ | |
161 The XSL-FO section starts here.... | |
162 =============================================== --> | |
163 | |
164 <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" | |
165 xmlns:fox="http://xml.apache.org/fop/extensions"> | |
166 | |
167 <!-- ============================================ | |
168 Define the page layouts. There are two sets of | |
169 three page mastters here; we use one set for | |
170 letter-sized paper, the other set for A4. | |
171 =============================================== --> | |
172 | |
173 <fo:layout-master-set> | |
174 <xsl:choose> | |
175 <xsl:when test="$page-size='ltr'"> | |
176 <fo:simple-page-master master-name="first" | |
177 page-height="11in" page-width="8.5in" | |
178 margin-right="72pt" margin-left="72pt" | |
179 margin-bottom="36pt" margin-top="72pt"> | |
180 <fo:region-body margin-bottom="50pt"/> | |
181 <fo:region-after region-name="ra-right" | |
182 extent="25pt"/> | |
183 </fo:simple-page-master> | |
184 | |
185 <fo:simple-page-master master-name="left" | |
186 page-height="11in" page-width="8.5in" | |
187 margin-right="72pt" margin-left="72pt" | |
188 margin-bottom="36pt" margin-top="36pt"> | |
189 <fo:region-before region-name="rb-left" | |
190 extent="25pt"/> | |
191 <fo:region-body margin-top="50pt" | |
192 margin-bottom="50pt"/> | |
193 <fo:region-after region-name="ra-left" | |
194 extent="25pt"/> | |
195 </fo:simple-page-master> | |
196 | |
197 <fo:simple-page-master master-name="right" | |
198 page-height="11in" page-width="8.5in" | |
199 margin-right="72pt" margin-left="72pt" | |
200 margin-bottom="36pt" margin-top="36pt"> | |
201 <fo:region-before region-name="rb-right" | |
202 extent="25pt"/> | |
203 <fo:region-body margin-top="50pt" | |
204 margin-bottom="50pt"/> | |
205 <fo:region-after region-name="ra-right" | |
206 extent="25pt"/> | |
207 </fo:simple-page-master> | |
208 </xsl:when> | |
209 | |
210 <!-- ============================================ | |
211 Page layouts for A4-sized paper | |
212 =============================================== --> | |
213 | |
214 <xsl:otherwise> | |
215 <fo:simple-page-master master-name="first" | |
216 page-height="29.7cm" page-width="21cm" | |
217 margin-right="72pt" margin-left="72pt" | |
218 margin-bottom="36pt" margin-top="72pt"> | |
219 <fo:region-body margin-top="1.5cm" | |
220 margin-bottom="1.5cm"/> | |
221 <fo:region-after region-name="ra-right" | |
222 extent="1cm"/> | |
223 </fo:simple-page-master> | |
224 | |
225 <fo:simple-page-master master-name="left" | |
226 page-height="29.7cm" page-width="21cm" | |
227 margin-right="72pt" margin-left="72pt" | |
228 margin-bottom="36pt" margin-top="36pt"> | |
229 <fo:region-before region-name="rb-left" | |
230 extent="3cm"/> | |
231 <fo:region-body margin-top="1.5cm" | |
232 margin-bottom="1.5cm"/> | |
233 <fo:region-after region-name="ra-left" | |
234 extent="1cm"/> | |
235 </fo:simple-page-master> | |
236 | |
237 <fo:simple-page-master master-name="right" | |
238 page-height="29.7cm" page-width="21cm" | |
239 margin-right="72pt" margin-left="72pt" | |
240 margin-bottom="36pt" margin-top="36pt"> | |
241 <fo:region-before region-name="rb-right" | |
242 extent="3cm"/> | |
243 <fo:region-body margin-top="1.5cm" | |
244 margin-bottom="1.5cm"/> | |
245 <fo:region-after region-name="ra-right" | |
246 extent="1cm"/> | |
247 </fo:simple-page-master> | |
248 </xsl:otherwise> | |
249 </xsl:choose> | |
250 | |
251 <!-- ============================================ | |
252 Now we define how we use the page layouts. One | |
253 is for the first page, one is for the even- | |
254 numbered pages, and one is for odd-numbered pages. | |
255 =============================================== --> | |
256 | |
257 <fo:page-sequence-master master-name="standard"> | |
258 <fo:repeatable-page-master-alternatives> | |
259 <fo:conditional-page-master-reference | |
260 master-reference="first" | |
261 page-position="first"/> | |
262 <fo:conditional-page-master-reference | |
263 master-reference="left" | |
264 odd-or-even="even"/> | |
265 <fo:conditional-page-master-reference | |
266 master-reference="right" | |
267 odd-or-even="odd"/> | |
268 </fo:repeatable-page-master-alternatives> | |
269 </fo:page-sequence-master> | |
270 | |
271 </fo:layout-master-set> | |
272 | |
273 <!-- ============================================ | |
274 Now that we've defined all of the page layouts, | |
275 we generate the bookmarks for the PDF file. | |
276 =============================================== --> | |
277 | |
278 <xsl:call-template name="generate-bookmarks"/> | |
279 | |
280 <!-- ============================================ | |
281 This is where the actual content of the document | |
282 starts. | |
283 =============================================== --> | |
284 | |
285 <fo:page-sequence master-reference="standard"> | |
286 | |
287 <!-- ============================================ | |
288 We define the static content for the headers | |
289 and footers of the various page layouts first. | |
290 =============================================== --> | |
291 | |
292 <fo:static-content flow-name="rb-right"> | |
293 <fo:block font-size="10pt" text-align-last="end"> | |
294 <fo:table table-layout="fixed"> | |
295 <fo:table-column column-width="396pt"/> | |
296 <fo:table-column column-width="72pt"/> | |
297 <fo:table-body> | |
298 <fo:table-row> | |
299 <fo:table-cell> | |
300 <fo:block text-align="start"> | |
301 developerWorks loves you! | |
302 </fo:block> | |
303 </fo:table-cell> | |
304 <fo:table-cell> | |
305 <fo:block text-align="end" font-weight="bold" | |
306 font-family="monospace"> | |
307 ibm.com/developerWorks | |
308 </fo:block> | |
309 </fo:table-cell> | |
310 </fo:table-row> | |
311 </fo:table-body> | |
312 </fo:table> | |
313 </fo:block> | |
314 </fo:static-content> | |
315 <fo:static-content flow-name="ra-right"> | |
316 <fo:block font-size="10pt" text-align-last="end"> | |
317 <fo:table table-layout="fixed"> | |
318 <fo:table-column column-width="396pt"/> | |
319 <fo:table-column column-width="72pt"/> | |
320 <fo:table-body> | |
321 <fo:table-row> | |
322 <fo:table-cell> | |
323 <fo:block text-align="start"> | |
324 <xsl:value-of select="/html/head/title"/> | |
325 </fo:block> | |
326 </fo:table-cell> | |
327 <fo:table-cell> | |
328 <fo:block text-align="end">Page | |
329 <fo:page-number/> of | |
330 <fo:page-number-citation | |
331 ref-id="TheVeryLastPage"/> | |
332 </fo:block> | |
333 </fo:table-cell> | |
334 </fo:table-row> | |
335 </fo:table-body> | |
336 </fo:table> | |
337 </fo:block> | |
338 </fo:static-content> | |
339 <fo:static-content flow-name="rb-left"> | |
340 <fo:block font-size="10pt" text-align-last="end"> | |
341 <fo:table table-layout="fixed"> | |
342 <fo:table-column column-width="72pt"/> | |
343 <fo:table-column column-width="396pt"/> | |
344 <fo:table-body> | |
345 <fo:table-row> | |
346 <fo:table-cell> | |
347 <fo:block text-align="start" font-weight="bold" | |
348 font-family="monospace"> | |
349 ibm.com/developerWorks | |
350 </fo:block> | |
351 </fo:table-cell> | |
352 <fo:table-cell> | |
353 <fo:block text-align="end"> | |
354 developerWorks loves you! | |
355 </fo:block> | |
356 </fo:table-cell> | |
357 </fo:table-row> | |
358 </fo:table-body> | |
359 </fo:table> | |
360 </fo:block> | |
361 </fo:static-content> | |
362 <fo:static-content flow-name="ra-left"> | |
363 <fo:block font-size="10pt" text-align-last="end"> | |
364 <fo:table table-layout="fixed"> | |
365 <fo:table-column column-width="72pt"/> | |
366 <fo:table-column column-width="396pt"/> | |
367 <fo:table-body> | |
368 <fo:table-row> | |
369 <fo:table-cell> | |
370 <fo:block text-align="start">Page | |
371 <fo:page-number/> | |
372 of <fo:page-number-citation | |
373 ref-id="TheVeryLastPage"/> | |
374 </fo:block> | |
375 </fo:table-cell> | |
376 <fo:table-cell> | |
377 <fo:block text-align="end"> | |
378 <xsl:value-of select="/html/head/title"/> | |
379 </fo:block> | |
380 </fo:table-cell> | |
381 </fo:table-row> | |
382 </fo:table-body> | |
383 </fo:table> | |
384 </fo:block> | |
385 </fo:static-content> | |
386 | |
387 <xsl:apply-templates select="body"/> | |
388 </fo:page-sequence> | |
389 </fo:root> | |
390 </xsl:template> | |
391 | |
392 <!-- ============================================ | |
393 Templates for individual HTML elements begin | |
394 here. | |
395 =============================================== --> | |
396 | |
397 <!-- ============================================ | |
398 Processing for the anchor tag is complex. First | |
399 of all, if this is a named anchor, we write an empty | |
400 <fo:block> with the appropriate id. (In the special | |
401 case that the next element is an <h1>, we ignore | |
402 the element altogether and put the id on the <h1>.) | |
403 Next, if this is a regular anchor and the href | |
404 starts with a hash mark (#), we create a link with | |
405 an internal-destination. Otherwise, we create a | |
406 link with an external destination. | |
407 =============================================== --> | |
408 | |
409 <xsl:template match="a"> | |
410 <xsl:choose> | |
411 <xsl:when test="@name"> | |
412 <xsl:if test="not(name(following-sibling::*[1]) = 'h1')"> | |
413 <fo:block line-height="0pt" space-after="0pt" | |
414 font-size="0pt" id="{@name}"/> | |
415 </xsl:if> | |
416 </xsl:when> | |
417 <xsl:when test="@href"> | |
418 <fo:basic-link color="blue"> | |
419 <xsl:choose> | |
420 <xsl:when test="starts-with(@href, '#')"> | |
421 <xsl:attribute name="internal-destination"> | |
422 <xsl:value-of select="substring(@href, 2)"/> | |
423 </xsl:attribute> | |
424 </xsl:when> | |
425 <xsl:otherwise> | |
426 <xsl:attribute name="external-destination"> | |
427 <xsl:value-of select="@href"/> | |
428 </xsl:attribute> | |
429 </xsl:otherwise> | |
430 </xsl:choose> | |
431 <xsl:apply-templates select="*|text()"/> | |
432 </fo:basic-link> | |
433 <xsl:if test="starts-with(@href, '#')"> | |
434 <xsl:text> on page </xsl:text> | |
435 <fo:page-number-citation ref-id="{substring(@href, 2)}"/> | |
436 </xsl:if> | |
437 </xsl:when> | |
438 </xsl:choose> | |
439 </xsl:template> | |
440 | |
441 <!-- ============================================ | |
442 We render an address element in italics. | |
443 =============================================== --> | |
444 | |
445 <xsl:template match="address"> | |
446 <fo:block font-style="italic" space-after="12pt"> | |
447 <xsl:apply-templates select="*|text()"/> | |
448 </fo:block> | |
449 </xsl:template> | |
450 | |
451 <!-- ============================================ | |
452 For bold elements, we just change the font-weight. | |
453 =============================================== --> | |
454 | |
455 <xsl:template match="b"> | |
456 <fo:inline font-weight="bold"> | |
457 <xsl:apply-templates select="*|text()"/> | |
458 </fo:inline> | |
459 </xsl:template> | |
460 | |
461 <!-- ============================================ | |
462 The big element is handled with a relative | |
463 font size. That means a <big> element inside | |
464 another <big> element will be even bigger, just | |
465 as it is in HTML. | |
466 =============================================== --> | |
467 | |
468 <xsl:template match="big"> | |
469 <fo:inline font-size="120%"> | |
470 <xsl:apply-templates select="*|text()"/> | |
471 </fo:inline> | |
472 </xsl:template> | |
473 | |
474 <!-- ============================================ | |
475 A blockquote is indented on both sides. | |
476 =============================================== --> | |
477 | |
478 <xsl:template match="blockquote"> | |
479 <fo:block start-indent="1.5cm" end-indent="1.5cm" | |
480 space-after="12pt"> | |
481 <xsl:apply-templates select="*|text()"/> | |
482 </fo:block> | |
483 </xsl:template> | |
484 | |
485 <!-- ============================================ | |
486 The HTML <body> element contains everything in | |
487 the main part of the document. This is analogous | |
488 to the <fo:flow flow-name="xsl-region-body"> | |
489 element, so we put the main document processing here. | |
490 =============================================== --> | |
491 | |
492 <xsl:template match="body"> | |
493 | |
494 <!-- ============================================ | |
495 Start generating the content for the main page | |
496 area (xsl-region-body). | |
497 =============================================== --> | |
498 | |
499 <fo:flow flow-name="xsl-region-body"> | |
500 <xsl:apply-templates select="/html/head/title"/> | |
501 <fo:block space-after="12pt" line-height="17pt" | |
502 font-size="14pt" text-align="center"> | |
503 developerWorks loves you! | |
504 </fo:block> | |
505 <fo:block space-after="24pt" line-height="17pt" | |
506 font-size="14pt" text-align="center" font-weight="bold" | |
507 font-family="monospace"> | |
508 ibm.com/developerWorks | |
509 </fo:block> | |
510 | |
511 <!-- ============================================ | |
512 Now we call the template to build the table | |
513 of contents. | |
514 =============================================== --> | |
515 | |
516 <xsl:call-template name="toc"/> | |
517 | |
518 <!-- ============================================ | |
519 This one line of code processes everything in | |
520 the body of the document. The template that | |
521 processes the <body> element in turn processes | |
522 everything that's inside it. | |
523 =============================================== --> | |
524 | |
525 <xsl:apply-templates select="*|text()"/> | |
526 | |
527 <!-- ============================================ | |
528 We put an ID at the end of the document so we | |
529 can do "Page x of y" numbering. | |
530 =============================================== --> | |
531 <fo:block id="TheVeryLastPage" font-size="0pt" | |
532 line-height="0pt" space-after="0pt"/> | |
533 | |
534 </fo:flow> | |
535 </xsl:template> | |
536 | |
537 <!-- ============================================ | |
538 We handle a break element by inserting an | |
539 empty <fo:block>. | |
540 =============================================== --> | |
541 | |
542 <xsl:template match="br"> | |
543 <fo:block> </fo:block> | |
544 </xsl:template> | |
545 | |
546 <!-- ============================================ | |
547 We're handling <center> as a block element; if | |
548 you use it, it creates a new paragraph that's | |
549 centered on the page. | |
550 =============================================== --> | |
551 | |
552 <xsl:template match="center"> | |
553 <fo:block text-align="center"> | |
554 <xsl:apply-templates select="*|text()"/> | |
555 </fo:block> | |
556 </xsl:template> | |
557 | |
558 <!-- ============================================ | |
559 The <cite> element is rendered in italics, | |
560 unless it's inside an italic (<i>) element. | |
561 We use the parent axis to check this. | |
562 =============================================== --> | |
563 | |
564 <xsl:template match="cite"> | |
565 <xsl:choose> | |
566 <xsl:when test="parent::i"> | |
567 <fo:inline font-style="normal"> | |
568 <xsl:apply-templates select="*|text()"/> | |
569 </fo:inline> | |
570 </xsl:when> | |
571 <xsl:otherwise> | |
572 <fo:inline font-style="italic"> | |
573 <xsl:apply-templates select="*|text()"/> | |
574 </fo:inline> | |
575 </xsl:otherwise> | |
576 </xsl:choose> | |
577 </xsl:template> | |
578 | |
579 <!-- ============================================ | |
580 We render <code> inline in a monospaced font. | |
581 =============================================== --> | |
582 | |
583 <xsl:template match="code"> | |
584 <fo:inline font-family="monospace"> | |
585 <xsl:apply-templates select="*|text()"/> | |
586 </fo:inline> | |
587 </xsl:template> | |
588 | |
589 <!-- ============================================ | |
590 We don't do anything with the <dl> element, we | |
591 just handle the elements it contains. Notice | |
592 that we're ignoring any text that appears | |
593 in the <dl> itself; I'm not sure if that's | |
594 the right call. | |
595 =============================================== --> | |
596 | |
597 <xsl:template match="dl"> | |
598 <xsl:apply-templates select="*"/> | |
599 </xsl:template> | |
600 | |
601 <!-- ============================================ | |
602 A definition term is rendered in bold. We | |
603 specify keep-with-next here, although it doesn't | |
604 always work with FOP. | |
605 =============================================== --> | |
606 | |
607 <xsl:template match="dt"> | |
608 <fo:block font-weight="bold" space-after="2pt" | |
609 keep-with-next="always"> | |
610 <xsl:apply-templates select="*|text()"/> | |
611 </fo:block> | |
612 </xsl:template> | |
613 | |
614 <!-- ============================================ | |
615 We handle each <dd> element as an indented block | |
616 beneath the defined term. If the following | |
617 element is another <dd>, that means it's another | |
618 definition for the same term. In that case, | |
619 we don't put as much vertical space after the | |
620 block. | |
621 =============================================== --> | |
622 | |
623 <xsl:template match="dd"> | |
624 <fo:block start-indent="1cm"> | |
625 <xsl:attribute name="space-after"> | |
626 <xsl:choose> | |
627 <xsl:when test="name(following::*[1]) = 'dd'"> | |
628 <xsl:text>3pt</xsl:text> | |
629 </xsl:when> | |
630 <xsl:otherwise> | |
631 <xsl:text>12pt</xsl:text> | |
632 </xsl:otherwise> | |
633 </xsl:choose> | |
634 </xsl:attribute> | |
635 <xsl:apply-templates select="*|text()"/> | |
636 </fo:block> | |
637 </xsl:template> | |
638 | |
639 <!-- ============================================ | |
640 The HTML <em> element is typically rendered in | |
641 italics. | |
642 =============================================== --> | |
643 | |
644 <xsl:template match="em"> | |
645 <fo:inline font-style="italic"> | |
646 <xsl:apply-templates select="*|text()"/> | |
647 </fo:inline> | |
648 </xsl:template> | |
649 | |
650 <!-- ============================================ | |
651 For the <font> element, we handle the color, | |
652 face, and size attributes. Color will work if | |
653 it's one of the twelve colors supported by XSL-FO | |
654 or it's a hex value like x0033ff. (In other words, | |
655 if you tell FOP to set the color to PapayaWhip, | |
656 you're out of luck.) The face attribute will | |
657 work if FOP supports it. (There are ways to add | |
658 fonts to FOP, see the FOP documentation for more | |
659 info.) Size is supported for values like | |
660 size="14pt", size="3", and size="+3". | |
661 =============================================== --> | |
662 | |
663 <xsl:template match="font"> | |
664 <xsl:variable name="color"> | |
665 <xsl:choose> | |
666 <xsl:when test="@color"> | |
667 <xsl:value-of select="@color"/> | |
668 </xsl:when> | |
669 <xsl:otherwise> | |
670 <xsl:text>black</xsl:text> | |
671 </xsl:otherwise> | |
672 </xsl:choose> | |
673 </xsl:variable> | |
674 <xsl:variable name="face"> | |
675 <xsl:choose> | |
676 <xsl:when test="@face"> | |
677 <xsl:value-of select="@face"/> | |
678 </xsl:when> | |
679 <xsl:otherwise> | |
680 <xsl:text>sans-serif</xsl:text> | |
681 </xsl:otherwise> | |
682 </xsl:choose> | |
683 </xsl:variable> | |
684 <xsl:variable name="size"> | |
685 <xsl:choose> | |
686 <xsl:when test="@size"> | |
687 <xsl:choose> | |
688 <xsl:when test="contains(@size, 'pt')"> | |
689 <xsl:text>@size</xsl:text> | |
690 </xsl:when> | |
691 <xsl:when test="@size = '+1'"> | |
692 <xsl:text>110%</xsl:text> | |
693 </xsl:when> | |
694 <xsl:when test="@size = '+2'"> | |
695 <xsl:text>120%</xsl:text> | |
696 </xsl:when> | |
697 <xsl:when test="@size = '+3'"> | |
698 <xsl:text>130%</xsl:text> | |
699 </xsl:when> | |
700 <xsl:when test="@size = '+4'"> | |
701 <xsl:text>140%</xsl:text> | |
702 </xsl:when> | |
703 <xsl:when test="@size = '+5'"> | |
704 <xsl:text>150%</xsl:text> | |
705 </xsl:when> | |
706 <xsl:when test="@size = '+6'"> | |
707 <xsl:text>175%</xsl:text> | |
708 </xsl:when> | |
709 <xsl:when test="@size = '+7'"> | |
710 <xsl:text>200%</xsl:text> | |
711 </xsl:when> | |
712 <xsl:when test="@size = '-1'"> | |
713 <xsl:text>90%</xsl:text> | |
714 </xsl:when> | |
715 <xsl:when test="@size = '-2'"> | |
716 <xsl:text>80%</xsl:text> | |
717 </xsl:when> | |
718 <xsl:when test="@size = '-3'"> | |
719 <xsl:text>70%</xsl:text> | |
720 </xsl:when> | |
721 <xsl:when test="@size = '-4'"> | |
722 <xsl:text>60%</xsl:text> | |
723 </xsl:when> | |
724 <xsl:when test="@size = '-5'"> | |
725 <xsl:text>50%</xsl:text> | |
726 </xsl:when> | |
727 <xsl:when test="@size = '-6'"> | |
728 <xsl:text>40%</xsl:text> | |
729 </xsl:when> | |
730 <xsl:when test="@size = '-7'"> | |
731 <xsl:text>30%</xsl:text> | |
732 </xsl:when> | |
733 <xsl:when test="@size = '1'"> | |
734 <xsl:text>8pt</xsl:text> | |
735 </xsl:when> | |
736 <xsl:when test="@size = '2'"> | |
737 <xsl:text>10pt</xsl:text> | |
738 </xsl:when> | |
739 <xsl:when test="@size = '3'"> | |
740 <xsl:text>12pt</xsl:text> | |
741 </xsl:when> | |
742 <xsl:when test="@size = '4'"> | |
743 <xsl:text>14pt</xsl:text> | |
744 </xsl:when> | |
745 <xsl:when test="@size = '5'"> | |
746 <xsl:text>18pt</xsl:text> | |
747 </xsl:when> | |
748 <xsl:when test="@size = '6'"> | |
749 <xsl:text>24pt</xsl:text> | |
750 </xsl:when> | |
751 <xsl:when test="@size = '7'"> | |
752 <xsl:text>36pt</xsl:text> | |
753 </xsl:when> | |
754 <xsl:otherwise> | |
755 <xsl:text>12pt</xsl:text> | |
756 </xsl:otherwise> | |
757 </xsl:choose> | |
758 </xsl:when> | |
759 <xsl:otherwise> | |
760 <xsl:text>12pt</xsl:text> | |
761 </xsl:otherwise> | |
762 </xsl:choose> | |
763 </xsl:variable> | |
764 <fo:inline font-size="{$size}" font-family="{$face}" | |
765 color="{$color}"> | |
766 <xsl:apply-templates select="*|text()"/> | |
767 </fo:inline> | |
768 </xsl:template> | |
769 | |
770 <!-- ============================================ | |
771 We render the <h1> by putting a horizontal rule | |
772 and a page break before it. We also process | |
773 the id attribute; if the <h1> tag has one, we | |
774 use it. If not, we see if the preceding element | |
775 is a named anchor (<a name="x"/>). If there is | |
776 a named anchor before the <h1>, we use the name | |
777 of the anchor point as the id. | |
778 =============================================== --> | |
779 | |
780 <xsl:template match="h1"> | |
781 <fo:block break-before="page"> | |
782 <fo:leader leader-pattern="rule"/> | |
783 </fo:block> | |
784 <fo:block font-size="28pt" line-height="32pt" | |
785 keep-with-next="always" | |
786 space-after="22pt" font-family="serif"> | |
787 <xsl:attribute name="id"> | |
788 <xsl:choose> | |
789 <xsl:when test="@id"> | |
790 <xsl:value-of select="@id"/> | |
791 </xsl:when> | |
792 <xsl:when test="name(preceding-sibling::*[1]) = 'a' and | |
793 preceding-sibling::*[1][@name]"> | |
794 <xsl:value-of select="preceding-sibling::*[1]/@name"/> | |
795 </xsl:when> | |
796 <xsl:otherwise> | |
797 <xsl:value-of select="generate-id()"/> | |
798 </xsl:otherwise> | |
799 </xsl:choose> | |
800 </xsl:attribute> | |
801 <xsl:apply-templates select="*|text()"/> | |
802 </fo:block> | |
803 </xsl:template> | |
804 | |
805 <!-- ============================================ | |
806 <h2> is in a slightly smaller font than an <h1>, | |
807 and it doesn't have a page break or a line. | |
808 =============================================== --> | |
809 | |
810 <xsl:template match="h2"> | |
811 <fo:block font-size="24pt" line-height="28pt" | |
812 keep-with-next="always" space-after="18pt" | |
813 font-family="serif"> | |
814 <xsl:attribute name="id"> | |
815 <xsl:choose> | |
816 <xsl:when test="@id"> | |
817 <xsl:value-of select="@id"/> | |
818 </xsl:when> | |
819 <xsl:otherwise> | |
820 <xsl:value-of select="generate-id()"/> | |
821 </xsl:otherwise> | |
822 </xsl:choose> | |
823 </xsl:attribute> | |
824 <xsl:apply-templates select="*|text()"/> | |
825 </fo:block> | |
826 </xsl:template> | |
827 | |
828 <!-- ============================================ | |
829 <h3> is slightly smaller than <h2>. | |
830 =============================================== --> | |
831 | |
832 <xsl:template match="h3"> | |
833 <fo:block font-size="21pt" line-height="24pt" | |
834 keep-with-next="always" space-after="14pt" | |
835 font-family="serif"> | |
836 <xsl:attribute name="id"> | |
837 <xsl:choose> | |
838 <xsl:when test="@id"> | |
839 <xsl:value-of select="@id"/> | |
840 </xsl:when> | |
841 <xsl:otherwise> | |
842 <xsl:value-of select="generate-id()"/> | |
843 </xsl:otherwise> | |
844 </xsl:choose> | |
845 </xsl:attribute> | |
846 <xsl:apply-templates select="*|text()"/> | |
847 </fo:block> | |
848 </xsl:template> | |
849 | |
850 <!-- ============================================ | |
851 <h4> is smaller than <h3>. For the bookmarks | |
852 and table of contents, <h4> is the lowest level | |
853 we include. | |
854 =============================================== --> | |
855 | |
856 <xsl:template match="h4"> | |
857 <fo:block font-size="18pt" line-height="21pt" | |
858 keep-with-next="always" space-after="12pt" | |
859 font-family="serif"> | |
860 <xsl:attribute name="id"> | |
861 <xsl:choose> | |
862 <xsl:when test="@id"> | |
863 <xsl:value-of select="@id"/> | |
864 </xsl:when> | |
865 <xsl:otherwise> | |
866 <xsl:value-of select="generate-id()"/> | |
867 </xsl:otherwise> | |
868 </xsl:choose> | |
869 </xsl:attribute> | |
870 <xsl:apply-templates select="*|text()"/> | |
871 </fo:block> | |
872 </xsl:template> | |
873 | |
874 <!-- ============================================ | |
875 <h5> is pretty small, and is underlined to | |
876 help it stand out. | |
877 =============================================== --> | |
878 | |
879 <xsl:template match="h5"> | |
880 <fo:block font-size="16pt" line-height="19pt" | |
881 keep-with-next="always" space-after="12pt" | |
882 font-family="serif" text-decoration="underline"> | |
883 <xsl:attribute name="id"> | |
884 <xsl:choose> | |
885 <xsl:when test="@id"> | |
886 <xsl:value-of select="@id"/> | |
887 </xsl:when> | |
888 <xsl:otherwise> | |
889 <xsl:value-of select="generate-id()"/> | |
890 </xsl:otherwise> | |
891 </xsl:choose> | |
892 </xsl:attribute> | |
893 <xsl:apply-templates select="*|text()"/> | |
894 </fo:block> | |
895 </xsl:template> | |
896 | |
897 <!-- ============================================ | |
898 <h6> is the smallest heading of all, and is | |
899 underlined and italicized. | |
900 =============================================== --> | |
901 | |
902 <xsl:template match="h6"> | |
903 <fo:block font-size="14pt" line-height="17pt" | |
904 keep-with-next="always" space-after="12pt" | |
905 font-family="serif" font-style="italic" | |
906 text-decoration="underline"> | |
907 <xsl:attribute name="id"> | |
908 <xsl:choose> | |
909 <xsl:when test="@id"> | |
910 <xsl:value-of select="@id"/> | |
911 </xsl:when> | |
912 <xsl:otherwise> | |
913 <xsl:value-of select="generate-id()"/> | |
914 </xsl:otherwise> | |
915 </xsl:choose> | |
916 </xsl:attribute> | |
917 <xsl:apply-templates select="*|text()"/> | |
918 </fo:block> | |
919 </xsl:template> | |
920 | |
921 <!-- ============================================ | |
922 We render an <hr> with a leader. Because <hr> | |
923 is empty, we don't have to process any child | |
924 elements. | |
925 =============================================== --> | |
926 | |
927 <xsl:template match="hr"> | |
928 <fo:block> | |
929 <fo:leader leader-pattern="rule"/> | |
930 </fo:block> | |
931 </xsl:template> | |
932 | |
933 <!-- ============================================ | |
934 Italics. You can't get much simpler than that. | |
935 =============================================== --> | |
936 | |
937 <xsl:template match="i"> | |
938 <fo:inline font-style="italic"> | |
939 <xsl:apply-templates select="*|text()"/> | |
940 </fo:inline> | |
941 </xsl:template> | |
942 | |
943 <!-- ============================================ | |
944 For the <img> element, we use the src attribute | |
945 as it comes from HTML. We also check for any | |
946 width and height attributes. If those attributes | |
947 are there, we try to use them; height="300px" is | |
948 used as-is, while height="300" is converted to | |
949 the value "300px". | |
950 =============================================== --> | |
951 | |
952 <xsl:template match="img"> | |
953 <fo:block space-after="12pt"> | |
954 <fo:external-graphic src="{@src}"> | |
955 <xsl:if test="@width"> | |
956 <xsl:attribute name="width"> | |
957 <xsl:choose> | |
958 <xsl:when test="contains(@width, 'px')"> | |
959 <xsl:value-of select="@width"/> | |
960 </xsl:when> | |
961 <xsl:otherwise> | |
962 <xsl:value-of select="concat(@width, 'px')"/> | |
963 </xsl:otherwise> | |
964 </xsl:choose> | |
965 </xsl:attribute> | |
966 </xsl:if> | |
967 <xsl:if test="@height"> | |
968 <xsl:attribute name="height"> | |
969 <xsl:choose> | |
970 <xsl:when test="contains(@height, 'px')"> | |
971 <xsl:value-of select="@height"/> | |
972 </xsl:when> | |
973 <xsl:otherwise> | |
974 <xsl:value-of select="concat(@height, 'px')"/> | |
975 </xsl:otherwise> | |
976 </xsl:choose> | |
977 </xsl:attribute> | |
978 </xsl:if> | |
979 </fo:external-graphic> | |
980 </fo:block> | |
981 </xsl:template> | |
982 | |
983 <!-- ============================================ | |
984 The <kbd> element is in a slightly larger | |
985 monospaced text. | |
986 =============================================== --> | |
987 | |
988 <xsl:template match="kbd"> | |
989 <fo:inline font-family="monospace" font-size="110%"> | |
990 <xsl:apply-templates select="*|text()"/> | |
991 </fo:inline> | |
992 </xsl:template> | |
993 | |
994 <!-- ============================================ | |
995 We handle the <li> elements under the <ol> and | |
996 <ul> elements, so there's no <li> template here. | |
997 =============================================== --> | |
998 | |
999 <!-- ============================================ | |
1000 For the <nobr> element, we simply turn off the | |
1001 wrap-option. | |
1002 =============================================== --> | |
1003 | |
1004 <xsl:template match="nobr"> | |
1005 <fo:inline wrap-option="no-wrap"> | |
1006 <xsl:apply-templates select="*|text()"/> | |
1007 </fo:inline> | |
1008 </xsl:template> | |
1009 | |
1010 <!-- ============================================ | |
1011 We handle an ordered list with two complications: | |
1012 If the list appears inside another list (either | |
1013 an <ol> or <ul>), we don't put any vertical space | |
1014 after it. The other issue is that we indent the | |
1015 list according to how deeply nested the list is. | |
1016 =============================================== --> | |
1017 | |
1018 <xsl:template match="ol"> | |
1019 <fo:list-block provisional-distance-between-starts="1cm" | |
1020 provisional-label-separation="0.5cm"> | |
1021 <xsl:attribute name="space-after"> | |
1022 <xsl:choose> | |
1023 <xsl:when test="ancestor::ul or ancestor::ol"> | |
1024 <xsl:text>0pt</xsl:text> | |
1025 </xsl:when> | |
1026 <xsl:otherwise> | |
1027 <xsl:text>12pt</xsl:text> | |
1028 </xsl:otherwise> | |
1029 </xsl:choose> | |
1030 </xsl:attribute> | |
1031 <xsl:attribute name="start-indent"> | |
1032 <xsl:variable name="ancestors"> | |
1033 <xsl:choose> | |
1034 <xsl:when test="count(ancestor::ol) or count(ancestor::ul)"> | |
1035 <xsl:value-of select="1 + | |
1036 (count(ancestor::ol) + | |
1037 count(ancestor::ul)) * | |
1038 1.25"/> | |
1039 </xsl:when> | |
1040 <xsl:otherwise> | |
1041 <xsl:text>1</xsl:text> | |
1042 </xsl:otherwise> | |
1043 </xsl:choose> | |
1044 </xsl:variable> | |
1045 <xsl:value-of select="concat($ancestors, 'cm')"/> | |
1046 </xsl:attribute> | |
1047 <xsl:apply-templates select="*"/> | |
1048 </fo:list-block> | |
1049 </xsl:template> | |
1050 | |
1051 <!-- ============================================ | |
1052 When we handle items in an ordered list, we need | |
1053 to check if the list has a start attribute. If | |
1054 it does, we change the starting number accordingly. | |
1055 Once we've figured out where to start counting, | |
1056 we check the type attribute to see what format | |
1057 the numbers should use. | |
1058 =============================================== --> | |
1059 | |
1060 <xsl:template match="ol/li"> | |
1061 <fo:list-item> | |
1062 <fo:list-item-label end-indent="label-end()"> | |
1063 <fo:block> | |
1064 <xsl:variable name="value-attr"> | |
1065 <xsl:choose> | |
1066 <xsl:when test="../@start"> | |
1067 <xsl:number value="position() + ../@start - 1"/> | |
1068 </xsl:when> | |
1069 <xsl:otherwise> | |
1070 <xsl:number value="position()"/> | |
1071 </xsl:otherwise> | |
1072 </xsl:choose> | |
1073 </xsl:variable> | |
1074 <xsl:choose> | |
1075 <xsl:when test="../@type='i'"> | |
1076 <xsl:number value="$value-attr" format="i. "/> | |
1077 </xsl:when> | |
1078 <xsl:when test="../@type='I'"> | |
1079 <xsl:number value="$value-attr" format="I. "/> | |
1080 </xsl:when> | |
1081 <xsl:when test="../@type='a'"> | |
1082 <xsl:number value="$value-attr" format="a. "/> | |
1083 </xsl:when> | |
1084 <xsl:when test="../@type='A'"> | |
1085 <xsl:number value="$value-attr" format="A. "/> | |
1086 </xsl:when> | |
1087 <xsl:otherwise> | |
1088 <xsl:number value="$value-attr" format="1. "/> | |
1089 </xsl:otherwise> | |
1090 </xsl:choose> | |
1091 </fo:block> | |
1092 </fo:list-item-label> | |
1093 <fo:list-item-body start-indent="body-start()"> | |
1094 <fo:block> | |
1095 <xsl:apply-templates select="*|text()"/> | |
1096 </fo:block> | |
1097 </fo:list-item-body> | |
1098 </fo:list-item> | |
1099 </xsl:template> | |
1100 | |
1101 <!-- ============================================ | |
1102 Your basic paragraph. | |
1103 =============================================== --> | |
1104 | |
1105 <xsl:template match="p"> | |
1106 <fo:block font-size="12pt" line-height="15pt" | |
1107 space-after="12pt"> | |
1108 <xsl:apply-templates select="*|text()"/> | |
1109 </fo:block> | |
1110 </xsl:template> | |
1111 | |
1112 <!-- ============================================ | |
1113 Preformatted text is rendered in a monospaced | |
1114 font. We also have to set the wrap-option | |
1115 and white-space-collapse properties. | |
1116 =============================================== --> | |
1117 | |
1118 <xsl:template match="pre"> | |
1119 <fo:block font-family="monospace" | |
1120 white-space-collapse="false" wrap-option="no-wrap"> | |
1121 <xsl:apply-templates select="*|text()"/> | |
1122 </fo:block> | |
1123 </xsl:template> | |
1124 | |
1125 <!-- ============================================ | |
1126 Sample text is rendered in a slightly larger | |
1127 monospaced font. | |
1128 =============================================== --> | |
1129 | |
1130 <xsl:template match="samp"> | |
1131 <fo:inline font-family="monospace" font-size="110%"> | |
1132 <xsl:apply-templates select="*|text()"/> | |
1133 </fo:inline> | |
1134 </xsl:template> | |
1135 | |
1136 <!-- ============================================ | |
1137 The <small> element is rendered with a relative | |
1138 font size. That means putting one <small> | |
1139 element inside another creates really small | |
1140 text. | |
1141 =============================================== --> | |
1142 | |
1143 <xsl:template match="small"> | |
1144 <fo:inline font-size="80%"> | |
1145 <xsl:apply-templates select="*|text()"/> | |
1146 </fo:inline> | |
1147 </xsl:template> | |
1148 | |
1149 <!-- ============================================ | |
1150 For strikethrough text, we use the text-decoration | |
1151 property. | |
1152 =============================================== --> | |
1153 | |
1154 <xsl:template match="strike"> | |
1155 <fo:inline text-decoration="line-through"> | |
1156 <xsl:apply-templates select="*|text()"/> | |
1157 </fo:inline> | |
1158 </xsl:template> | |
1159 | |
1160 <!-- ============================================ | |
1161 Strongly emphasized text is simply rendered | |
1162 in bold. | |
1163 =============================================== --> | |
1164 | |
1165 <xsl:template match="strong"> | |
1166 <fo:inline font-weight="bold"> | |
1167 <xsl:apply-templates select="*|text()"/> | |
1168 </fo:inline> | |
1169 </xsl:template> | |
1170 | |
1171 <!-- ============================================ | |
1172 For subscript text, we use the vertical-align | |
1173 property and decrease the font size. | |
1174 =============================================== --> | |
1175 | |
1176 <xsl:template match="sub"> | |
1177 <fo:inline vertical-align="sub" font-size="75%"> | |
1178 <xsl:apply-templates select="*|text()"/> | |
1179 </fo:inline> | |
1180 </xsl:template> | |
1181 | |
1182 <!-- ============================================ | |
1183 Superscript text changes the vertical-align | |
1184 property also, and uses a smaller font. | |
1185 =============================================== --> | |
1186 | |
1187 <xsl:template match="sup"> | |
1188 <fo:inline vertical-align="super" font-size="75%"> | |
1189 <xsl:apply-templates select="*|text()"/> | |
1190 </fo:inline> | |
1191 </xsl:template> | |
1192 | |
1193 <!-- ============================================ | |
1194 Tables are a hassle. The main problem we have | |
1195 is converting the cols attribute into some | |
1196 number of <fo:table-column> elements. We do | |
1197 this with a named template called build-columns. | |
1198 Once we've processed the cols attribute, we | |
1199 invoke all of the templates for the children | |
1200 of this element. | |
1201 =============================================== --> | |
1202 | |
1203 <xsl:template match="table"> | |
1204 <fo:table table-layout="fixed"> | |
1205 <xsl:choose> | |
1206 <xsl:when test="@cols"> | |
1207 <xsl:call-template name="build-columns"> | |
1208 <xsl:with-param name="cols" | |
1209 select="concat(@cols, ' ')"/> | |
1210 </xsl:call-template> | |
1211 </xsl:when> | |
1212 <xsl:otherwise> | |
1213 <fo:table-column column-width="200pt"/> | |
1214 </xsl:otherwise> | |
1215 </xsl:choose> | |
1216 <fo:table-body> | |
1217 <xsl:apply-templates select="*"/> | |
1218 </fo:table-body> | |
1219 </fo:table> | |
1220 </xsl:template> | |
1221 | |
1222 <!-- ============================================ | |
1223 For a table cell, we put everything inside a | |
1224 <fo:table-cell> element. We set the padding | |
1225 property correctly, then we set the border | |
1226 style. For the border style, we look to see if | |
1227 any of the ancestor elements we care about | |
1228 specified a solid border. Next, we check for the | |
1229 rowspan, colspan, and align attributes. Notice | |
1230 that for align, we check this element, then go | |
1231 up the ancestor chain until we find the <table> | |
1232 element or we find something that specifies the | |
1233 alignment. | |
1234 =============================================== --> | |
1235 | |
1236 <xsl:template match="td"> | |
1237 <fo:table-cell | |
1238 padding-start="3pt" padding-end="3pt" | |
1239 padding-before="3pt" padding-after="3pt"> | |
1240 <xsl:if test="@colspan"> | |
1241 <xsl:attribute name="number-columns-spanned"> | |
1242 <xsl:value-of select="@colspan"/> | |
1243 </xsl:attribute> | |
1244 </xsl:if> | |
1245 <xsl:if test="@rowspan"> | |
1246 <xsl:attribute name="number-rows-spanned"> | |
1247 <xsl:value-of select="@rowspan"/> | |
1248 </xsl:attribute> | |
1249 </xsl:if> | |
1250 <xsl:if test="@border='1' or | |
1251 ancestor::tr[@border='1'] or | |
1252 ancestor::thead[@border='1'] or | |
1253 ancestor::table[@border='1']"> | |
1254 <xsl:attribute name="border-style"> | |
1255 <xsl:text>solid</xsl:text> | |
1256 </xsl:attribute> | |
1257 <xsl:attribute name="border-color"> | |
1258 <xsl:text>black</xsl:text> | |
1259 </xsl:attribute> | |
1260 <xsl:attribute name="border-width"> | |
1261 <xsl:text>1pt</xsl:text> | |
1262 </xsl:attribute> | |
1263 </xsl:if> | |
1264 <xsl:variable name="align"> | |
1265 <xsl:choose> | |
1266 <xsl:when test="@align"> | |
1267 <xsl:choose> | |
1268 <xsl:when test="@align='center'"> | |
1269 <xsl:text>center</xsl:text> | |
1270 </xsl:when> | |
1271 <xsl:when test="@align='right'"> | |
1272 <xsl:text>end</xsl:text> | |
1273 </xsl:when> | |
1274 <xsl:when test="@align='justify'"> | |
1275 <xsl:text>justify</xsl:text> | |
1276 </xsl:when> | |
1277 <xsl:otherwise> | |
1278 <xsl:text>start</xsl:text> | |
1279 </xsl:otherwise> | |
1280 </xsl:choose> | |
1281 </xsl:when> | |
1282 <xsl:when test="ancestor::tr[@align]"> | |
1283 <xsl:choose> | |
1284 <xsl:when test="ancestor::tr/@align='center'"> | |
1285 <xsl:text>center</xsl:text> | |
1286 </xsl:when> | |
1287 <xsl:when test="ancestor::tr/@align='right'"> | |
1288 <xsl:text>end</xsl:text> | |
1289 </xsl:when> | |
1290 <xsl:when test="ancestor::tr/@align='justify'"> | |
1291 <xsl:text>justify</xsl:text> | |
1292 </xsl:when> | |
1293 <xsl:otherwise> | |
1294 <xsl:text>start</xsl:text> | |
1295 </xsl:otherwise> | |
1296 </xsl:choose> | |
1297 </xsl:when> | |
1298 <xsl:when test="ancestor::thead"> | |
1299 <xsl:text>center</xsl:text> | |
1300 </xsl:when> | |
1301 <xsl:when test="ancestor::table[@align]"> | |
1302 <xsl:choose> | |
1303 <xsl:when test="ancestor::table/@align='center'"> | |
1304 <xsl:text>center</xsl:text> | |
1305 </xsl:when> | |
1306 <xsl:when test="ancestor::table/@align='right'"> | |
1307 <xsl:text>end</xsl:text> | |
1308 </xsl:when> | |
1309 <xsl:when test="ancestor::table/@align='justify'"> | |
1310 <xsl:text>justify</xsl:text> | |
1311 </xsl:when> | |
1312 <xsl:otherwise> | |
1313 <xsl:text>start</xsl:text> | |
1314 </xsl:otherwise> | |
1315 </xsl:choose> | |
1316 </xsl:when> | |
1317 <xsl:otherwise> | |
1318 <xsl:text>start</xsl:text> | |
1319 </xsl:otherwise> | |
1320 </xsl:choose> | |
1321 </xsl:variable> | |
1322 <fo:block text-align="{$align}"> | |
1323 <xsl:apply-templates select="*|text()"/> | |
1324 </fo:block> | |
1325 </fo:table-cell> | |
1326 </xsl:template> | |
1327 | |
1328 <!-- ============================================ | |
1329 The rarely-used <tfoot> element contains some | |
1330 number of <tr> elements; we just invoke the | |
1331 template for <tr> here. | |
1332 =============================================== --> | |
1333 | |
1334 <xsl:template match="tfoot"> | |
1335 <xsl:apply-templates select="tr"/> | |
1336 </xsl:template> | |
1337 | |
1338 <!-- ============================================ | |
1339 If there's a <th> element, we process it just | |
1340 like a normal <td>, except the font-weight is | |
1341 always bold and the text-align is always center. | |
1342 =============================================== --> | |
1343 | |
1344 <xsl:template match="th"> | |
1345 <fo:table-cell | |
1346 padding-start="3pt" padding-end="3pt" | |
1347 padding-before="3pt" padding-after="3pt"> | |
1348 <xsl:if test="@border='1' or | |
1349 ancestor::tr[@border='1'] or | |
1350 ancestor::table[@border='1']"> | |
1351 <xsl:attribute name="border-style"> | |
1352 <xsl:text>solid</xsl:text> | |
1353 </xsl:attribute> | |
1354 <xsl:attribute name="border-color"> | |
1355 <xsl:text>black</xsl:text> | |
1356 </xsl:attribute> | |
1357 <xsl:attribute name="border-width"> | |
1358 <xsl:text>1pt</xsl:text> | |
1359 </xsl:attribute> | |
1360 </xsl:if> | |
1361 <fo:block font-weight="bold" text-align="center"> | |
1362 <xsl:apply-templates select="*|text()"/> | |
1363 </fo:block> | |
1364 </fo:table-cell> | |
1365 </xsl:template> | |
1366 | |
1367 <!-- ============================================ | |
1368 Just like <tfoot>, the rarely-used <thead> element | |
1369 contains some number of table rows. We just | |
1370 invoke the template for <tr> here. | |
1371 =============================================== --> | |
1372 | |
1373 <xsl:template match="thead"> | |
1374 <xsl:apply-templates select="tr"/> | |
1375 </xsl:template> | |
1376 | |
1377 <!-- ============================================ | |
1378 The title of the document is rendered in a large | |
1379 bold font, centered on the page. This is the | |
1380 <title> element in the <head> in <html>. | |
1381 =============================================== --> | |
1382 | |
1383 <xsl:template match="title"> | |
1384 <fo:block space-after="18pt" line-height="27pt" | |
1385 font-size="24pt" font-weight="bold" text-align="center"> | |
1386 <xsl:apply-templates select="*|text()"/> | |
1387 </fo:block> | |
1388 </xsl:template> | |
1389 | |
1390 <!-- ============================================ | |
1391 For an HTML table row, we create an XSL-FO table | |
1392 row, then invoke the templates for everything | |
1393 inside it. | |
1394 =============================================== --> | |
1395 | |
1396 <xsl:template match="tr"> | |
1397 <fo:table-row> | |
1398 <xsl:apply-templates select="*|text()"/> | |
1399 </fo:table-row> | |
1400 </xsl:template> | |
1401 | |
1402 <!-- ============================================ | |
1403 Teletype text is rendered in a monospaced font. | |
1404 =============================================== --> | |
1405 | |
1406 <xsl:template match="tt"> | |
1407 <fo:inline font-family="monospace"> | |
1408 <xsl:apply-templates select="*|text()"/> | |
1409 </fo:inline> | |
1410 </xsl:template> | |
1411 | |
1412 <!-- ============================================ | |
1413 For underlined text, we use the text-decoration | |
1414 property. | |
1415 =============================================== --> | |
1416 | |
1417 <xsl:template match="u"> | |
1418 <fo:inline text-decoration="underline"> | |
1419 <xsl:apply-templates select="*|text()"/> | |
1420 </fo:inline> | |
1421 </xsl:template> | |
1422 | |
1423 <!-- ============================================ | |
1424 The unordered list is pretty straightforward; | |
1425 the only complication is calculating the space- | |
1426 after and start-indent properties. If this | |
1427 list is inside another list, we don't put any | |
1428 space after this one, and we calculate the | |
1429 indentation based on the nesting level of this | |
1430 list. | |
1431 =============================================== --> | |
1432 | |
1433 <xsl:template match="ul"> | |
1434 <fo:list-block provisional-distance-between-starts="1cm" | |
1435 provisional-label-separation="0.5cm"> | |
1436 <xsl:attribute name="space-after"> | |
1437 <xsl:choose> | |
1438 <xsl:when test="ancestor::ul or ancestor::ol"> | |
1439 <xsl:text>0pt</xsl:text> | |
1440 </xsl:when> | |
1441 <xsl:otherwise> | |
1442 <xsl:text>12pt</xsl:text> | |
1443 </xsl:otherwise> | |
1444 </xsl:choose> | |
1445 </xsl:attribute> | |
1446 <xsl:attribute name="start-indent"> | |
1447 <xsl:variable name="ancestors"> | |
1448 <xsl:choose> | |
1449 <xsl:when test="count(ancestor::ol) or count(ancestor::ul)"> | |
1450 <xsl:value-of select="1 + | |
1451 (count(ancestor::ol) + | |
1452 count(ancestor::ul)) * | |
1453 1.25"/> | |
1454 </xsl:when> | |
1455 <xsl:otherwise> | |
1456 <xsl:text>1</xsl:text> | |
1457 </xsl:otherwise> | |
1458 </xsl:choose> | |
1459 </xsl:variable> | |
1460 <xsl:value-of select="concat($ancestors, 'cm')"/> | |
1461 </xsl:attribute> | |
1462 <xsl:apply-templates select="*"/> | |
1463 </fo:list-block> | |
1464 </xsl:template> | |
1465 | |
1466 <!-- ============================================ | |
1467 List items inside unordered lists are easy; we | |
1468 just have to use the correct Unicode character | |
1469 for the bullet. | |
1470 =============================================== --> | |
1471 | |
1472 <xsl:template match="ul/li"> | |
1473 <fo:list-item> | |
1474 <fo:list-item-label end-indent="label-end()"> | |
1475 <fo:block>•</fo:block> | |
1476 </fo:list-item-label> | |
1477 <fo:list-item-body start-indent="body-start()"> | |
1478 <fo:block> | |
1479 <xsl:apply-templates select="*|text()"/> | |
1480 </fo:block> | |
1481 </fo:list-item-body> | |
1482 </fo:list-item> | |
1483 </xsl:template> | |
1484 | |
1485 <!-- ============================================ | |
1486 The <var> element is rendered in italics. | |
1487 =============================================== --> | |
1488 | |
1489 <xsl:template match="var"> | |
1490 <fo:inline font-style="italic"> | |
1491 <xsl:apply-templates select="*|text()"/> | |
1492 </fo:inline> | |
1493 </xsl:template> | |
1494 | |
1495 <!-- ============================================ | |
1496 Named templates | |
1497 =============================================== --> | |
1498 | |
1499 <!-- ============================================ | |
1500 This template creates the table of contents. | |
1501 It indents each entry according to the heading | |
1502 level (<h1> isn't indented, <h2> is indented | |
1503 1 cm, etc.). We insert the title of each | |
1504 section as a link, put a leader of dots, then | |
1505 the page number. Notice that we generate an | |
1506 id for the heading if it doesn't have one | |
1507 already; this is done with the XSLT generate-id() | |
1508 function. | |
1509 =============================================== --> | |
1510 | |
1511 <xsl:template name="toc"> | |
1512 <fo:block> | |
1513 <fo:leader leader-pattern="rule" space-after="18pt"/> | |
1514 </fo:block> | |
1515 <fo:block space-after="12pt" id="TableOfContents" | |
1516 line-height="21pt" font-size="18pt" text-align="start"> | |
1517 Table of Contents | |
1518 </fo:block> | |
1519 <fo:block line-height="11pt" font-size="8pt" | |
1520 space-after="6pt"> | |
1521 If you're viewing this document online, you can | |
1522 click any of the topics below to link directly to | |
1523 that section. | |
1524 </fo:block> | |
1525 <xsl:for-each select="/html/body//h1 | | |
1526 /html/body//h2 | | |
1527 /html/body//h3 | | |
1528 /html/body//h4"> | |
1529 <fo:block text-align-last="justify" line-height="17pt" | |
1530 font-size="14pt" space-after="3pt" text-align="start" | |
1531 text-indent="-1cm"> | |
1532 <xsl:attribute name="start-indent"> | |
1533 <xsl:choose> | |
1534 <xsl:when test="name() = 'h1'"> | |
1535 <xsl:text>1cm</xsl:text> | |
1536 </xsl:when> | |
1537 <xsl:when test="name() = 'h2'"> | |
1538 <xsl:text>1.5cm</xsl:text> | |
1539 </xsl:when> | |
1540 <xsl:when test="name() = 'h3'"> | |
1541 <xsl:text>2cm</xsl:text> | |
1542 </xsl:when> | |
1543 <xsl:when test="name() = 'h4'"> | |
1544 <xsl:text>2.5cm</xsl:text> | |
1545 </xsl:when> | |
1546 </xsl:choose> | |
1547 </xsl:attribute> | |
1548 <fo:basic-link color="blue"> | |
1549 <xsl:attribute name="internal-destination"> | |
1550 <xsl:choose> | |
1551 <xsl:when test="@id"> | |
1552 <xsl:value-of select="@id"/> | |
1553 </xsl:when> | |
1554 <xsl:when test="name(preceding-sibling::*[1]) = 'a' and | |
1555 preceding-sibling::*[1][@name]"> | |
1556 <xsl:value-of select="preceding-sibling::*[1]/@name"/> | |
1557 </xsl:when> | |
1558 <xsl:otherwise> | |
1559 <xsl:value-of select="generate-id()"/> | |
1560 </xsl:otherwise> | |
1561 </xsl:choose> | |
1562 </xsl:attribute> | |
1563 <xsl:apply-templates select="*|text()"/> | |
1564 </fo:basic-link> | |
1565 <fo:leader leader-pattern="dots" | |
1566 leader-pattern-width="5pt"/> | |
1567 <fo:page-number-citation> | |
1568 <xsl:attribute name="ref-id"> | |
1569 <xsl:choose> | |
1570 <xsl:when test="@id"> | |
1571 <xsl:value-of select="@id"/> | |
1572 </xsl:when> | |
1573 <xsl:when test="name(preceding-sibling::*[1]) = 'a' and | |
1574 preceding-sibling::*[1][@name]"> | |
1575 <xsl:value-of select="preceding-sibling::*[1]/@name"/> | |
1576 </xsl:when> | |
1577 <xsl:otherwise> | |
1578 <xsl:value-of select="generate-id()"/> | |
1579 </xsl:otherwise> | |
1580 </xsl:choose> | |
1581 </xsl:attribute> | |
1582 </fo:page-number-citation> | |
1583 </fo:block> | |
1584 </xsl:for-each> | |
1585 </xsl:template> | |
1586 | |
1587 <!-- ============================================ | |
1588 This complicated template creates the PDF bookmarks | |
1589 supported by FOP. For each <h1> element, it | |
1590 creates a bookmark for that element, then it | |
1591 looks for all of the <h2> elements beneath it. | |
1592 For each <h2>, it looks for all the <h3> | |
1593 elements beneath it, etc. We use generate-id() | |
1594 extensively so we can determine whether a given | |
1595 <h1> or <h2> or <h3> is one we've seen before. | |
1596 The end result of all this hard work is a set of | |
1597 hierarchical bookmarks that are nested within each | |
1598 other. | |
1599 =============================================== --> | |
1600 | |
1601 <xsl:template name="generate-bookmarks"> | |
1602 <fox:outline internal-destination="TableOfContents"> | |
1603 <fox:label>Table of Contents</fox:label> | |
1604 </fox:outline> | |
1605 <xsl:for-each select="/html/body//h1"> | |
1606 <xsl:variable name="current-h1" select="generate-id()"/> | |
1607 <fox:outline> | |
1608 <xsl:attribute name="internal-destination"> | |
1609 <xsl:choose> | |
1610 <xsl:when test="@id"> | |
1611 <xsl:value-of select="@id"/> | |
1612 </xsl:when> | |
1613 <xsl:when test="name(preceding-sibling::*[1]) = 'a' and | |
1614 preceding-sibling::*[1][@name]"> | |
1615 <xsl:value-of select="preceding-sibling::*[1]/@name"/> | |
1616 </xsl:when> | |
1617 <xsl:otherwise> | |
1618 <xsl:value-of select="generate-id()"/> | |
1619 </xsl:otherwise> | |
1620 </xsl:choose> | |
1621 </xsl:attribute> | |
1622 <fox:label> | |
1623 <xsl:value-of select="."/> | |
1624 </fox:label> | |
1625 <xsl:for-each select="following-sibling::h2"> | |
1626 <xsl:variable name="current-h2" select="generate-id()"/> | |
1627 <xsl:if | |
1628 test="generate-id(preceding-sibling::h1[1]) = $current-h1"> | |
1629 <fox:outline> | |
1630 <xsl:attribute name="internal-destination"> | |
1631 <xsl:choose> | |
1632 <xsl:when test="@id"> | |
1633 <xsl:value-of select="@id"/> | |
1634 </xsl:when> | |
1635 <xsl:otherwise> | |
1636 <xsl:value-of select="$current-h2"/> | |
1637 </xsl:otherwise> | |
1638 </xsl:choose> | |
1639 </xsl:attribute> | |
1640 <fox:label> | |
1641 <xsl:value-of select="."/> | |
1642 </fox:label> | |
1643 <xsl:for-each select="following-sibling::h3"> | |
1644 <xsl:variable name="current-h3" select="generate-id()"/> | |
1645 <xsl:if | |
1646 test="generate-id(preceding-sibling::h2[1]) = $current-h2"> | |
1647 <fox:outline> | |
1648 <xsl:attribute name="internal-destination"> | |
1649 <xsl:choose> | |
1650 <xsl:when test="@id"> | |
1651 <xsl:value-of select="@id"/> | |
1652 </xsl:when> | |
1653 <xsl:otherwise> | |
1654 <xsl:value-of select="$current-h2"/> | |
1655 </xsl:otherwise> | |
1656 </xsl:choose> | |
1657 </xsl:attribute> | |
1658 <fox:label> | |
1659 <xsl:value-of select="."/> | |
1660 </fox:label> | |
1661 <xsl:for-each select="following-sibling::h4"> | |
1662 <xsl:if | |
1663 test="generate-id(preceding-sibling::h3[1]) = $current-h3"> | |
1664 <fox:outline> | |
1665 <xsl:attribute name="internal-destination"> | |
1666 <xsl:choose> | |
1667 <xsl:when test="@id"> | |
1668 <xsl:value-of select="@id"/> | |
1669 </xsl:when> | |
1670 <xsl:otherwise> | |
1671 <xsl:value-of select="$current-h3"/> | |
1672 </xsl:otherwise> | |
1673 </xsl:choose> | |
1674 </xsl:attribute> | |
1675 <fox:label> | |
1676 <xsl:value-of select="."/> | |
1677 </fox:label> | |
1678 </fox:outline> | |
1679 </xsl:if> | |
1680 </xsl:for-each> | |
1681 </fox:outline> | |
1682 </xsl:if> | |
1683 </xsl:for-each> | |
1684 </fox:outline> | |
1685 </xsl:if> | |
1686 </xsl:for-each> | |
1687 </fox:outline> | |
1688 </xsl:for-each> | |
1689 </xsl:template> | |
1690 | |
1691 <!-- ============================================ | |
1692 This template generates an <fo:table-column> | |
1693 element for each token in the cols attribute of | |
1694 the HTML <table> tag. The template processes | |
1695 the first token, then invokes itself with the | |
1696 rest of the string. | |
1697 =============================================== --> | |
1698 | |
1699 <xsl:template name="build-columns"> | |
1700 <xsl:param name="cols"/> | |
1701 | |
1702 <xsl:if test="string-length(normalize-space($cols))"> | |
1703 <xsl:variable name="next-col"> | |
1704 <xsl:value-of select="substring-before($cols, ' ')"/> | |
1705 </xsl:variable> | |
1706 <xsl:variable name="remaining-cols"> | |
1707 <xsl:value-of select="substring-after($cols, ' ')"/> | |
1708 </xsl:variable> | |
1709 <xsl:choose> | |
1710 <xsl:when test="contains($next-col, 'pt')"> | |
1711 <fo:table-column column-width="{$next-col}"/> | |
1712 </xsl:when> | |
1713 <xsl:when test="number($next-col) > 0"> | |
1714 <fo:table-column column-width="{concat($next-col, 'pt')}"/> | |
1715 </xsl:when> | |
1716 <xsl:otherwise> | |
1717 <fo:table-column column-width="50pt"/> | |
1718 </xsl:otherwise> | |
1719 </xsl:choose> | |
1720 | |
1721 <xsl:call-template name="build-columns"> | |
1722 <xsl:with-param name="cols" select="concat($remaining-cols, ' ')"/> | |
1723 </xsl:call-template> | |
1724 </xsl:if> | |
1725 </xsl:template> | |
1726 | |
1727 </xsl:stylesheet> |