xsl-list
[Top] [All Lists]

Stylesheet for converting XHTML tables to CALS

2006-03-06 04:33:49

Hi everybody,

I just finished my first attempt to transform XHTML tables into tables
conforming to the CALS table model.
Attached is my XSLT 2.0 stylesheet. Every feedback is heartily welcome
:)

with best regards,
Roman


 
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns:ln="http://www.lexisnexis.at/schema/norm";
xmlns:xs="http://www.w3.org/2001/XMLSchema";
xmlns:xsldoc="http://www.bacman.net/XSLdoc";
xmlns:xhtml="http://www.w3.org/1999/xhtml";
exclude-result-prefixes="xsldoc xs ln xhtml"
xmlns="http://www.w3.org/1999/xhtml";>
        <!--
===================================================================
-->
        <!--
-->
        <!-- This Stylesheets converts arbitrary XHTML tables into
tables                  -->
        <!-- conforming to the OASIS CALS model
-->
        <!--
-->
        <!-- Author: Roman Huditsch, 
roman(_dot_)huditsch(_at_)lexisnexis(_dot_)at
-->
        <!--
-->
        <!--
===================================================================
-->
        <xsl:output method="xhtml" version="1.0" encoding="UTF-8"/>
        <xsldoc:author>Roman Huditsch</xsldoc:author>
        <xsldoc:date>March 2, 2006</xsldoc:date>
        <xsldoc:version>Version 0.9</xsldoc:version>
        <!--
===================================================================
-->
        <!-- Per default all existing nodes should be copied into the
result document -->
        <!--
===================================================================
-->
        <xsl:template match="node() | @*">
                <xsl:copy>
                        <xsl:apply-templates select="@* | node()"/>
                </xsl:copy>
        </xsl:template>
        <!--
===================================================================
-->
        <!-- Table
-->
        <!--
===================================================================
-->
        <xsl:template match="xhtml:table">
                <!-- Create param to indicate border handling to child
nodes   -->
                <xsl:param name="border" select="if(starts-with(@border,
'0')) then(xs:boolean(0)) else(xs:boolean(1))" as="xs:boolean"
tunnel="yes"/>
                <table>
                        <xsl:apply-templates select="(@border,
@width)"/>
                        <!-- <tgroup> -->
                        <tgroup>
                                <xsl:message select="concat('Max
Columns: ', ln:max_columns(.))"/>
                                <xsl:call-template
name="generate-colspecs">
                                        <xsl:with-param name="max"
select="ln:max_columns(.)" as="xs:integer"/>
                                </xsl:call-template>
                        </tgroup>
                        <!-- <thead> -->
                        <xsl:apply-templates select="xhtml:thead"/>
                        <!-- <tbody> -->
                        <tbody>
                                <xsl:apply-templates
select="xhtml:tr[not(parent::*[local-name()=('thead', 'tbody',
'tfoot')])] | xhtml:tbody/xhtml:tr"/>
                        </tbody>
                        <!-- <tfoot> -->
                        <xsl:apply-templates select="xhtml:tfoot"/>
                </table>
        </xsl:template>
        <!--
===================================================================
-->
        <!-- Table attributes
-->
        <!--
===================================================================
-->
        <xsl:template match="@border">
                <xsl:attribute name="frame">
                        <xsl:value-of select="if(starts-with(., '0'))
then('none') else('all')"/>
                </xsl:attribute>
        </xsl:template>
        <xsl:template match="xhtml:table/@width">
                <xsl:attribute name="pgwide">
                        <xsl:value-of select="if(.='100%') then('0')
else('1')"/>
                </xsl:attribute>
        </xsl:template>
        <!--
===================================================================
-->
        <!-- colspec
-->
        <!--
===================================================================
-->
        <xsl:template name="generate-colspecs">
                <xsl:param name="border" tunnel="yes"/>
                <xsl:param name="max" as="xs:integer"/>
                <xsl:param name="count" select="1" as="xs:integer"/>
                <xsl:choose>
                        <xsl:when test="$count &gt; $max"/>
                        <xsl:otherwise>
                                <colspec colnum="{$count}"
colname="{concat('col', $count)}" colsep="{if($border) then('1')
else('0')}">
                                        <xsl:choose>
                                                <xsl:when
test="xhtml:colgroup/xhtml:col[$count]/@width">
        
<xsl:apply-templates select="xhtml:colgroup/xhtml:col[$count]/@width"/>
                                                </xsl:when>
                                                <xsl:when test="( ./(*/*
| *)/xhtml:td[$count] | ./(*/* | *)/xhtml:th[$count])/@width">
                                                        <xsl:message
select="concat('Count: ', $count)"/>
        
<xsl:message select="concat('Max: ', $max)"/>
                                                        <xsl:message
select="( ./(*/* | *)/xhtml:td[$count] | ./(*/* |
*)/xhtml:th[$count])/@width"/>
                                                        <xsl:attribute
name="colwidth">
        
<xsl:value-of select="concat(ln:max_width(., $count), '*')"/>
                                                        </xsl:attribute>
                                                </xsl:when>
                                        </xsl:choose>
                                </colspec>
                                <xsl:call-template
name="generate-colspecs">
                                        <xsl:with-param name="max"
select="$max"/>
                                        <xsl:with-param name="count"
select="$count + 1"/>
                                </xsl:call-template>
                        </xsl:otherwise>
                </xsl:choose>
        </xsl:template>
        <!--
===================================================================
-->
        <!-- thead, tfoot
-->
        <!--
===================================================================
-->
        <xsl:template match="xhtml:thead | xhtml:tfoot">
                <xsl:element name="{local-name()}">
                        <xsl:copy-of select="@valign"/>
                        <xsl:apply-templates/>
                </xsl:element>
        </xsl:template>
        <!--
===================================================================
-->
        <!-- TR
-->
        <!--
===================================================================
-->
        <xsl:template match="xhtml:tr">
                <xsl:param name="border" tunnel="yes"/>
                <row rowsep="{if($border) then('1') else('0')}">
                        <xsl:copy-of select="@valign"/>
                        <xsl:apply-templates/>
                </row>
        </xsl:template>
        <!--
===================================================================
-->
        <!-- TD | TH
-->
        <!--
===================================================================
-->
        <xsl:template match="xhtml:th | xhtml:td">
                <xsl:variable name="position"
select="count(preceding-sibling::*) + 1"/>
                <entry>
                        <xsl:if test="@colspan &gt; 1">
                                <xsl:attribute name="namest">
                                        <xsl:value-of
select="concat('col',$position)"/>
                                </xsl:attribute>
                                <xsl:attribute name="nameend">
                                        <xsl:value-of
select="concat('col',$position + number(@colspan) - 1)"/>
                                </xsl:attribute>
                        </xsl:if>
                        <xsl:if test="@rowspan &gt; 1">
                                <xsl:attribute name="morerows">
                                        <xsl:value-of
select="number(@rowspan) - 1"/>
                                </xsl:attribute>
                        </xsl:if>
                        <xsl:copy-of select="@align"/>
                        <xsl:apply-templates/>
                </entry>
        </xsl:template>
        <!--
=======================================================================
-->
        <!-- Function for counting the number of columns
-->
        <!-- Input: Context Element, Output: Maximum Integer
-->
        <!--
=======================================================================
-->
        <xsl:function name="ln:max_columns" as="xs:integer">
                <xsl:param name="context" as="element()"/>
                <xsl:choose>
                        <xsl:when
test="$context/xhtml:colgroup[not(@span)]">
                                <xsl:sequence
select="count($context/xhtml:colgroup/xhtml:col)"/>
                        </xsl:when>
                        <xsl:when test="$context/xhtml:colgroup[(_at_)span]">
                                <xsl:sequence
select="$context/xhtml:colgroup/@span"/>
                        </xsl:when>
                        <xsl:otherwise>
                                <xsl:sequence select="max(for $x in
($context | $context/* )/xhtml:tr  return count($x/xhtml:td))"/>
                        </xsl:otherwise>
                </xsl:choose>
        </xsl:function>
        <!--
========================================================================
======  -->
        <!-- Function for searching the maximun width for a column
-->
        <!-- Input: Context Element, Output: Maximum Integer
-->
        <!--
========================================================================
======  -->
        <xsl:function name="ln:max_width" as="xs:integer">
                <xsl:param name="context" as="element()"/>
                                <xsl:param name="count"
as="xs:integer"/>
                <xsl:sequence select="xs:integer(max(for $x in
($context/* | $context/*/* )/(xhtml:td[$count] |
xhtml:th[$count])/@width return (if($x castable as xs:double) then($x)
else(xs:integer(replace($x, '[a-z%]', ''))))))"/>
        </xsl:function>
        <!--
===================================================================
-->
        <!-- Suppressed elements
-->
        <!--
===================================================================
-->
        <xsl:template match="xhtml:colgroup"/>
</xsl:stylesheet>

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



<Prev in Thread] Current Thread [Next in Thread>