]> git.saurik.com Git - bison.git/blob - data/xslt/xml2xhtml.xsl
(bison:ruleNumber): New key. Improve processing time. Suggested by Joel E. Denny.
[bison.git] / data / xslt / xml2xhtml.xsl
1 <?xml version="1.0" encoding="UTF-8"?>
2
3 <!--
4 xml2html.xsl - transform Bison XML Report into XHTML.
5 $Id$
6
7 Copyright (C) 2007 Free Software Foundation, Inc.
8
9 This file is part of Bison, the GNU Compiler Compiler.
10
11 This program is free software: you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
23
24 Written by Wojciech Polak <polak@gnu.org>.
25 -->
26
27 <xsl:stylesheet version="1.0"
28 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
29 xmlns="http://www.w3.org/1999/xhtml"
30 xmlns:bison="http://www.gnu.org/software/bison/">
31
32 <xsl:import href="bison.xsl"/>
33
34 <xsl:output method="xml" encoding="UTF-8"
35 doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
36 doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
37 indent="yes"/>
38
39 <xsl:template match="/">
40 <html>
41 <head>
42 <title>GNU Bison XML Automaton Report</title>
43 <style type="text/css"><![CDATA[
44 body {
45 font-family: "Nimbus Sans L", Arial, sans-serif;
46 font-size: 9pt;
47 }
48 a:link {
49 color: #1f00ff;
50 text-decoration: none;
51 }
52 a:visited {
53 color: #1f00ff;
54 text-decoration: none;
55 }
56 a:hover {
57 color: red;
58 }
59 #menu a {
60 text-decoration: underline;
61 }
62 .i {
63 font-style: italic;
64 }
65 .pre {
66 font-family: monospace;
67 white-space: pre;
68 }
69 ol.decimal {
70 list-style-type: decimal;
71 }
72 ol.lower-alpha {
73 list-style-type: lower-alpha;
74 }
75 .point {
76 color: #cc0000;
77 }
78 #footer {
79 margin-top: 3.5em;
80 font-size: 7pt;
81 }
82 ]]></style>
83 </head>
84 <body>
85 <xsl:apply-templates select="bison-xml-report"/>
86 <xsl:text>&#10;&#10;</xsl:text>
87 <div id="footer"><hr />
88 <a href="http://www.gnu.org/software/bison/" title="GNU Bison">
89 GNU Bison <xsl:value-of select="/bison-xml-report/@version"/></a>
90 XML Automaton Report, written by
91 <a href="http://www.gnu.org.ua/~polak/" title="Wojciech Polak">Wojciech Polak</a>.
92 Copyright (C) 2007 Free Software Foundation, Inc.<br />
93 Verbatim copying and distribution of this entire page is permitted
94 in any medium, provided this notice is preserved.</div>
95 </body>
96 </html>
97 </xsl:template>
98
99 <xsl:template match="bison-xml-report">
100 <h1>GNU Bison XML Automaton Report</h1>
101 <p>
102 input grammar: <span class="i"><xsl:value-of select="filename"/></span>
103 </p>
104
105 <xsl:text>&#10;&#10;</xsl:text>
106 <h3>Table of Contents</h3>
107 <ul id="menu">
108 <li>
109 <a href="#reductions">Reductions</a>
110 <ul class="lower-alpha">
111 <li><a href="#useless_nonterminals">Useless nonterminal symbols</a></li>
112 <li><a href="#unused_terminals">Unused terminal symbols</a></li>
113 <li><a href="#useless_rules">Useless rules</a></li>
114 </ul>
115 </li>
116 <li><a href="#conflicts">Conflicts</a></li>
117 <li>
118 <a href="#grammar">Grammar</a>
119 <ul class="lower-alpha">
120 <li><a href="#grammar">Itemset</a></li>
121 <li><a href="#terminals">Terminal symbols</a></li>
122 <li><a href="#nonterminals">Nonterminal symbols</a></li>
123 </ul>
124 </li>
125 <li><a href="#automaton">Automaton</a></li>
126 </ul>
127 <xsl:apply-templates select="reductions"/>
128 <xsl:apply-templates select="rules-never-reduced"/>
129 <xsl:apply-templates select="automaton" mode="conflicts"/>
130 <xsl:apply-templates select="grammar"/>
131 <xsl:apply-templates select="automaton"/>
132 </xsl:template>
133
134 <xsl:template match="rules-never-reduced">
135 <xsl:if test="rule">
136 <h2>
137 <a name="rules_never_reduced"/>
138 <xsl:text> Rules never reduced</xsl:text>
139 </h2>
140 <xsl:text>&#10;</xsl:text>
141 <p class="pre">
142 <xsl:apply-templates select="rule">
143 <xsl:with-param name="pad" select="'3'"/>
144 </xsl:apply-templates>
145 </p>
146 <xsl:text>&#10;&#10;</xsl:text>
147 </xsl:if>
148 </xsl:template>
149
150 <xsl:template match="reductions">
151 <h2>
152 <a name="reductions"/>
153 <xsl:text> Reductions</xsl:text>
154 </h2>
155 <xsl:apply-templates select="useless/nonterminals"/>
156 <xsl:apply-templates select="unused/terminals"/>
157 <xsl:apply-templates select="useless/rules"/>
158 </xsl:template>
159
160 <xsl:template match="useless/nonterminals">
161 <h3>
162 <a name="useless_nonterminals"/>
163 <xsl:text> Useless nonterminals</xsl:text>
164 </h3>
165 <xsl:text>&#10;&#10;</xsl:text>
166 <xsl:if test="nonterminal">
167 <p class="pre">
168 <xsl:for-each select="nonterminal">
169 <xsl:text> </xsl:text>
170 <xsl:value-of select="."/>
171 <xsl:text>&#10;</xsl:text>
172 </xsl:for-each>
173 <xsl:text>&#10;&#10;</xsl:text>
174 </p>
175 </xsl:if>
176 </xsl:template>
177
178 <xsl:template match="useless/rules">
179 <h3>
180 <a name="useless_rules"/>
181 <xsl:text> Useless rules</xsl:text>
182 </h3>
183 <xsl:text>&#10;</xsl:text>
184 <xsl:if test="rule">
185 <p class="pre">
186 <xsl:apply-templates select="rule">
187 <xsl:with-param name="pad" select="'3'"/>
188 </xsl:apply-templates>
189 <xsl:text>&#10;&#10;</xsl:text>
190 </p>
191 </xsl:if>
192 </xsl:template>
193
194 <xsl:template match="unused/terminals">
195 <h3>
196 <a name="unused_terminals"/>
197 <xsl:text> Terminals which are not used</xsl:text>
198 </h3>
199 <xsl:text>&#10;&#10;</xsl:text>
200 <xsl:if test="terminal">
201 <p class="pre">
202 <xsl:for-each select="terminal">
203 <xsl:text> </xsl:text>
204 <xsl:value-of select="."/>
205 <xsl:text>&#10;</xsl:text>
206 </xsl:for-each>
207 <xsl:text>&#10;&#10;</xsl:text>
208 </p>
209 </xsl:if>
210 </xsl:template>
211
212 <xsl:template match="automaton" mode="conflicts">
213 <h2>
214 <a name="conflicts"/>
215 <xsl:text> Conflicts</xsl:text>
216 </h2>
217 <xsl:text>&#10;&#10;</xsl:text>
218 <xsl:variable name="conflict-report">
219 <xsl:apply-templates select="state" mode="conflicts"/>
220 </xsl:variable>
221 <xsl:if test="string-length($conflict-report) != 0">
222 <p class="pre">
223 <xsl:copy-of select="$conflict-report"/>
224 <xsl:text>&#10;&#10;</xsl:text>
225 </p>
226 </xsl:if>
227 </xsl:template>
228
229 <xsl:template match="state" mode="conflicts">
230 <xsl:variable name="conflict-counts">
231 <xsl:apply-templates select="." mode="bison:count-conflicts" />
232 </xsl:variable>
233 <xsl:variable
234 name="sr-count" select="substring-before($conflict-counts, ',')"
235 />
236 <xsl:variable
237 name="rr-count" select="substring-after($conflict-counts, ',')"
238 />
239 <xsl:if test="$sr-count > 0 or $rr-count > 0">
240 <a>
241 <xsl:attribute name="href">
242 <xsl:value-of select="concat('#state_', @number)"/>
243 </xsl:attribute>
244 <xsl:value-of select="concat('State ', @number)"/>
245 </a>
246 <xsl:text> conflicts:</xsl:text>
247 <xsl:if test="$sr-count > 0">
248 <xsl:value-of select="concat(' ', $sr-count, ' shift/reduce')"/>
249 <xsl:if test="$rr-count > 0">
250 <xsl:value-of select="(',')"/>
251 </xsl:if>
252 </xsl:if>
253 <xsl:if test="$rr-count > 0">
254 <xsl:value-of select="concat(' ', $rr-count, ' reduce/reduce')"/>
255 </xsl:if>
256 <xsl:value-of select="'&#10;'"/>
257 </xsl:if>
258 </xsl:template>
259
260 <xsl:template match="grammar">
261 <h2>
262 <a name="grammar"/>
263 <xsl:text> Grammar</xsl:text>
264 </h2>
265 <xsl:text>&#10;</xsl:text>
266 <p class="pre">
267 <xsl:apply-templates select="rules/rule">
268 <xsl:with-param name="pad" select="'3'"/>
269 </xsl:apply-templates>
270 </p>
271 <xsl:text>&#10;&#10;</xsl:text>
272 <xsl:apply-templates select="terminals"/>
273 <xsl:apply-templates select="nonterminals"/>
274 </xsl:template>
275
276 <xsl:template match="grammar/terminals">
277 <h3>
278 <a name="terminals"/>
279 <xsl:text> Terminals, with rules where they appear</xsl:text>
280 </h3>
281 <xsl:text>&#10;&#10;</xsl:text>
282 <p class="pre">
283 <xsl:apply-templates select="terminal"/>
284 </p>
285 <xsl:text>&#10;&#10;</xsl:text>
286 </xsl:template>
287
288 <xsl:template match="grammar/nonterminals">
289 <h3>
290 <a name="nonterminals"/>
291 <xsl:text> Nonterminals, with rules where they appear</xsl:text>
292 </h3>
293 <xsl:text>&#10;&#10;</xsl:text>
294 <p class="pre">
295 <xsl:apply-templates select="nonterminal"/>
296 </p>
297 </xsl:template>
298
299 <xsl:template match="terminal">
300 <b><xsl:value-of select="@symbol"/></b>
301 <xsl:value-of select="concat(' (', @type, ')')"/>
302 <xsl:apply-templates select="rule"/>
303 <xsl:text>&#10;</xsl:text>
304 </xsl:template>
305
306 <xsl:template match="terminal/rule">
307 <xsl:text> </xsl:text>
308 <a>
309 <xsl:attribute name="href">
310 <xsl:value-of select="concat('#rule_', .)"/>
311 </xsl:attribute>
312 <xsl:value-of select="."/>
313 </a>
314 </xsl:template>
315
316 <xsl:template match="nonterminal">
317 <b><xsl:value-of select="@symbol"/></b>
318 <xsl:value-of select="concat(' (', @type, ')')"/>
319 <xsl:text>&#10; </xsl:text>
320 <xsl:if test="left/rule">
321 <xsl:text>on left:</xsl:text>
322 </xsl:if>
323 <xsl:apply-templates select="left/rule"/>
324 <xsl:if test="left/rule and right/rule">
325 <xsl:text>&#10; </xsl:text>
326 </xsl:if>
327 <xsl:if test="right/rule">
328 <xsl:text>on right:</xsl:text>
329 </xsl:if>
330 <xsl:apply-templates select="right/rule"/>
331 <xsl:text>&#10;</xsl:text>
332 </xsl:template>
333
334 <xsl:template match="nonterminal/left/rule|nonterminal/right/rule">
335 <xsl:text> </xsl:text>
336 <a>
337 <xsl:attribute name="href">
338 <xsl:value-of select="concat('#rule_', .)"/>
339 </xsl:attribute>
340 <xsl:value-of select="."/>
341 </a>
342 </xsl:template>
343
344 <xsl:template match="automaton">
345 <h2>
346 <a name="automaton"/>
347 <xsl:text> Automaton</xsl:text>
348 </h2>
349 <xsl:apply-templates select="state">
350 <xsl:with-param name="pad" select="'3'"/>
351 </xsl:apply-templates>
352 </xsl:template>
353
354 <xsl:template match="automaton/state">
355 <xsl:param name="pad"/>
356 <xsl:text>&#10;&#10;</xsl:text>
357 <h3>
358 <a>
359 <xsl:attribute name="name">
360 <xsl:value-of select="concat('state_', @number)"/>
361 </xsl:attribute>
362 </a>
363 <xsl:text>state </xsl:text>
364 <xsl:value-of select="@number"/>
365 </h3>
366 <xsl:text>&#10;&#10;</xsl:text>
367 <p class="pre">
368 <xsl:apply-templates select="itemset/rule">
369 <xsl:with-param name="pad" select="$pad"/>
370 </xsl:apply-templates>
371 <xsl:apply-templates select="actions/transitions">
372 <xsl:with-param name="type" select="'shift'"/>
373 </xsl:apply-templates>
374 <xsl:apply-templates select="actions/errors"/>
375 <xsl:apply-templates select="actions/reductions"/>
376 <xsl:apply-templates select="actions/transitions">
377 <xsl:with-param name="type" select="'goto'"/>
378 </xsl:apply-templates>
379 <xsl:apply-templates select="solved-conflicts"/>
380 </p>
381 </xsl:template>
382
383 <xsl:template match="actions/transitions">
384 <xsl:param name="type"/>
385 <xsl:if test="transition[@type = $type]">
386 <xsl:text>&#10;</xsl:text>
387 <xsl:apply-templates select="transition[@type = $type]">
388 <xsl:with-param name="pad">
389 <xsl:call-template name="max-width-symbol">
390 <xsl:with-param name="node" select="transition[@type = $type]"/>
391 </xsl:call-template>
392 </xsl:with-param>
393 </xsl:apply-templates>
394 </xsl:if>
395 </xsl:template>
396
397 <xsl:template match="actions/errors">
398 <xsl:if test="error">
399 <xsl:text>&#10;</xsl:text>
400 <xsl:apply-templates select="error">
401 <xsl:with-param name="pad">
402 <xsl:call-template name="max-width-symbol">
403 <xsl:with-param name="node" select="error"/>
404 </xsl:call-template>
405 </xsl:with-param>
406 </xsl:apply-templates>
407 </xsl:if>
408 </xsl:template>
409
410 <xsl:template match="actions/reductions">
411 <xsl:if test="reduction">
412 <xsl:text>&#10;</xsl:text>
413 <xsl:apply-templates select="reduction">
414 <xsl:with-param name="pad">
415 <xsl:call-template name="max-width-symbol">
416 <xsl:with-param name="node" select="reduction"/>
417 </xsl:call-template>
418 </xsl:with-param>
419 </xsl:apply-templates>
420 </xsl:if>
421 </xsl:template>
422
423 <xsl:template match="rule">
424 <xsl:param name="pad"/>
425 <xsl:if test="not(name(..) = 'itemset') and not(preceding-sibling::rule[1]/lhs[text()] = lhs[text()])">
426 <xsl:text>&#10;</xsl:text>
427 </xsl:if>
428 <xsl:if test="not(name(..) = 'itemset')">
429 <a>
430 <xsl:attribute name="name">
431 <xsl:value-of select="concat('rule_', @number)"/>
432 </xsl:attribute>
433 </a>
434 </xsl:if>
435 <xsl:text> </xsl:text>
436 <xsl:choose>
437 <xsl:when test="name(..) = 'itemset'">
438 <a>
439 <xsl:attribute name="href">
440 <xsl:value-of select="concat('#rule_', @number)"/>
441 </xsl:attribute>
442 <xsl:call-template name="lpad">
443 <xsl:with-param name="str" select="string(@number)"/>
444 <xsl:with-param name="pad" select="number($pad)"/>
445 </xsl:call-template>
446 </a>
447 </xsl:when>
448 <xsl:otherwise>
449 <xsl:call-template name="lpad">
450 <xsl:with-param name="str" select="string(@number)"/>
451 <xsl:with-param name="pad" select="number($pad)"/>
452 </xsl:call-template>
453 </xsl:otherwise>
454 </xsl:choose>
455 <xsl:text> </xsl:text>
456 <xsl:choose>
457 <xsl:when test="preceding-sibling::rule[1]/lhs[text()] = lhs[text()]">
458 <xsl:call-template name="lpad">
459 <xsl:with-param name="str" select="'|'"/>
460 <xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 2"/>
461 </xsl:call-template>
462 </xsl:when>
463 <xsl:otherwise>
464 <span class="i">
465 <xsl:value-of select="lhs"/>
466 </span>
467 <xsl:text> &#8594;</xsl:text>
468 </xsl:otherwise>
469 </xsl:choose>
470 <xsl:apply-templates select="rhs/symbol|rhs/point|rhs/empty"/>
471 <xsl:apply-templates select="lookaheads"/>
472 <xsl:text>&#10;</xsl:text>
473 </xsl:template>
474
475 <xsl:template match="symbol">
476 <xsl:text> </xsl:text>
477 <xsl:choose>
478 <xsl:when test="@class = 'nonterminal'">
479 <span class="i"><xsl:value-of select="."/></span>
480 </xsl:when>
481 <xsl:otherwise>
482 <b><xsl:value-of select="."/></b>
483 </xsl:otherwise>
484 </xsl:choose>
485 </xsl:template>
486
487 <xsl:template match="point">
488 <xsl:text> </xsl:text>
489 <span class="point">.</span>
490 </xsl:template>
491
492 <xsl:template match="empty">
493 <xsl:text> &#949;</xsl:text>
494 </xsl:template>
495
496 <xsl:template match="lookaheads">
497 <xsl:text> [</xsl:text>
498 <xsl:apply-templates select="symbol"/>
499 <xsl:text>]</xsl:text>
500 </xsl:template>
501
502 <xsl:template match="lookaheads/symbol">
503 <xsl:value-of select="."/>
504 <xsl:if test="position() != last()">
505 <xsl:text>, </xsl:text>
506 </xsl:if>
507 </xsl:template>
508
509 <xsl:template match="transition">
510 <xsl:param name="pad"/>
511 <xsl:text> </xsl:text>
512 <xsl:call-template name="rpad">
513 <xsl:with-param name="str" select="string(@symbol)"/>
514 <xsl:with-param name="pad" select="number($pad) + 2"/>
515 </xsl:call-template>
516 <xsl:choose>
517 <xsl:when test="@type = 'shift'">
518 <a>
519 <xsl:attribute name="href">
520 <xsl:value-of select="concat('#state_', @state)"/>
521 </xsl:attribute>
522 <xsl:value-of select="concat('shift, and go to state ', @state)"/>
523 </a>
524 </xsl:when>
525 <xsl:when test="@type = 'goto'">
526 <a>
527 <xsl:attribute name="href">
528 <xsl:value-of select="concat('#state_', @state)"/>
529 </xsl:attribute>
530 <xsl:value-of select="concat('go to state ', @state)"/>
531 </a>
532 </xsl:when>
533 </xsl:choose>
534 <xsl:text>&#10;</xsl:text>
535 </xsl:template>
536
537 <xsl:template match="error">
538 <xsl:param name="pad"/>
539 <xsl:text> </xsl:text>
540 <xsl:call-template name="rpad">
541 <xsl:with-param name="str" select="string(@symbol)"/>
542 <xsl:with-param name="pad" select="number($pad) + 2"/>
543 </xsl:call-template>
544 <xsl:text>error</xsl:text>
545 <xsl:text> (</xsl:text>
546 <xsl:value-of select="text()"/>
547 <xsl:text>)</xsl:text>
548 <xsl:text>&#10;</xsl:text>
549 </xsl:template>
550
551 <xsl:template match="reduction">
552 <xsl:param name="pad"/>
553 <xsl:text> </xsl:text>
554 <xsl:call-template name="rpad">
555 <xsl:with-param name="str" select="string(@symbol)"/>
556 <xsl:with-param name="pad" select="number($pad) + 2"/>
557 </xsl:call-template>
558 <xsl:if test="@enabled = 'false'">
559 <xsl:text>[</xsl:text>
560 </xsl:if>
561 <xsl:choose>
562 <xsl:when test="@rule = 'accept'">
563 <xsl:text>accept</xsl:text>
564 </xsl:when>
565 <xsl:otherwise>
566 <a>
567 <xsl:attribute name="href">
568 <xsl:value-of select="concat('#rule_', @rule)"/>
569 </xsl:attribute>
570 <xsl:value-of select="concat('reduce using rule ', @rule)"/>
571 </a>
572 <xsl:text> (</xsl:text>
573 <xsl:value-of
574 select="/bison-xml-report/grammar/rules/rule[@number = current()/@rule]/lhs[text()]"/>
575 <xsl:text>)</xsl:text>
576 </xsl:otherwise>
577 </xsl:choose>
578 <xsl:if test="@enabled = 'false'">
579 <xsl:text>]</xsl:text>
580 </xsl:if>
581 <xsl:text>&#10;</xsl:text>
582 </xsl:template>
583
584 <xsl:template match="solved-conflicts">
585 <xsl:if test="resolution">
586 <xsl:text>&#10;</xsl:text>
587 <xsl:apply-templates select="resolution"/>
588 </xsl:if>
589 </xsl:template>
590
591 <xsl:template match="resolution">
592 <xsl:text> Conflict between </xsl:text>
593 <a>
594 <xsl:attribute name="href">
595 <xsl:value-of select="concat('#rule_', @rule)"/>
596 </xsl:attribute>
597 <xsl:value-of select="concat('rule ',@rule)"/>
598 </a>
599 <xsl:text> and token </xsl:text>
600 <xsl:value-of select="@symbol"/>
601 <xsl:text> resolved as </xsl:text>
602 <xsl:if test="@type = 'error'">
603 <xsl:text>an </xsl:text>
604 </xsl:if>
605 <xsl:value-of select="@type"/>
606 <xsl:text> (</xsl:text>
607 <xsl:value-of select="."/>
608 <xsl:text>).&#10;</xsl:text>
609 </xsl:template>
610
611 <xsl:template name="max-width-symbol">
612 <xsl:param name="node"/>
613 <xsl:variable name="longest">
614 <xsl:for-each select="$node">
615 <xsl:sort data-type="number" select="string-length(@symbol)"
616 order="descending"/>
617 <xsl:if test="position() = 1">
618 <xsl:value-of select="string-length(@symbol)"/>
619 </xsl:if>
620 </xsl:for-each>
621 </xsl:variable>
622 <xsl:value-of select="$longest"/>
623 </xsl:template>
624
625 <xsl:template name="lpad">
626 <xsl:param name="str" select="''"/>
627 <xsl:param name="pad" select="0"/>
628 <xsl:variable name="diff" select="$pad - string-length($str)" />
629 <xsl:choose>
630 <xsl:when test="$diff &lt; 0">
631 <xsl:value-of select="$str"/>
632 </xsl:when>
633 <xsl:otherwise>
634 <xsl:call-template name="space">
635 <xsl:with-param name="repeat" select="$diff"/>
636 </xsl:call-template>
637 <xsl:value-of select="$str"/>
638 </xsl:otherwise>
639 </xsl:choose>
640 </xsl:template>
641
642 <xsl:template name="rpad">
643 <xsl:param name="str" select="''"/>
644 <xsl:param name="pad" select="0"/>
645 <xsl:variable name="diff" select="$pad - string-length($str)"/>
646 <xsl:choose>
647 <xsl:when test="$diff &lt; 0">
648 <xsl:value-of select="$str"/>
649 </xsl:when>
650 <xsl:otherwise>
651 <xsl:value-of select="$str"/>
652 <xsl:call-template name="space">
653 <xsl:with-param name="repeat" select="$diff"/>
654 </xsl:call-template>
655 </xsl:otherwise>
656 </xsl:choose>
657 </xsl:template>
658
659 <xsl:template name="space">
660 <xsl:param name="repeat">0</xsl:param>
661 <xsl:param name="fill" select="' '"/>
662 <xsl:if test="number($repeat) &gt;= 1">
663 <xsl:call-template name="space">
664 <xsl:with-param name="repeat" select="$repeat - 1"/>
665 <xsl:with-param name="fill" select="$fill"/>
666 </xsl:call-template>
667 <xsl:value-of select="$fill"/>
668 </xsl:if>
669 </xsl:template>
670
671 </xsl:stylesheet>