]> git.stg.codes - stg.git/blob - doc/xslt/common/l10n.xsl
Enhanced config serializer.
[stg.git] / doc / xslt / common / l10n.xsl
1 <?xml version='1.0'?>
2 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
3                 xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0"
4                 exclude-result-prefixes="l"
5                 version='1.0'>
6
7 <!-- ********************************************************************
8      $Id: l10n.xsl 8904 2010-09-11 01:56:22Z kosek $
9      ********************************************************************
10
11      This file is part of the XSL DocBook Stylesheet distribution.
12      See ../README or http://docbook.sf.net/release/xsl/current/ for
13      copyright and other information.
14
15      This file contains localization templates (for internationalization)
16      ******************************************************************** -->
17
18 <xsl:param name="l10n.xml" select="document('../common/l10n.xml')"/>
19 <xsl:param name="local.l10n.xml" select="document('')"/>
20 <xsl:param name="empty.local.l10n.xml" select="not($local.l10n.xml//l:l10n)"/>
21
22 <xsl:key name="l10n-lang" match="l:l10n" use="@language"/>
23 <xsl:key name="l10n-gentext" match="l:l10n/l:gentext" use="@key"/>
24 <xsl:key name="l10n-dingbat" match="l:l10n/l:dingbat" use="@key"/>
25 <xsl:key name="l10n-context" match="l:l10n/l:context" use="@name"/>
26 <xsl:key name="l10n-template" match="l:l10n/l:context/l:template[not(@style)]" use="concat(../@name, '#', @name)"/>
27 <xsl:key name="l10n-template-style" match="l:l10n/l:context/l:template[@style]" use="concat(../@name, '#', @name, '#', @style)"/>
28
29 <xsl:template name="l10n.language">
30   <xsl:param name="target" select="."/>
31   <xsl:param name="xref-context" select="false()"/>
32
33   <xsl:variable name="mc-language">
34     <xsl:choose>
35       <xsl:when test="$l10n.gentext.language != ''">
36         <xsl:value-of select="$l10n.gentext.language"/>
37       </xsl:when>
38
39       <xsl:when test="$xref-context or $l10n.gentext.use.xref.language != 0">
40         <!-- can't do this one step: attributes are unordered! -->
41         <xsl:variable name="lang-scope"
42                       select="$target/ancestor-or-self::*
43                               [@lang or @xml:lang][1]"/>
44         <xsl:variable name="lang-attr"
45                       select="($lang-scope/@lang | $lang-scope/@xml:lang)[1]"/>
46         <xsl:choose>
47           <xsl:when test="string($lang-attr) = ''">
48             <xsl:value-of select="$l10n.gentext.default.language"/>
49           </xsl:when>
50           <xsl:otherwise>
51             <xsl:value-of select="$lang-attr"/>
52           </xsl:otherwise>
53         </xsl:choose>
54       </xsl:when>
55
56       <xsl:otherwise>
57         <!-- can't do this one step: attributes are unordered! -->
58         <xsl:variable name="lang-scope"
59                       select="$target/ancestor-or-self::*
60                               [@lang or @xml:lang][1]"/>
61         <xsl:variable name="lang-attr"
62                       select="($lang-scope/@lang | $lang-scope/@xml:lang)[1]"/>
63
64         <xsl:choose>
65           <xsl:when test="string($lang-attr) = ''">
66             <xsl:value-of select="$l10n.gentext.default.language"/>
67           </xsl:when>
68           <xsl:otherwise>
69             <xsl:value-of select="$lang-attr"/>
70           </xsl:otherwise>
71         </xsl:choose>
72       </xsl:otherwise>
73     </xsl:choose>
74   </xsl:variable>
75
76   <xsl:variable name="language" select="translate($mc-language,
77                                         'ABCDEFGHIJKLMNOPQRSTUVWXYZ-',
78                                         'abcdefghijklmnopqrstuvwxyz_')"/>
79
80   <xsl:for-each select="$l10n.xml">   <!-- We need to change context in order to get key work -->
81     <xsl:choose>
82       <xsl:when test="key('l10n-lang', $language)">
83         <xsl:value-of select="$language"/>
84       </xsl:when>
85       <!-- try just the lang code without country -->
86       <xsl:when test="key('l10n-lang', substring-before($language,'_'))">
87         <xsl:value-of select="substring-before($language,'_')"/>
88       </xsl:when>
89       <!-- or use the default -->
90       <xsl:otherwise>
91         <xsl:message>
92           <xsl:text>No localization exists for "</xsl:text>
93           <xsl:value-of select="$language"/>
94           <xsl:text>" or "</xsl:text>
95           <xsl:value-of select="substring-before($language,'_')"/>
96           <xsl:text>". Using default "</xsl:text>
97           <xsl:value-of select="$l10n.gentext.default.language"/>
98           <xsl:text>".</xsl:text>
99         </xsl:message>
100         <xsl:value-of select="$l10n.gentext.default.language"/>
101       </xsl:otherwise>
102     </xsl:choose>
103   </xsl:for-each>
104 </xsl:template>
105
106 <xsl:template name="l10n.language.name">
107   <xsl:param name="lang">
108     <xsl:call-template name="l10n.language"/>
109   </xsl:param>
110
111   <xsl:for-each select="$l10n.xml">
112     <xsl:value-of
113         select="document(key('l10n-lang', $lang)/@href)/l:l10n/@english-language-name"/>
114   </xsl:for-each>
115 </xsl:template>
116
117 <xsl:template name="language.attribute">
118   <xsl:param name="node" select="."/>
119
120   <xsl:variable name="language">
121     <xsl:choose>
122       <xsl:when test="$l10n.gentext.language != ''">
123         <xsl:value-of select="$l10n.gentext.language"/>
124       </xsl:when>
125
126       <xsl:otherwise>
127         <!-- can't do this one step: attributes are unordered! -->
128         <xsl:variable name="lang-scope"
129                       select="$node/ancestor-or-self::*
130                               [@lang or @xml:lang][1]"/>
131         <xsl:variable name="lang-attr"
132                       select="($lang-scope/@lang | $lang-scope/@xml:lang)[1]"/>
133
134         <xsl:choose>
135           <xsl:when test="string($lang-attr) = ''">
136             <xsl:value-of select="$l10n.gentext.default.language"/>
137           </xsl:when>
138           <xsl:otherwise>
139             <xsl:value-of select="$lang-attr"/>
140           </xsl:otherwise>
141         </xsl:choose>
142       </xsl:otherwise>
143     </xsl:choose>
144   </xsl:variable>
145
146   <xsl:if test="$language != ''">
147     <xsl:attribute name="lang">
148       <xsl:choose>
149         <xsl:when test="$l10n.lang.value.rfc.compliant != 0">
150           <xsl:value-of select="translate($language, '_', '-')"/>
151         </xsl:when>
152         <xsl:otherwise>
153           <xsl:value-of select="$language"/>
154         </xsl:otherwise>
155       </xsl:choose>
156     </xsl:attribute>
157   </xsl:if>
158
159   <!-- FIXME: This is sort of hack, but it was the easiest way to add at least partial support for dir attribute -->
160   <xsl:copy-of select="ancestor-or-self::*[@dir][1]/@dir"/>
161 </xsl:template>
162
163 <!-- Duplication of language.attribute template to allow for xml:lang attribute
164      creation for XHTML 1.1 and epub target -->
165 <xsl:template name="xml.language.attribute">
166   <xsl:param name="node" select="."/>
167
168   <xsl:variable name="language">
169     <xsl:choose>
170       <xsl:when test="$l10n.gentext.language != ''">
171         <xsl:value-of select="$l10n.gentext.language"/>
172       </xsl:when>
173
174       <xsl:otherwise>
175         <!-- can't do this one step: attributes are unordered! -->
176         <xsl:variable name="lang-scope"
177                       select="$node/ancestor-or-self::*
178                               [@lang or @xml:lang][1]"/>
179         <xsl:variable name="lang-attr"
180                       select="($lang-scope/@lang | $lang-scope/@xml:lang)[1]"/>
181
182         <xsl:choose>
183           <xsl:when test="string($lang-attr) = ''">
184             <xsl:value-of select="$l10n.gentext.default.language"/>
185           </xsl:when>
186           <xsl:otherwise>
187             <xsl:value-of select="$lang-attr"/>
188           </xsl:otherwise>
189         </xsl:choose>
190       </xsl:otherwise>
191     </xsl:choose>
192   </xsl:variable>
193
194   <xsl:if test="$language != ''">
195     <xsl:attribute name="xml:lang">
196       <xsl:choose>
197         <xsl:when test="$l10n.lang.value.rfc.compliant != 0">
198           <xsl:value-of select="translate($language, '_', '-')"/>
199         </xsl:when>
200         <xsl:otherwise>
201           <xsl:value-of select="$language"/>
202         </xsl:otherwise>
203       </xsl:choose>
204     </xsl:attribute>
205   </xsl:if>
206
207   <!-- FIXME: This is sort of hack, but it was the easiest way to add at least partial support for dir attribute -->
208   <xsl:copy-of select="ancestor-or-self::*[@dir][1]/@dir"/>
209 </xsl:template>
210
211 <xsl:template name="gentext">
212   <xsl:param name="key" select="local-name(.)"/>
213   <xsl:param name="lang">
214     <xsl:call-template name="l10n.language"/>
215   </xsl:param>
216
217   <xsl:for-each select="$l10n.xml">  <!-- We need to switch context in order to make key() work -->
218     <xsl:for-each select="document(key('l10n-lang', $lang)/@href)">
219       <xsl:variable name="local.l10n.gentext"
220                     select="($local.l10n.xml//l:i18n/l:l10n[@language=$lang]/l:gentext[@key=$key])[1]"/>
221
222       <xsl:variable name="l10n.gentext"
223                     select="key('l10n-gentext', $key)[1]"/>
224
225       <xsl:choose>
226         <xsl:when test="$local.l10n.gentext">
227           <xsl:value-of select="$local.l10n.gentext/@text"/>
228         </xsl:when>
229         <xsl:when test="$l10n.gentext">
230           <xsl:value-of select="$l10n.gentext/@text"/>
231         </xsl:when>
232         <xsl:otherwise>
233           <xsl:message>
234             <xsl:text>No "</xsl:text>
235             <xsl:value-of select="$lang"/>
236             <xsl:text>" localization of "</xsl:text>
237             <xsl:value-of select="$key"/>
238             <xsl:text>" exists</xsl:text>
239             <xsl:choose>
240               <xsl:when test="$lang = 'en'">
241                  <xsl:text>.</xsl:text>
242               </xsl:when>
243               <xsl:otherwise>
244                  <xsl:text>; using "en".</xsl:text>
245               </xsl:otherwise>
246             </xsl:choose>
247           </xsl:message>
248           
249           <xsl:for-each select="$l10n.xml">  <!-- We need to switch context in order to make key() work -->
250             <xsl:for-each select="document(key('l10n-lang', 'en')/@href)">
251               <xsl:value-of select="key('l10n-gentext', $key)[1]/@text"/>
252             </xsl:for-each>
253           </xsl:for-each>
254         </xsl:otherwise>
255       </xsl:choose>
256     </xsl:for-each>
257   </xsl:for-each>
258 </xsl:template>
259
260 <xsl:template name="gentext.element.name">
261   <xsl:param name="element.name" select="local-name(.)"/>
262   <xsl:param name="lang">
263     <xsl:call-template name="l10n.language"/>
264   </xsl:param>
265
266   <xsl:call-template name="gentext">
267     <xsl:with-param name="key" select="$element.name"/>
268     <xsl:with-param name="lang" select="$lang"/>
269   </xsl:call-template>
270 </xsl:template>
271
272 <xsl:template name="gentext.space">
273   <xsl:text> </xsl:text>
274 </xsl:template>
275
276 <xsl:template name="gentext.edited.by">
277   <xsl:call-template name="gentext">
278     <xsl:with-param name="key" select="'Editedby'"/>
279   </xsl:call-template>
280 </xsl:template>
281
282 <xsl:template name="gentext.by">
283   <xsl:call-template name="gentext">
284     <xsl:with-param name="key" select="'by'"/>
285   </xsl:call-template>
286 </xsl:template>
287
288 <xsl:template name="gentext.dingbat">
289   <xsl:param name="dingbat">bullet</xsl:param>
290   <xsl:param name="lang">
291     <xsl:call-template name="l10n.language"/>
292   </xsl:param>
293
294   <xsl:for-each select="$l10n.xml">  <!-- We need to switch context in order to make key() work -->
295     <xsl:for-each select="document(key('l10n-lang', $lang)/@href)">
296       <xsl:variable name="local.l10n.dingbat"
297                     select="($local.l10n.xml//l:i18n/l:l10n[@language=$lang]/l:dingbat[@key=$dingbat])[1]"/>
298
299       <xsl:variable name="l10n.dingbat"
300                     select="key('l10n-dingbat', $dingbat)[1]"/>
301
302       <xsl:choose>
303         <xsl:when test="$local.l10n.dingbat">
304           <xsl:value-of select="$local.l10n.dingbat/@text"/>
305         </xsl:when>
306         <xsl:when test="$l10n.dingbat">
307           <xsl:value-of select="$l10n.dingbat/@text"/>
308         </xsl:when>
309         <xsl:otherwise>
310           <xsl:message>
311             <xsl:text>No "</xsl:text>
312             <xsl:value-of select="$lang"/>
313             <xsl:text>" localization of dingbat </xsl:text>
314             <xsl:value-of select="$dingbat"/>
315             <xsl:text> exists; using "en".</xsl:text>
316           </xsl:message>
317
318           <xsl:for-each select="$l10n.xml">  <!-- We need to switch context in order to make key() work -->
319             <xsl:for-each select="document(key('l10n-lang', 'en')/@href)">  
320               <xsl:value-of select="key('l10n-dingbat', $dingbat)[1]/@text"/>
321             </xsl:for-each>
322           </xsl:for-each>
323         </xsl:otherwise>
324       </xsl:choose>
325     </xsl:for-each>
326   </xsl:for-each>
327 </xsl:template>
328
329 <xsl:template name="gentext.startquote">
330   <xsl:call-template name="gentext.dingbat">
331     <xsl:with-param name="dingbat">startquote</xsl:with-param>
332   </xsl:call-template>
333 </xsl:template>
334
335 <xsl:template name="gentext.endquote">
336   <xsl:call-template name="gentext.dingbat">
337     <xsl:with-param name="dingbat">endquote</xsl:with-param>
338   </xsl:call-template>
339 </xsl:template>
340
341 <xsl:template name="gentext.nestedstartquote">
342   <xsl:call-template name="gentext.dingbat">
343     <xsl:with-param name="dingbat">nestedstartquote</xsl:with-param>
344   </xsl:call-template>
345 </xsl:template>
346
347 <xsl:template name="gentext.nestedendquote">
348   <xsl:call-template name="gentext.dingbat">
349     <xsl:with-param name="dingbat">nestedendquote</xsl:with-param>
350   </xsl:call-template>
351 </xsl:template>
352
353 <xsl:template name="gentext.nav.prev">
354   <xsl:call-template name="gentext">
355     <xsl:with-param name="key" select="'nav-prev'"/>
356   </xsl:call-template>
357 </xsl:template>
358
359 <xsl:template name="gentext.nav.next">
360   <xsl:call-template name="gentext">
361     <xsl:with-param name="key" select="'nav-next'"/>
362   </xsl:call-template>
363 </xsl:template>
364
365 <xsl:template name="gentext.nav.home">
366   <xsl:call-template name="gentext">
367     <xsl:with-param name="key" select="'nav-home'"/>
368   </xsl:call-template>
369 </xsl:template>
370
371 <xsl:template name="gentext.nav.up">
372   <xsl:call-template name="gentext">
373     <xsl:with-param name="key" select="'nav-up'"/>
374   </xsl:call-template>
375 </xsl:template>
376
377 <!-- ============================================================ -->
378
379 <xsl:template name="gentext.template">
380   <xsl:param name="context" select="'default'"/>
381   <xsl:param name="name" select="'default'"/>
382   <xsl:param name="origname" select="$name"/>
383   <xsl:param name="purpose"/>
384   <xsl:param name="xrefstyle"/>
385   <xsl:param name="referrer"/>
386   <xsl:param name="lang">
387     <xsl:call-template name="l10n.language"/>
388   </xsl:param>
389   <xsl:param name="verbose" select="1"/>
390
391   <xsl:choose>
392     <xsl:when test="$empty.local.l10n.xml">
393       <xsl:for-each select="$l10n.xml">  <!-- We need to switch context in order to make key() work -->
394         <xsl:for-each select="document(key('l10n-lang', $lang)/@href)">
395
396           <xsl:variable name="localization.node"
397                         select="key('l10n-lang', $lang)[1]"/>
398
399           <xsl:if test="count($localization.node) = 0
400                         and $verbose != 0">
401             <xsl:message>
402               <xsl:text>No "</xsl:text>
403               <xsl:value-of select="$lang"/>
404               <xsl:text>" localization exists.</xsl:text>
405             </xsl:message>
406           </xsl:if>
407
408           <xsl:variable name="context.node"
409                         select="key('l10n-context', $context)[1]"/>
410
411           <xsl:if test="count($context.node) = 0
412                         and $verbose != 0">
413             <xsl:message>
414               <xsl:text>No context named "</xsl:text>
415               <xsl:value-of select="$context"/>
416               <xsl:text>" exists in the "</xsl:text>
417               <xsl:value-of select="$lang"/>
418               <xsl:text>" localization.</xsl:text>
419             </xsl:message>
420           </xsl:if>
421
422           <xsl:for-each select="$context.node">
423             <xsl:variable name="template.node"
424                           select="(key('l10n-template-style', concat($context, '#', $name, '#', $xrefstyle))
425                                    |key('l10n-template', concat($context, '#', $name)))[1]"/>
426
427             <xsl:choose>
428               <xsl:when test="$template.node/@text">
429                 <xsl:value-of select="$template.node/@text"/>
430               </xsl:when>
431               <xsl:otherwise>
432                 <xsl:choose>
433                   <xsl:when test="contains($name, '/')">
434                     <xsl:call-template name="gentext.template">
435                       <xsl:with-param name="context" select="$context"/>
436                       <xsl:with-param name="name" select="substring-after($name, '/')"/>
437                       <xsl:with-param name="origname" select="$origname"/>
438                       <xsl:with-param name="purpose" select="$purpose"/>
439                       <xsl:with-param name="xrefstyle" select="$xrefstyle"/>
440                       <xsl:with-param name="referrer" select="$referrer"/>
441                       <xsl:with-param name="lang" select="$lang"/>
442                       <xsl:with-param name="verbose" select="$verbose"/>
443                     </xsl:call-template>
444                   </xsl:when>
445                   <xsl:when test="$verbose = 0">
446                     <!-- silence -->
447                   </xsl:when>
448                   <xsl:otherwise>
449                     <xsl:message>
450                       <xsl:text>No template for "</xsl:text>
451                       <xsl:value-of select="$origname"/>
452                       <xsl:text>" (or any of its leaves) exists in the context named "</xsl:text>
453                       <xsl:value-of select="$context"/>
454                       <xsl:text>" in the "</xsl:text>
455                       <xsl:value-of select="$lang"/>
456                       <xsl:text>" localization.</xsl:text>
457                     </xsl:message>
458                   </xsl:otherwise>
459                 </xsl:choose>
460               </xsl:otherwise>
461             </xsl:choose>
462           </xsl:for-each>
463         </xsl:for-each>
464       </xsl:for-each>
465     </xsl:when>
466     <xsl:otherwise>
467       <xsl:for-each select="$l10n.xml">  <!-- We need to switch context in order to make key() work -->
468         <xsl:for-each select="document(key('l10n-lang', $lang)/@href)">
469
470           <xsl:variable name="local.localization.node"
471                         select="($local.l10n.xml//l:i18n/l:l10n[@language=$lang])[1]"/>
472
473           <xsl:variable name="localization.node"
474                         select="key('l10n-lang', $lang)[1]"/>
475
476           <xsl:if test="count($localization.node) = 0
477                         and count($local.localization.node) = 0
478                         and $verbose != 0">
479             <xsl:message>
480               <xsl:text>No "</xsl:text>
481               <xsl:value-of select="$lang"/>
482               <xsl:text>" localization exists.</xsl:text>
483             </xsl:message>
484           </xsl:if>
485
486           <xsl:variable name="local.context.node"
487                         select="$local.localization.node/l:context[@name=$context]"/>
488
489           <xsl:variable name="context.node"
490                         select="key('l10n-context', $context)[1]"/>
491
492           <xsl:if test="count($context.node) = 0
493                         and count($local.context.node) = 0
494                         and $verbose != 0">
495             <xsl:message>
496               <xsl:text>No context named "</xsl:text>
497               <xsl:value-of select="$context"/>
498               <xsl:text>" exists in the "</xsl:text>
499               <xsl:value-of select="$lang"/>
500               <xsl:text>" localization.</xsl:text>
501             </xsl:message>
502           </xsl:if>
503
504           <xsl:variable name="local.template.node"
505                         select="($local.context.node/l:template[@name=$name
506                                                                 and @style
507                                                                 and @style=$xrefstyle]
508                                 |$local.context.node/l:template[@name=$name
509                                                                 and not(@style)])[1]"/>
510
511           <xsl:for-each select="$context.node">
512             <xsl:variable name="template.node"
513                           select="(key('l10n-template-style', concat($context, '#', $name, '#', $xrefstyle))
514                                    |key('l10n-template', concat($context, '#', $name)))[1]"/>
515
516             <xsl:choose>
517               <xsl:when test="$local.template.node/@text">
518                 <xsl:value-of select="$local.template.node/@text"/>
519               </xsl:when>
520               <xsl:when test="$template.node/@text">
521                 <xsl:value-of select="$template.node/@text"/>
522               </xsl:when>
523               <xsl:otherwise>
524                 <xsl:choose>
525                   <xsl:when test="contains($name, '/')">
526                     <xsl:call-template name="gentext.template">
527                       <xsl:with-param name="context" select="$context"/>
528                       <xsl:with-param name="name" select="substring-after($name, '/')"/>
529                       <xsl:with-param name="origname" select="$origname"/>
530                       <xsl:with-param name="purpose" select="$purpose"/>
531                       <xsl:with-param name="xrefstyle" select="$xrefstyle"/>
532                       <xsl:with-param name="referrer" select="$referrer"/>
533                       <xsl:with-param name="lang" select="$lang"/>
534                       <xsl:with-param name="verbose" select="$verbose"/>
535                     </xsl:call-template>
536                   </xsl:when>
537                   <xsl:when test="$verbose = 0">
538                     <!-- silence -->
539                   </xsl:when>
540                   <xsl:otherwise>
541                     <xsl:message>
542                       <xsl:text>No template for "</xsl:text>
543                       <xsl:value-of select="$origname"/>
544                       <xsl:text>" (or any of its leaves) exists in the context named "</xsl:text>
545                       <xsl:value-of select="$context"/>
546                       <xsl:text>" in the "</xsl:text>
547                       <xsl:value-of select="$lang"/>
548                       <xsl:text>" localization.</xsl:text>
549                     </xsl:message>
550                   </xsl:otherwise>
551                 </xsl:choose>
552               </xsl:otherwise>
553             </xsl:choose>
554           </xsl:for-each>
555         </xsl:for-each>
556       </xsl:for-each>
557     </xsl:otherwise>
558   </xsl:choose>
559 </xsl:template>
560
561 <!-- silently test if a gentext template exists -->
562
563 <xsl:template name="gentext.template.exists">
564   <xsl:param name="context" select="'default'"/>
565   <xsl:param name="name" select="'default'"/>
566   <xsl:param name="origname" select="$name"/>
567   <xsl:param name="purpose"/>
568   <xsl:param name="xrefstyle"/>
569   <xsl:param name="referrer"/>
570   <xsl:param name="lang">
571     <xsl:call-template name="l10n.language"/>
572   </xsl:param>
573
574   <xsl:variable name="template">
575     <xsl:call-template name="gentext.template">
576       <xsl:with-param name="context" select="$context"/>
577       <xsl:with-param name="name" select="$name"/>
578       <xsl:with-param name="origname" select="$origname"/>
579       <xsl:with-param name="purpose" select="$purpose"/>
580       <xsl:with-param name="xrefstyle" select="$xrefstyle"/>
581       <xsl:with-param name="referrer" select="$referrer"/>
582       <xsl:with-param name="lang" select="$lang"/>
583       <xsl:with-param name="verbose" select="0"/>
584     </xsl:call-template>
585   </xsl:variable>
586   
587   <xsl:choose>
588     <xsl:when test="string-length($template) != 0">1</xsl:when>
589     <xsl:otherwise>0</xsl:otherwise>
590   </xsl:choose>
591 </xsl:template>
592
593 </xsl:stylesheet>