fix handling empty xml files
[librarian.git] / librarian / xslt / book2html.xslt
1 <?xml version="1.0" encoding="utf-8"?>
2 <!--
3  
4    This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
5    Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
6   
7 -->
8 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
9     xmlns:wl="http://wolnelektury.pl/functions" >
10
11 <xsl:output encoding="utf-8" indent="yes" omit-xml-declaration = "yes" version="2.0" />
12 <xsl:template match="utwor">
13     <!-- <html>
14         <head>
15             <title>Książka z serwisu WolneLektury.pl</title>
16             <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
17         </head>
18         <style>
19             body {
20                 font-size: 16px;
21                 font: Georgia, "Times New Roman", serif;
22                 line-height: 1.5em;
23                 margin: 0;
24             }
25
26             a {
27                 color: blue;
28                 text-decoration: none;
29             }
30
31             #book-text {
32                 margin: 3em;
33                 max-width: 36em;
34             }
35
36             /* ================================== */
37             /* = Header with logo and menu      = */
38             /* ================================== */
39             #header {
40                 margin: 3.4em 0 0 1.4em;
41             }
42
43             img {
44                 border: none;
45             }
46
47
48             #menu {
49                 position: fixed;
50                 left: 0em;
51                 top: 0em;
52                 width: 100%;
53                 height: 1.5em;
54                 background: #333;
55                 color: #FFF;
56                 opacity: 0.9;
57             }
58
59             #menu ul {
60                 list-style: none;
61                 padding: 0;
62                 margin: 0;
63             }
64
65             #menu li a {
66                 display: block;
67                 float: left;
68                 width: 7.5em;
69                 height: 1.5em;
70                 margin-left: 0.5em;
71                 text-align: center;
72                 color: #FFF;
73             }
74
75             #menu li a:hover, #menu li a:active {
76                 color: #000;
77                 background: #FFF url(/media/img/arrow-down.png) no-repeat center right;
78             }
79
80             #menu li a.selected {
81                 color: #000;
82                 background: #FFF url(/media/img/arrow-up.png) no-repeat center right;
83             }
84
85             #toc, #themes {
86                 position: fixed;
87                 left: 0em;
88                 top: 1.5em;
89                 width: 37em;
90                 padding: 1.5em;
91                 background: #FFF;
92                 border-bottom: 0.25em solid #DDD;
93                 border-right: 0.25em solid #DDD;
94                 display: none;
95                 height: 16em;
96                 overflow-x: hidden;
97                 overflow-y: auto;
98                 opacity: 0.9;
99             }
100
101             #toc ol, #themes ol {
102                 list-style: none;
103                 padding: 0;
104                 margin: 0;
105             }
106
107             #toc ol li {
108                 font-weight: bold;
109             }
110
111             #toc ol ol {
112                 padding: 0 0 1.5em 1.5em;
113                 margin: 0;
114             }
115
116             #toc ol ol li {
117                 font-weight: normal;
118             }
119
120             #toc h2 {
121                 display: none;
122             }
123
124             #toc .anchor {
125                 float: none;
126                 margin: 0;
127                 color: blue;
128                 font-size: 16px;
129                 position: inherit;
130             }
131
132             /* =================================================== */
133             /* = Common elements: headings, paragraphs and lines = */
134             /* =================================================== */
135             h1 {
136                 font-size: 3em;
137                 margin: 1.5em 0;
138                 text-align: center;
139                 line-height: 1.5em;
140                 font-weight: bold;
141             }
142
143             h2 {
144                 font-size: 2em;
145                 margin: 1.5em 0 0;
146                 font-weight: bold;
147                 line-height: 1.5em;
148             }
149
150             h3 {
151                 font-size: 1.5em;
152                 margin: 1.5em 0 0;
153                 font-weight: normal;
154                 line-height: 1.5em;
155             }
156
157             h4 {
158                 font-size: 1em;
159                 margin: 1.5em 0 0;
160                 line-height: 1.5em;
161             }
162
163             p {
164                 margin: 0;
165             }
166
167             /* ======================== */
168             /* = Footnotes and themes = */
169             /* ======================== */
170             .theme-begin {
171                 border-left: 0.1em solid #DDDDDD;
172                 color: #777;
173                 padding: 0 0.5em;
174                 width: 7.5em;
175                 font-style: normal;
176                 font-weight: normal;
177                 font-size: 16px;
178                 float: right;
179                 margin-right: -9.5em;
180                 clear: both;
181                 left: 40em;
182                 line-height: 1.5em;
183                 text-align: left;
184             }
185
186             .annotation {
187                 font-style: normal;
188                 font-weight: normal;
189                 font-size: 12px;
190             }
191
192             #footnotes .annotation {
193                 display: block;
194                 float: left;
195                 width: 2.5em;
196                 clear: both;
197             }
198
199             #footnotes div {
200                 margin: 1.5em 0 0 0;
201             }
202
203             #footnotes p {
204                 margin-left: 2.5em;
205                 font-size: 0.875em;
206             }
207
208             blockquote {
209                 font-size: 0.875em;
210             }
211
212             /* ============= */
213             /* = Numbering = */
214             /* ============= */
215             .anchor {
216                 position: absolute;
217                 margin: -0.25em -0.5em;
218                 left: 1em;
219                 color: #777;
220                 font-size: 12px;
221                 width: 2em;
222                 text-align: center;
223                 padding: 0.25em 0.5em;
224                 line-height: 1.5em;
225             }
226
227             .anchor:hover, #book-text .anchor:active {
228                 color: #FFF;
229                 background-color: #CCC;
230             }
231
232             /* =================== */
233             /* = Custom elements = */
234             /* =================== */
235             span.author {
236                 font-size: 0.5em;
237                 display: block;
238                 line-height: 1.5em;
239                 margin-bottom: 0.25em;
240             }
241
242             span.collection {
243                 font-size: 0.375em;
244                 display: block;
245                 line-height: 1.5em;
246                 margin-bottom: -0.25em;
247             }
248
249             span.subtitle {
250                 font-size: 0.5em;
251                 display: block;
252                 line-height: 1.5em;
253                 margin-top: -0.25em;
254             }
255
256             div.didaskalia {
257                 font-style: italic;
258                 margin: 0.5em 0 0 1.5em;
259             }
260
261             div.kwestia {
262                 margin: 0.5em 0 0;
263             }
264
265             div.stanza {
266                 margin: 1.5em 0 0;
267             }
268
269             div.kwestia div.stanza {
270                 margin: 0;
271             }
272
273             p.paragraph {
274                 text-align: justify;
275                 margin: 1.5em 0 0;
276             }
277
278             p.motto {
279                 text-align: justify;
280                 font-style: italic;
281                 margin: 1.5em 0 0;
282             }
283
284             p.motto_podpis {
285                 font-size: 0.875em;
286                 text-align: right;
287             }
288
289             div.fragment {
290                 border-bottom: 0.1em solid #999;
291                 padding-bottom: 1.5em;
292             }
293
294             div.note p, div.dedication p, div.note p.paragraph, div.dedication p.paragraph {
295                 text-align: right;
296                 font-style: italic;
297             }
298
299             hr.spacer {
300                 height: 3em;
301                 visibility: hidden;
302             }
303
304             hr.spacer-line {
305                 margin: 1.5em 0;
306                 border: none;
307                 border-bottom: 0.1em solid #000;
308             }
309
310             p.spacer-asterisk {
311                 padding: 0;
312                 margin: 1.5em 0;
313                 text-align: center;
314             }
315
316             div.person-list ol {
317                 list-style: none;
318                 padding: 0 0 0 1.5em;
319             }
320
321             p.place-and-time {
322                 font-style: italic;
323             }
324
325             em.math, em.foreign-word, em.book-title, em.didaskalia {
326                 font-style: italic;
327             }
328
329             em.author-emphasis {
330                 letter-spacing: 0.1em;
331             }
332
333             em.person {
334                 font-style: normal;
335                 font-variant: small-caps;
336             }
337         </style>
338         <body> -->
339         <div id="book-text">
340             <xsl:apply-templates select="powiesc|opowiadanie|liryka_l|liryka_lp|dramat_wierszowany_l|dramat_wierszowany_lp|dramat_wspolczesny" />
341             <xsl:if test="count(descendant::*[self::pe or self::pa or self::pr or self::pt][not(parent::extra)])">
342                 <div id="footnotes">
343                     <h3>Przypisy</h3>
344                     <xsl:for-each select="descendant::*[self::pe or self::pa or self::pr or self::pt][not(parent::extra)]">
345                         <div>
346                             <a name="{concat('footnote-', generate-id(.))}" />
347                             <a href="{concat('#anchor-', generate-id(.))}" class="annotation">[<xsl:number value="count(preceding::*[self::pa or self::pe or self::pr or self::pt]) + 1" />]</a>
348                             <xsl:choose>
349                                 <xsl:when test="count(akap|akap_cd|strofa) = 0">
350                                     <p><xsl:apply-templates select="text()|*" mode="inline" /></p>
351                                 </xsl:when>
352                                 <xsl:otherwise>
353                                     <xsl:apply-templates select="text()|*" mode="inline" />
354                                 </xsl:otherwise>
355                             </xsl:choose>
356                         </div>
357                     </xsl:for-each>
358                 </div>
359             </xsl:if>
360         </div>
361         <!-- </body>
362     </html> -->
363 </xsl:template>
364
365
366 <!-- ============================================================================== -->
367 <!-- = MASTER TAG                                                                 = -->
368 <!-- = (can contain block tags, paragraph tags, standalone tags and special tags) = -->
369 <!-- ============================================================================== -->
370 <xsl:template match="powiesc|opowiadanie|liryka_l|liryka_lp|dramat_wierszowany_l|dramat_wierszowany_lp|dramat_wspolczesny">
371     <xsl:if test="nazwa_utworu">
372         <h1>
373             <xsl:apply-templates select="autor_utworu|dzielo_nadrzedne|nazwa_utworu|podtytul" mode="header" />
374         </h1>
375     </xsl:if>
376     <xsl:apply-templates />
377 </xsl:template>
378
379
380 <!-- ==================================================================================== -->
381 <!-- = BLOCK TAGS                                                                       = -->
382 <!-- = (can contain other block tags, paragraph tags, standalone tags and special tags) = -->
383 <!-- ==================================================================================== -->
384 <xsl:template match="nota">
385     <div class="note"><xsl:apply-templates /></div>
386 </xsl:template>
387
388 <xsl:template match="lista_osob">
389     <div class="person-list">
390         <h3><xsl:value-of select="naglowek_listy" /></h3>
391         <ol>
392             <xsl:apply-templates select="lista_osoba" />
393         </ol>
394     </div>
395 </xsl:template>
396
397 <xsl:template match="dedykacja">
398     <div class="dedication"><xsl:apply-templates /></div>
399 </xsl:template>
400
401 <xsl:template match="kwestia">
402     <div class="kwestia">
403         <xsl:apply-templates select="strofa|akap|didaskalia" />
404     </div>
405 </xsl:template>
406
407 <xsl:template match="dlugi_cytat|poezja_cyt">
408     <blockquote><xsl:apply-templates /></blockquote>
409 </xsl:template>
410
411 <xsl:template match="motto">
412     <div class="motto"><xsl:apply-templates mode="inline" /></div>
413 </xsl:template>
414
415
416 <!-- ========================================== -->
417 <!-- = PARAGRAPH TAGS                         = -->
418 <!-- = (can contain inline and special tags)  = -->
419 <!-- ========================================== -->
420 <!-- Title page -->
421 <xsl:template match="autor_utworu" mode="header">
422     <span class="author"><xsl:apply-templates mode="inline" /></span>
423 </xsl:template>
424
425 <xsl:template match="nazwa_utworu" mode="header">
426     <span class="title"><xsl:apply-templates mode="inline" /></span>
427 </xsl:template>
428
429 <xsl:template match="dzielo_nadrzedne" mode="header">
430     <span class="collection"><xsl:apply-templates mode="inline" /></span>
431 </xsl:template>
432
433 <xsl:template match="podtytul" mode="header">
434     <span class="subtitle"><xsl:apply-templates mode="inline" /></span>
435 </xsl:template>
436
437 <!-- Section headers (included in index)-->
438 <xsl:template match="naglowek_akt|naglowek_czesc|srodtytul">
439     <h2><xsl:apply-templates mode="inline" /></h2>
440 </xsl:template>
441
442 <xsl:template match="naglowek_scena|naglowek_rozdzial">
443     <h3><xsl:apply-templates mode="inline" /></h3>
444 </xsl:template>
445
446 <xsl:template match="naglowek_osoba|naglowek_podrozdzial">
447     <h4><xsl:apply-templates mode="inline" /></h4>
448 </xsl:template>
449
450 <!-- Other paragraph tags -->
451 <xsl:template match="miejsce_czas">
452     <p class="place-and-time"><xsl:apply-templates mode="inline" /></p>
453 </xsl:template>
454
455 <xsl:template match="didaskalia">
456     <div class="didaskalia"><xsl:apply-templates mode="inline" /></div>
457 </xsl:template>
458
459 <xsl:template match="lista_osoba">
460     <li><xsl:apply-templates mode="inline" /></li>
461 </xsl:template>
462
463 <xsl:template match="akap|akap_dialog|akap_cd">
464     <p class="paragraph"><xsl:apply-templates mode="inline" /></p>
465 </xsl:template>
466
467 <xsl:template match="strofa">
468     <div class="stanza">
469         <xsl:choose>
470             <xsl:when test="count(br) > 0">     
471                 <xsl:call-template name="verse">
472                     <xsl:with-param name="verse-content" select="br[1]/preceding-sibling::text() | br[1]/preceding-sibling::node()" />
473                     <xsl:with-param name="verse-type" select="br[1]/preceding-sibling::*[name() = 'wers_wciety' or name() = 'wers_akap' or name() = 'wers_cd'][1]" />
474                 </xsl:call-template>    
475                 <xsl:for-each select="br">              
476                                 <!-- Each BR tag "consumes" text after it -->
477                     <xsl:variable name="lnum" select="count(preceding-sibling::br)" />
478                     <xsl:call-template name="verse">
479                         <xsl:with-param name="verse-content" 
480                             select="following-sibling::text()[count(preceding-sibling::br) = $lnum+1] | following-sibling::node()[count(preceding-sibling::br) = $lnum+1]" />
481                         <xsl:with-param name="verse-type" select="following-sibling::*[count(preceding-sibling::br) = $lnum+1 and (name() = 'wers_wciety' or name() = 'wers_akap' or name() = 'wers_cd')][1]" />
482                     </xsl:call-template>
483                 </xsl:for-each>
484             </xsl:when>
485             <xsl:otherwise>
486                 <xsl:call-template name="verse">
487                     <xsl:with-param name="verse-content" select="text() | node()" />
488                     <xsl:with-param name="verse-type" select="wers_wciety|wers_akap|wers_cd[1]" />
489                  </xsl:call-template>           
490             </xsl:otherwise>
491         </xsl:choose>
492     </div>
493 </xsl:template>
494
495 <xsl:template name="verse">
496     <xsl:param name="verse-content" />
497     <xsl:param name="verse-type" />
498     <p class="verse">
499         <xsl:choose>
500             <xsl:when test="name($verse-type) = 'wers_akap'">
501                 <xsl:attribute name="style">padding-left: 1em</xsl:attribute>
502             </xsl:when>
503             <xsl:when test="name($verse-type) = 'wers_wciety'">
504                 <xsl:choose>
505                     <xsl:when test="$verse-content/@typ">
506                         <xsl:attribute name="style">padding-left: <xsl:value-of select="$verse-content/@typ" />em</xsl:attribute>
507                     </xsl:when>
508                     <xsl:otherwise>
509                         <xsl:attribute name="style">padding-left: 1em</xsl:attribute>
510                     </xsl:otherwise>
511                 </xsl:choose>
512             </xsl:when>
513             <xsl:when test="name($verse-type) = 'wers_cd'">
514                 <xsl:attribute name="style">padding-left: 12em</xsl:attribute>
515             </xsl:when>
516         </xsl:choose>
517         <xsl:apply-templates select="$verse-content" mode="inline" />
518     </p>
519 </xsl:template>
520
521 <xsl:template match="motto_podpis">
522     <p class="motto_podpis"><xsl:apply-templates mode="inline" /></p>
523 </xsl:template>
524
525
526 <!-- ================================================ -->
527 <!-- = INLINE TAGS                                  = -->
528 <!-- = (contain other inline tags and special tags) = -->
529 <!-- ================================================ -->
530 <!-- Annotations -->
531 <xsl:template match="pa|pe|pr|pt" mode="inline">
532     <a name="{concat('anchor-', generate-id(.))}" />
533     <a href="{concat('#footnote-', generate-id(.))}" class="annotation">[<xsl:number value="count(preceding::*[self::pa or self::pe or self::pr or self::pt]) + 1" />]</a>
534 </xsl:template>
535
536 <!-- Other inline tags -->
537 <xsl:template match="mat" mode="inline">
538     <em class="math"><xsl:apply-templates mode="inline" /></em>
539 </xsl:template>
540
541 <xsl:template match="didask_tekst" mode="inline">
542     <em class="didaskalia"><xsl:apply-templates mode="inline" /></em>
543 </xsl:template>
544
545 <xsl:template match="slowo_obce" mode="inline">
546     <em class="foreign-word"><xsl:apply-templates mode="inline" /></em>
547 </xsl:template>
548
549 <xsl:template match="tytul_dziela" mode="inline">
550     <em class="book-title">
551         <xsl:if test="@typ = '1'">„</xsl:if><xsl:apply-templates mode="inline" /><xsl:if test="@typ = '1'">”</xsl:if>
552     </em>
553 </xsl:template>
554
555 <xsl:template match="wyroznienie" mode="inline">
556     <em class="author-emphasis"><xsl:apply-templates mode="inline" /></em>
557 </xsl:template>
558
559 <xsl:template match="osoba" mode="inline">
560     <em class="person"><xsl:apply-templates mode="inline" /></em>
561 </xsl:template>
562
563
564 <!-- ============================================== -->
565 <!-- = STANDALONE TAGS                            = -->
566 <!-- = (cannot contain any other tags)            = -->
567 <!-- ============================================== -->
568 <xsl:template match="sekcja_swiatlo">
569     <hr class="spacer" />
570 </xsl:template>
571
572 <xsl:template match="sekcja_asterysk">
573     <p class="spacer-asterisk">*</p>
574 </xsl:template>
575
576 <xsl:template match="separator_linia">
577     <hr class="spacer-line" />
578 </xsl:template>
579
580
581 <!-- ================ -->
582 <!-- = SPECIAL TAGS = -->
583 <!-- ================ -->
584 <!-- Themes -->
585 <xsl:template match="begin" mode="inline">
586     <xsl:variable name="mnum" select="concat('m', substring(@id, 2))" />
587     <a name="m{substring(@id, 2)}" class="theme-begin" fid="{substring(@id, 2)}">
588         <xsl:value-of select="string(following::motyw[@id=$mnum]/text())" />
589     </a>
590 </xsl:template>
591
592 <xsl:template match="end" mode="inline">
593     <span class="theme-end" fid="{substring(@id, 2)}"> </span>
594 </xsl:template>
595
596 <xsl:template match="begin|end">
597     <xsl:apply-templates select='.' mode="inline" />
598 </xsl:template>
599
600 <xsl:template match="motyw" mode="inline" />
601
602
603 <!-- ================ -->
604 <!-- = IGNORED TAGS = -->
605 <!-- ================ -->
606 <xsl:template match="extra|uwaga" />
607 <xsl:template match="extra|uwaga" mode="inline" />
608
609
610 <!-- ======== -->
611 <!-- = TEXT = -->
612 <!-- ======== -->
613 <xsl:template match="text()" />
614 <xsl:template match="text()" mode="inline">
615     <xsl:value-of select="wl:substitute_entities(.)" />
616 </xsl:template>
617
618
619 </xsl:stylesheet>