1<?xml version='1.0'?>
2<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
3                xmlns:doc="http://nwalsh.com/xsl/documentation/1.0"
4                xmlns:stbl="http://nwalsh.com/xslt/ext/com.nwalsh.saxon.Table"
5                xmlns:xtbl="com.nwalsh.xalan.Table"
6                xmlns:lxslt="http://xml.apache.org/xslt"
7                exclude-result-prefixes="doc stbl xtbl lxslt"
8                version='1.0'>
9
10<!-- ********************************************************************
11     $Id$
12     ********************************************************************
13
14     This file is part of the XSL DocBook Stylesheet distribution.
15     See /README or http://nwalsh.com/docbook/xsl/ for copyright
16     and other information.
17
18     ******************************************************************** -->
19
20<lxslt:component prefix="xtbl"
21                 functions="adjustColumnWidths"/>
22
23<xsl:template match="tgroup">
24  <table>
25    <xsl:choose>
26      <!-- If there's a <?dbhtml table-summary="foo"?> PI, use it for
27           the HTML table summary attribute -->
28      <xsl:when test="processing-instruction('dbhtml')">
29        <xsl:variable name="summary">
30          <xsl:call-template name="dbhtml-attribute">
31            <xsl:with-param name="pis"
32                            select="processing-instruction('dbhtml')[1]"/>
33            <xsl:with-param name="attribute" select="'table-summary'"/>
34          </xsl:call-template>
35        </xsl:variable>
36        <xsl:if test="$summary != ''">
37          <xsl:attribute name="summary">
38            <xsl:value-of select="$summary"/>
39          </xsl:attribute>
40        </xsl:if>
41      </xsl:when>
42      <!-- Otherwise, if there's a title, use that -->
43      <xsl:when test="/title">
44        <xsl:attribute name="summary">
45          <xsl:value-of select="string(/title)"/>
46        </xsl:attribute>
47      </xsl:when>
48      <!-- Otherwise, forget the whole idea -->
49      <xsl:otherwise><!-- nevermind --></xsl:otherwise>
50    </xsl:choose>
51
52    <xsl:if test="../@pgwide=1">
53      <xsl:attribute name="width">100%</xsl:attribute>
54    </xsl:if>
55
56<!-- this is wrong, align on tgroup gives the default alignment for table
57     cells, not the alignment for the table itself...
58    <xsl:if test="@align">
59      <xsl:attribute name="align">
60        <xsl:value-of select="@align"/>
61      </xsl:attribute>
62    </xsl:if>
63-->
64
65    <xsl:choose>
66      <xsl:when test="../@frame='none'">
67        <xsl:attribute name="border">0</xsl:attribute>
68      </xsl:when>
69      <xsl:otherwise>
70        <xsl:attribute name="border">1</xsl:attribute>
71      </xsl:otherwise>
72    </xsl:choose>
73
74    <xsl:variable name="vendor" select="system-property('xsl:vendor')"/>
75
76    <xsl:variable name="colgroup">
77      <colgroup>
78        <xsl:call-template name="generate.colgroup">
79          <xsl:with-param name="cols" select="@cols"/>
80        </xsl:call-template>
81      </colgroup>
82    </xsl:variable>
83
84    <xsl:variable name="explicit.table.width">
85      <xsl:call-template name="dbhtml-attribute">
86        <xsl:with-param name="pis"
87                        select="/processing-instruction('dbhtml')[1]"/>
88        <xsl:with-param name="attribute" select="'table-width'"/>
89      </xsl:call-template>
90    </xsl:variable>
91
92    <xsl:variable name="table.width">
93      <xsl:choose>
94        <xsl:when test="$explicit.table.width != ''">
95          <xsl:value-of select="$explicit.table.width"/>
96        </xsl:when>
97        <xsl:when test="$default.table.width = ''">
98          <xsl:text>100%</xsl:text>
99        </xsl:when>
100        <xsl:otherwise>
101          <xsl:value-of select="$default.table.width"/>
102        </xsl:otherwise>
103      </xsl:choose>
104    </xsl:variable>
105
106    <xsl:if test="$default.table.width != ''
107                  or $explicit.table.width != ''">
108      <xsl:attribute name="width">
109        <xsl:choose>
110          <xsl:when test="contains($table.width, '%')">
111            <xsl:value-of select="$table.width"/>
112          </xsl:when>
113          <xsl:when test="$use.extensions != 0
114                          and $tablecolumns.extension != 0">
115            <xsl:choose>
116              <xsl:when test="contains($vendor, 'SAXON 6')">
117                <xsl:value-of select="stbl:convertLength($table.width)"/>
118              </xsl:when>
119              <xsl:when test="contains($vendor, 'SAXON 5')">
120                <!-- the saxon5 extension doesn't support this (yet) -->
121                <xsl:value-of select="$table.width"/>
122              </xsl:when>
123              <xsl:when test="contains($vendor, 'Apache Software Foundation')">
124                <xsl:value-of select="xtbl:convertLength($table.width)"/>
125              </xsl:when>
126              <xsl:otherwise>
127                <xsl:message terminate="yes">
128                  <xsl:text>Don't know how to do convert lengths with </xsl:text>
129                  <xsl:value-of select="$vendor"/>
130                </xsl:message>
131              </xsl:otherwise>
132            </xsl:choose>
133          </xsl:when>
134          <xsl:otherwise>
135            <xsl:value-of select="$table.width"/>
136          </xsl:otherwise>
137        </xsl:choose>
138      </xsl:attribute>
139    </xsl:if>
140
141    <xsl:choose>
142      <xsl:when test="$use.extensions != 0
143                      and $tablecolumns.extension != 0">
144        <xsl:choose>
145          <xsl:when test="contains($vendor, 'SAXON 6')">
146            <xsl:copy-of select="stbl:adjustColumnWidths($colgroup)"/>
147          </xsl:when>
148          <xsl:when test="contains($vendor, 'SAXON 5')">
149            <!-- the saxon5 extension doesn't support this (yet) -->
150            <xsl:copy-of select="$colgroup"/>
151          </xsl:when>
152          <xsl:when test="contains($vendor, 'Apache Software Foundation')">
153            <xsl:copy-of select="xtbl:adjustColumnWidths($colgroup)"/>
154          </xsl:when>
155          <xsl:otherwise>
156            <xsl:message terminate="yes">
157              <xsl:text>Don't know how to do adjust column widths with </xsl:text>
158              <xsl:value-of select="$vendor"/>
159            </xsl:message>
160          </xsl:otherwise>
161        </xsl:choose>
162      </xsl:when>
163      <xsl:otherwise>
164        <xsl:copy-of select="$colgroup"/>
165      </xsl:otherwise>
166    </xsl:choose>
167
168    <xsl:apply-templates select="thead"/>
169    <xsl:apply-templates select="tbody"/>
170    <xsl:apply-templates select="tfoot"/>
171
172    <xsl:if test=".//footnote">
173      <tr>
174        <td colspan="{@cols}">
175          <xsl:apply-templates select=".//footnote" 
176                               mode="table.footnote.mode"/>
177        </td>
178      </tr>
179    </xsl:if>
180  </table>
181</xsl:template>
182
183<xsl:template match="tgroup/processing-instruction('dbhtml')">
184  <xsl:variable name="summary">
185    <xsl:call-template name="dbhtml-attribute">
186      <xsl:with-param name="pis" select="."/>
187      <xsl:with-param name="attribute" select="'table-summary'"/>
188    </xsl:call-template>
189  </xsl:variable>
190
191  <!-- Suppress the table-summary PI -->
192  <xsl:if test="$summary = ''">
193    <xsl:processing-instruction name="dbhtml">
194      <xsl:value-of select="."/>
195    </xsl:processing-instruction>
196  </xsl:if>
197</xsl:template>
198
199<xsl:template match="colspec"></xsl:template>
200
201<xsl:template match="spanspec"></xsl:template>
202
203<xsl:template match="thead|tfoot">
204  <xsl:element name="{name(.)}">
205    <xsl:if test="@align">
206      <xsl:attribute name="align">
207        <xsl:value-of select="@align"/>
208      </xsl:attribute>
209    </xsl:if>
210    <xsl:if test="@char">
211      <xsl:attribute name="char">
212        <xsl:value-of select="@char"/>
213      </xsl:attribute>
214    </xsl:if>
215    <xsl:if test="@charoff">
216      <xsl:attribute name="charoff">
217        <xsl:value-of select="@charoff"/>
218      </xsl:attribute>
219    </xsl:if>
220    <xsl:if test="@valign">
221      <xsl:attribute name="valign">
222        <xsl:value-of select="@valign"/>
223      </xsl:attribute>
224    </xsl:if>
225
226    <xsl:apply-templates/>
227  </xsl:element>
228</xsl:template>
229
230<xsl:template match="tbody">
231  <tbody>
232    <xsl:if test="@align">
233      <xsl:attribute name="align">
234        <xsl:value-of select="@align"/>
235      </xsl:attribute>
236    </xsl:if>
237    <xsl:if test="@char">
238      <xsl:attribute name="char">
239        <xsl:value-of select="@char"/>
240      </xsl:attribute>
241    </xsl:if>
242    <xsl:if test="@charoff">
243      <xsl:attribute name="charoff">
244        <xsl:value-of select="@charoff"/>
245      </xsl:attribute>
246    </xsl:if>
247    <xsl:if test="@valign">
248      <xsl:attribute name="valign">
249        <xsl:value-of select="@valign"/>
250      </xsl:attribute>
251    </xsl:if>
252
253    <xsl:apply-templates/>
254  </tbody>
255</xsl:template>
256
257<xsl:template match="row">
258  <tr>
259    <xsl:if test="@align">
260      <xsl:attribute name="align">
261        <xsl:value-of select="@align"/>
262      </xsl:attribute>
263    </xsl:if>
264    <xsl:if test="@char">
265      <xsl:attribute name="char">
266        <xsl:value-of select="@char"/>
267      </xsl:attribute>
268    </xsl:if>
269    <xsl:if test="@charoff">
270      <xsl:attribute name="charoff">
271        <xsl:value-of select="@charoff"/>
272      </xsl:attribute>
273    </xsl:if>
274    <xsl:if test="@valign">
275      <xsl:attribute name="valign">
276        <xsl:value-of select="@valign"/>
277      </xsl:attribute>
278    </xsl:if>
279
280    <xsl:apply-templates/>
281  </tr>
282</xsl:template>
283
284<xsl:template match="thead/row/entry">
285  <xsl:call-template name="process.cell">
286    <xsl:with-param name="cellgi">th</xsl:with-param>
287  </xsl:call-template>
288</xsl:template>
289
290<xsl:template match="tbody/row/entry">
291  <xsl:call-template name="process.cell">
292    <xsl:with-param name="cellgi">td</xsl:with-param>
293  </xsl:call-template>
294</xsl:template>
295
296<xsl:template match="tfoot/row/entry">
297  <xsl:call-template name="process.cell">
298    <xsl:with-param name="cellgi">th</xsl:with-param>
299  </xsl:call-template>
300</xsl:template>
301
302<xsl:template name="process.cell">
303  <xsl:param name="cellgi">td</xsl:param>
304  <xsl:variable name="empty.cell" select="count(node()) = 0"/>
305
306  <xsl:variable name="entry.colnum">
307    <xsl:call-template name="entry.colnum"/>
308  </xsl:variable>
309
310  <xsl:if test="$entry.colnum != ''">
311    <xsl:variable name="prev.entry" select="preceding-sibling::*[1]"/>
312    <xsl:variable name="prev.ending.colnum">
313      <xsl:choose>
314        <xsl:when test="$prev.entry">
315          <xsl:call-template name="entry.ending.colnum">
316            <xsl:with-param name="entry" select="$prev.entry"/>
317          </xsl:call-template>
318        </xsl:when>
319        <xsl:otherwise>0</xsl:otherwise>
320      </xsl:choose>
321    </xsl:variable>
322
323    <!-- 1.31: removed add-empty-entries; there's no practical way for
324         XSLT to keep track of "overhang" from morerows in previous rows.
325         At least none that I can think of. -->
326  </xsl:if>
327
328  <xsl:element name="{$cellgi}">
329    <xsl:if test="@morerows">
330      <xsl:attribute name="rowspan">
331        <xsl:value-of select="@morerows+1"/>
332      </xsl:attribute>
333    </xsl:if>
334    <xsl:if test="@namest">
335      <xsl:attribute name="colspan">
336        <xsl:call-template name="calculate.colspan"/>
337      </xsl:attribute>
338    </xsl:if>
339    <xsl:if test="@align">
340      <xsl:attribute name="align">
341        <xsl:value-of select="@align"/>
342      </xsl:attribute>
343    </xsl:if>
344    <xsl:if test="@char">
345      <xsl:attribute name="char">
346        <xsl:value-of select="@char"/>
347      </xsl:attribute>
348    </xsl:if>
349    <xsl:if test="@charoff">
350      <xsl:attribute name="charoff">
351        <xsl:value-of select="@charoff"/>
352      </xsl:attribute>
353    </xsl:if>
354    <xsl:if test="@valign">
355      <xsl:attribute name="valign">
356        <xsl:value-of select="@valign"/>
357      </xsl:attribute>
358    </xsl:if>
359
360    <xsl:if test="not(preceding-sibling::*)
361                  and ancestor::row/@id">
362      <a name="{ancestor::row/@id}"/>
363    </xsl:if>
364
365    <xsl:if test="@id">
366      <a name="{@id}"/>
367    </xsl:if>
368
369    <xsl:choose>
370      <xsl:when test="$empty.cell">
371        <xsl:text>&#160;</xsl:text>
372      </xsl:when>
373      <xsl:otherwise>
374        <xsl:apply-templates/>
375      </xsl:otherwise>
376    </xsl:choose>
377  </xsl:element>
378</xsl:template>
379
380<xsl:template name="entry.colnum">
381  <xsl:param name="entry" select="."/>
382
383  <xsl:choose>
384    <xsl:when test="$entry/@colname">
385      <xsl:variable name="colname" select="$entry/@colname"/>
386      <xsl:variable name="colspec"
387                    select="$entry/ancestor::tgroup/colspec[@colname=$colname]"/>
388      <xsl:call-template name="colspec.colnum">
389        <xsl:with-param name="colspec" select="$colspec"/>
390      </xsl:call-template>
391    </xsl:when>
392    <xsl:when test="$entry/@namest">
393      <xsl:variable name="namest" select="$entry/@namest"/>
394      <xsl:variable name="colspec"
395                    select="$entry/ancestor::tgroup/colspec[@colname=$namest]"/>
396      <xsl:call-template name="colspec.colnum">
397        <xsl:with-param name="colspec" select="$colspec"/>
398      </xsl:call-template>
399    </xsl:when>
400    <xsl:when test="count($entry/preceding-sibling::*) = 0">1</xsl:when>
401    <xsl:otherwise>
402      <xsl:variable name="pcol">
403        <xsl:call-template name="entry.ending.colnum">
404          <xsl:with-param name="entry"
405                          select="$entry/preceding-sibling::*[1]"/>
406        </xsl:call-template>
407      </xsl:variable>
408      <xsl:value-of select="$pcol + 1"/>
409    </xsl:otherwise>
410  </xsl:choose>
411</xsl:template>
412
413<doc:template name="entry.colnum" xmlns="">
414<refpurpose>Determine the column number in which a given entry occurs</refpurpose>
415<refdescription>
416<para>If an <sgmltag>entry</sgmltag> has a
417<sgmltag class="attribute">colname</sgmltag> or
418<sgmltag class="attribute">namest</sgmltag> attribute, this template
419will determine the number of the column in which the entry should occur.
420For other <sgmltag>entry</sgmltag>s, nothing is returned.</para>
421</refdescription>
422<refparameter>
423<variablelist>
424<varlistentry><term>entry</term>
425<listitem>
426<para>The <sgmltag>entry</sgmltag>-element which is to be tested.</para>
427</listitem>
428</varlistentry>
429</variablelist>
430</refparameter>
431
432<refreturn>
433<para>This template returns the column number if it can be determined,
434or nothing (the empty string)</para>
435</refreturn>
436</doc:template>
437
438<xsl:template name="entry.ending.colnum">
439  <xsl:param name="entry" select="."/>
440
441  <xsl:choose>
442    <xsl:when test="$entry/@colname">
443      <xsl:variable name="colname" select="$entry/@colname"/>
444      <xsl:variable name="colspec"
445                    select="$entry/ancestor::tgroup/colspec[@colname=$colname]"/>
446      <xsl:call-template name="colspec.colnum">
447        <xsl:with-param name="colspec" select="$colspec"/>
448      </xsl:call-template>
449    </xsl:when>
450    <xsl:when test="$entry/@nameend">
451      <xsl:variable name="nameend" select="$entry/@nameend"/>
452      <xsl:variable name="colspec"
453                    select="$entry/ancestor::tgroup/colspec[@colname=$nameend]"/>
454      <xsl:call-template name="colspec.colnum">
455        <xsl:with-param name="colspec" select="$colspec"/>
456      </xsl:call-template>
457    </xsl:when>
458    <xsl:when test="count($entry/preceding-sibling::*) = 0">1</xsl:when>
459    <xsl:otherwise>
460      <xsl:variable name="pcol">
461        <xsl:call-template name="entry.ending.colnum">
462          <xsl:with-param name="entry"
463                          select="$entry/preceding-sibling::*[1]"/>
464        </xsl:call-template>
465      </xsl:variable>
466      <xsl:value-of select="$pcol + 1"/>
467    </xsl:otherwise>
468  </xsl:choose>
469</xsl:template>
470
471
472<xsl:template name="colspec.colnum">
473  <xsl:param name="colspec" select="."/>
474  <xsl:choose>
475    <xsl:when test="$colspec/@colnum">
476      <xsl:value-of select="$colspec/@colnum"/>
477    </xsl:when>
478    <xsl:when test="$colspec/preceding-sibling::colspec">
479      <xsl:variable name="prec.colspec.colnum">
480        <xsl:call-template name="colspec.colnum">
481          <xsl:with-param name="colspec"
482                          select="$colspec/preceding-sibling::colspec[1]"/>
483        </xsl:call-template>
484      </xsl:variable>
485      <xsl:value-of select="$prec.colspec.colnum + 1"/>
486    </xsl:when>
487    <xsl:otherwise>1</xsl:otherwise>
488  </xsl:choose>
489</xsl:template>
490
491<xsl:template name="generate.colgroup">
492  <xsl:param name="cols" select="1"/>
493  <xsl:param name="count" select="1"/>
494  <xsl:choose>
495    <xsl:when test="$count>$cols"></xsl:when>
496    <xsl:otherwise>
497      <xsl:call-template name="generate.col">
498        <xsl:with-param name="countcol" select="$count"/>
499      </xsl:call-template>
500      <xsl:call-template name="generate.colgroup">
501        <xsl:with-param name="cols" select="$cols"/>
502        <xsl:with-param name="count" select="$count+1"/>
503      </xsl:call-template>
504    </xsl:otherwise>
505  </xsl:choose>
506</xsl:template>
507
508<xsl:template name="generate.col">
509  <xsl:param name="countcol">1</xsl:param>
510  <xsl:param name="colspecs" select="/colspec"/>
511  <xsl:param name="count">1</xsl:param>
512  <xsl:param name="colnum">1</xsl:param>
513
514  <xsl:choose>
515    <xsl:when test="$count>count($colspecs)">
516      <col/>
517    </xsl:when>
518    <xsl:otherwise>
519      <xsl:variable name="colspec" select="$colspecs[$count=position()]"/>
520      <xsl:variable name="colspec.colnum">
521        <xsl:choose>
522          <xsl:when test="$colspec/@colnum">
523            <xsl:value-of select="$colspec/@colnum"/>
524          </xsl:when>
525          <xsl:otherwise>
526            <xsl:value-of select="$colnum"/>
527          </xsl:otherwise>
528        </xsl:choose>
529      </xsl:variable>
530
531      <xsl:choose>
532        <xsl:when test="$colspec.colnum=$countcol">
533          <col>
534            <xsl:if test="$colspec/@colwidth
535                          and $use.extensions != 0
536                          and $tablecolumns.extension != 0">
537              <xsl:attribute name="width">
538                <xsl:value-of select="$colspec/@colwidth"/>
539              </xsl:attribute>
540            </xsl:if>
541
542            <xsl:choose>
543              <xsl:when test="$colspec/@align">
544                <xsl:attribute name="align">
545                  <xsl:value-of select="$colspec/@align"/>
546                </xsl:attribute>
547              </xsl:when>
548              <!-- Suggested by Pavel ZAMPACH <zampach@nemcb.cz> -->
549              <xsl:when test="$colspecs/ancestor::tgroup/@align">
550                <xsl:attribute name="align">
551                  <xsl:value-of select="$colspecs/ancestor::tgroup/@align"/>
552                </xsl:attribute>
553              </xsl:when>
554            </xsl:choose>
555
556            <xsl:if test="$colspec/@char">
557              <xsl:attribute name="char">
558                <xsl:value-of select="$colspec/@char"/>
559              </xsl:attribute>
560            </xsl:if>
561            <xsl:if test="$colspec/@charoff">
562              <xsl:attribute name="charoff">
563                <xsl:value-of select="$colspec/@charoff"/>
564              </xsl:attribute>
565            </xsl:if>
566          </col>
567        </xsl:when>
568        <xsl:otherwise>
569          <xsl:call-template name="generate.col">
570            <xsl:with-param name="countcol" select="$countcol"/>
571            <xsl:with-param name="colspecs" select="$colspecs"/>
572            <xsl:with-param name="count" select="$count+1"/>
573            <xsl:with-param name="colnum">
574              <xsl:choose>
575                <xsl:when test="$colspec/@colnum">
576                  <xsl:value-of select="$colspec/@colnum + 1"/>
577                </xsl:when>
578                <xsl:otherwise>
579                  <xsl:value-of select="$colnum + 1"/>
580                </xsl:otherwise>
581              </xsl:choose>
582            </xsl:with-param>
583           </xsl:call-template>
584        </xsl:otherwise>
585      </xsl:choose>
586    </xsl:otherwise>
587  </xsl:choose>
588
589</xsl:template>
590
591<xsl:template name="colspec.colwidth">
592  <!-- when this macro is called, the current context must be an entry -->
593  <xsl:param name="colname"></xsl:param>
594  <!-- .. = row, ../.. = thead|tbody, ../../.. = tgroup -->
595  <xsl:param name="colspecs" select="/tgroup/colspec"/>
596  <xsl:param name="count">1</xsl:param>
597  <xsl:choose>
598    <xsl:when test="$count>count($colspecs)"></xsl:when>
599    <xsl:otherwise>
600      <xsl:variable name="colspec" select="$colspecs[$count=position()]"/>
601      <xsl:choose>
602        <xsl:when test="$colspec/@colname=$colname">
603          <xsl:value-of select="$colspec/@colwidth"/>
604        </xsl:when>
605        <xsl:otherwise>
606          <xsl:call-template name="colspec.colwidth">
607            <xsl:with-param name="colname" select="$colname"/>
608            <xsl:with-param name="colspecs" select="$colspecs"/>
609            <xsl:with-param name="count" select="$count+1"/>
610          </xsl:call-template>
611        </xsl:otherwise>
612      </xsl:choose>
613    </xsl:otherwise>
614  </xsl:choose>
615</xsl:template>
616
617<xsl:template name="calculate.colspan">
618  <xsl:param name="entry" select="."/>
619  <xsl:variable name="namest" select="$entry/@namest"/>
620  <xsl:variable name="nameend" select="$entry/@nameend"/>
621
622  <xsl:variable name="scol">
623    <xsl:call-template name="colspec.colnum">
624      <xsl:with-param name="colspec"
625                      select="$entry/ancestor::tgroup/colspec[@colname=$namest]"/>
626    </xsl:call-template>
627  </xsl:variable>
628  <xsl:variable name="ecol">
629    <xsl:call-template name="colspec.colnum">
630      <xsl:with-param name="colspec"
631                      select="$entry/ancestor::tgroup/colspec[@colname=$nameend]"/>
632    </xsl:call-template>
633  </xsl:variable>
634  <xsl:value-of select="$ecol - $scol + 1"/>
635</xsl:template>
636
637</xsl:stylesheet>
638
639