fix handling empty xml files
[librarian.git] / librarian / xslt / normalize.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"
9     xmlns="http://nowoczesnapolska.org.pl/ML/Lektury/1.1"
10         
11     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
12     xmlns:wlf="http://wolnelektury.pl/functions"
13
14     xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
15     xmlns:dc="http://purl.org/dc/elements/1.1/"
16
17     exclude-result-prefixes="wlf xsl"
18 >
19
20     <!-- Normalization Stylsheet for Wolne Lektury XML -->
21     <xsl:output method="xml" encoding="utf-8" indent="yes" />
22      
23     <xsl:strip-space elements="rdf:RDF rdf:Description meta doc main-text strofa stanza drama-line wlml:*" />
24
25     <xsl:param name="normalize-text" select="boolean(1)" />
26
27     <!-- Main entry point -->
28     <xsl:template match="/">
29         <doc>
30             <meta>
31                 <xsl:apply-templates select="//rdf:RDF" mode="meta"/>
32             </meta>
33
34             <xsl:variable name="body" select="/utwor/*[local-name() = name()]" />
35
36             <main-text class="{name($body)}">
37                 <xsl:apply-templates select="$body/node()" />
38             </main-text>
39
40             <annotations>
41                 <xsl:apply-templates select="//pr|pt|pe|pa" mode="annotations" />              
42             </annotations>
43         </doc>
44     </xsl:template>    
45
46     <xsl:template match="strofa">
47         <xsl:element name="stanza" namespace="http://nowoczesnapolska.org.pl/ML/Lektury/1.1">
48             <!-- normalize verses -->
49             <xsl:choose>
50                 <xsl:when test="count(br) > 0">
51                     <!-- First, collect all the tags up to first BR -->
52                     <xsl:call-template name="verse">
53                         <xsl:with-param name="verse-content" select="br[1]/preceding-sibling::node()" />
54                         <xsl:with-param name="verse-type" select="br[1]/preceding-sibling::*[name() = 'wers_wciety' or name() = 'wers_akap' or name() = 'wers_cd'][1]" />
55                     </xsl:call-template>
56
57                     <!-- Collect the rest of verses -->
58                     <xsl:for-each select="br">
59                                 <!-- Each BR tag "consumes" text after it -->
60                         <xsl:variable name="lnum" select="count(preceding-sibling::br)" />
61                         <xsl:call-template name="verse">
62                             <xsl:with-param name="verse-content"
63                                 select="following-sibling::node()[count(preceding-sibling::br) = $lnum+1 and name() != 'br']" />
64                             <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]" />
65                         </xsl:call-template>
66                     </xsl:for-each>
67                 </xsl:when>
68
69                 <!-- No BR's - collect the whole content -->
70                 <xsl:otherwise>
71                     <xsl:call-template name="verse">
72                         <xsl:with-param name="verse-content" select="child::node()" />
73                         <xsl:with-param name="verse-type" select="wers_wciety|wers_akap|wers_cd[1]" />
74                     </xsl:call-template>
75                 </xsl:otherwise>
76
77             </xsl:choose>
78         </xsl:element>
79     </xsl:template>
80
81     <xsl:template name="verse">
82         <xsl:param name="verse-content" />
83         <xsl:param name="verse-type" />
84
85         <xsl:choose>
86             <xsl:when test="not($verse-type)">
87                 <xsl:element name="v" namespace="http://nowoczesnapolska.org.pl/ML/Lektury/1.1">
88                     <xsl:apply-templates select="$verse-content" />
89                 </xsl:element>
90             </xsl:when>
91
92             <xsl:otherwise>
93                 <xsl:apply-templates select="$verse-content" />
94             </xsl:otherwise>
95         </xsl:choose>
96     </xsl:template>
97
98
99     <!-- akapity -->
100     <xsl:template match="akap">
101         <xsl:element name="p">
102             <xsl:apply-templates select="@*|node()" />
103         </xsl:element>
104     </xsl:template>
105
106     <xsl:template match="akap_cd">
107         <xsl:element name="pc">
108             <xsl:apply-templates select="@*|node()" />
109         </xsl:element>
110     </xsl:template>
111
112     <xsl:template match="akap_dialog">
113         <xsl:element name="pd">
114             <xsl:variable name="prolog" select="./text()[1]" />            
115             <xsl:value-of select="wlf:fix-dialog-line($prolog)" />
116             <xsl:apply-templates select="@*|*|text()[. != $prolog]" />
117         </xsl:element>
118     </xsl:template>
119
120     <!-- wersy -->
121     <xsl:template match="wers_cd">
122         <xsl:element name="vc">
123             <xsl:apply-templates select="@*|node()" />
124         </xsl:element>
125     </xsl:template>
126
127     <xsl:template match="wers_akap">
128         <xsl:element name="vi">
129             <xsl:attribute name="size">p</xsl:attribute>
130             <xsl:apply-templates select="@*|node()" />
131         </xsl:element>
132     </xsl:template>
133
134     <xsl:template match="wers_wciety">
135         <xsl:element name="vi">
136             <xsl:if test="@typ">
137             <xsl:attribute name="size"><xsl:value-of select="@typ" /></xsl:attribute>
138             </xsl:if>
139             <xsl:apply-templates select="@*[name() != 'typ']|node()" />
140         </xsl:element>
141     </xsl:template>
142
143     <xsl:template match="zastepnik_wersu">
144         <xsl:element name="verse-skip">
145             <xsl:choose>
146                 <xsl:when test="starts-with(., '.')">
147                     <xsl:attribute name="type">dot</xsl:attribute>
148                 </xsl:when>
149             </xsl:choose> 
150         </xsl:element>
151     </xsl:template>
152
153     <!-- Przypisy i motywy -->
154     <xsl:template match="begin">
155         <xsl:element name="mark">
156             <xsl:attribute name="starts">
157                 <xsl:value-of select="substring(@id, 2)" />
158             </xsl:attribute>
159             <xsl:attribute name="themes">
160                 <xsl:value-of select="following-sibling::motyw[1]/text()" />
161             </xsl:attribute>
162         </xsl:element>
163     </xsl:template>
164
165     <xsl:template match="motyw" />
166
167     <xsl:template match="end">
168         <xsl:element name="mark">
169             <xsl:attribute name="ends">
170                 <xsl:value-of select="substring(@id, 2)" />
171             </xsl:attribute>
172         </xsl:element>
173     </xsl:template>
174
175     <xsl:template match="pa|pe|pr|pt">
176         <mark id="{generate-id(.)}" />
177     </xsl:template>
178
179
180     <xsl:template match="pa|pe|pr|pt" mode="annotations">
181         <annotation refs="{generate-id(.)}" type="{name(.)}">
182             <xsl:apply-templates select="@*|node()" />
183         </annotation>
184     </xsl:template>
185
186
187     <!-- Tytuły -->
188     <xsl:template match="autor_utworu">
189         <xsl:element name="author">
190             <xsl:apply-templates select="@*|node()" />
191         </xsl:element>
192     </xsl:template>
193
194     <xsl:template match="nazwa_utworu">
195         <xsl:element name="title">
196             <xsl:apply-templates select="@*|node()" />
197         </xsl:element>
198     </xsl:template>
199
200     <xsl:template match="naglowek_czesc">
201         <chapter>
202             <xsl:apply-templates select="@*|node()" />
203         </chapter>
204     </xsl:template>
205
206     <xsl:template match="naglowek_akt">
207         <act>
208             <xsl:apply-templates select="@*|node()" />
209         </act>
210     </xsl:template>
211
212     <xsl:template match="naglowek_scena">
213         <scene>
214             <xsl:apply-templates select="@*|node()" />
215         </scene>
216     </xsl:template>
217
218     <xsl:template match="podtytul">
219         <second-title>
220             <xsl:apply-templates select="@*|node()" />
221         </second-title>
222     </xsl:template>
223
224     <xsl:template match="srodtytul">
225         <part-title>
226             <xsl:apply-templates select="@*|node()" />
227         </part-title>
228     </xsl:template>
229
230     <!-- elementy dramatu -->
231     <xsl:template match="miejsce_czas">
232         <xsl:element name="time-and-date">
233             <xsl:apply-templates select="@*|node()" />
234         </xsl:element>
235     </xsl:template>
236
237
238     <xsl:template match="didaskalia|didask_tekst">
239         <xsl:element name="stage-directions">
240             <xsl:apply-templates select="@*|node()" />
241         </xsl:element>
242     </xsl:template>
243
244     <xsl:template match="motto">
245         <xsl:element name="motto">
246             <xsl:apply-templates select="@*|node()" />
247         
248         <xsl:variable name="sign" select="following-sibling::*[1][name() = 'motto_podpis']" />
249         <signature>
250             <xsl:apply-templates select="$sign/node()" />
251         </signature>
252         </xsl:element>
253     </xsl:template>
254
255     <xsl:template match="motto_podpis[preceding-sibling::*[1][name() = 'motto']]" />
256         
257     <xsl:template match="lista_osob">
258         <person-list>
259             <xsl:apply-templates select="@*|node()" />
260         </person-list>
261     </xsl:template>
262
263     <xsl:template match="naglowek_listy">
264         <caption>
265             <xsl:apply-templates select="@*|node()" />
266         </caption>
267     </xsl:template>
268
269     <xsl:template match="lista_osoba">
270         <person>
271             <xsl:apply-templates select="@*|node()" />
272         </person>
273     </xsl:template>
274
275     <!-- Odstępy i prześwity -->
276     <xsl:template match="sekcja_swiatlo">
277         <vertical-space />
278     </xsl:template>
279     
280     <xsl:template match="sekcja_asterysk">
281         <vertical-space type="asterisk" />
282     </xsl:template>
283
284     <xsl:template match="sekcja_asterysk">
285         <vertical-space type="line" />
286     </xsl:template>
287
288     <!-- pozostałe elementy blokowe -->
289     <xsl:template match="dlugi_cytat">
290         <block-quote>
291             <xsl:apply-templates select="@*|node()" />
292         </block-quote>`
293     </xsl:template>
294
295     <xsl:template match="poezja_cyt">
296         <block-quote>
297             <xsl:apply-templates select="@*|node()" />
298         </block-quote>`
299     </xsl:template>
300
301     <xsl:template match="kwestia">
302         <xsl:variable name="person" select="preceding-sibling::*[1][name() = 'naglowek_osoba']" />
303         <drama-line>
304             <person>
305                 <xsl:apply-templates select="$person/node()" />
306             </person>
307             <xsl:apply-templates select="node()[. != $person]" />
308         </drama-line>
309     </xsl:template>
310
311     <xsl:template match="naglowek_osoba[following-sibling::*[1][name() = 'kwestia']]" />
312         
313     <!-- Inne -->
314     <xsl:template match="osoba">
315         <xsl:element name="person-ref">
316             <xsl:apply-templates select="@*|node()" />
317         </xsl:element>
318     </xsl:template>
319
320     <xsl:template match="slowo_obce">
321         <xsl:element name="df">
322             <xsl:apply-templates select="@*|node()" />
323         </xsl:element>
324     </xsl:template>
325
326     <xsl:template match="wyroznienie">
327         <xsl:element name="em">
328             <xsl:apply-templates select="@*|node()" />
329         </xsl:element>
330     </xsl:template>
331
332     <xsl:template match="mat">
333         <xsl:element name="math">
334             <xsl:apply-templates select="@*|node()" />
335         </xsl:element>
336     </xsl:template>
337
338     <!-- oznaczenie tytulu innego utworu, wymienionego w tym -->
339     <xsl:template match="tytul_dziela">
340         <xsl:element name="book-ref">
341             <xsl:apply-templates select="@*|node()" />
342         </xsl:element>
343     </xsl:template>
344
345     <xsl:template match="extra">
346         <xsl:element name="comment">
347             <xsl:apply-templates select="@*|node()" />
348         </xsl:element>
349     </xsl:template>
350
351     <xsl:template match="uwaga">
352         <xsl:element name="edit-comment">
353             <xsl:apply-templates select="@*|node()" />
354         </xsl:element>
355     </xsl:template>
356
357     <!-- Copy attributes -->
358     <xsl:template match="@*|comment()">
359         <xsl:copy />
360     </xsl:template>    
361
362     <!-- Inside RDF meta-data, leave the text unchanged -->
363     <xsl:template match="rdf:RDF//text()">
364         <xsl:value-of select="." />
365     </xsl:template>
366
367     <!-- Normalize text in other nodes -->
368     <xsl:template match="text()">
369         <xsl:choose>
370             <xsl:when test="$normalize-text">
371                 <xsl:value-of select="wlf:normalize-text(.)" />
372             </xsl:when>
373             <xsl:otherwise>
374                 <xsl:value-of select="." />
375             </xsl:otherwise>
376         </xsl:choose>
377     </xsl:template>
378
379     <!-- Ignoruj RDF poza meta -->
380     <xsl:template match="rdf:*|dc:*" />
381    
382     <xsl:template match="@*|node()" mode="meta">
383         <xsl:copy>
384             <xsl:apply-templates match="@*|node()" mode="meta" />
385         </xsl:copy>
386     </xsl:template>
387
388     <!-- Warn about non-matched elements -->
389     <xsl:template match="node()">
390         <xsl:message>
391             <xsl:text>Nieprzetworzony węzeł:</xsl:text>
392             <xsl:value-of select="." />           
393         </xsl:message>
394         <unparsed-node>
395             <xsl:copy-of select="." />
396         </unparsed-node>
397     </xsl:template>
398     
399 </xsl:stylesheet>