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 > $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 > 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 > 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>
--~--