[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

[xsl] Stylesheet for converting XHTML tables to CALS


Subject: [xsl] Stylesheet for converting XHTML tables to CALS
From: "Huditsch, Roman \(LNG-VIE\)" <Roman.Huditsch@xxxxxxxxxxxxx>
Date: Mon, 6 Mar 2006 12:33:49 +0100

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.huditsch@xxxxxxxxxxxxx
-->
	<!--
-->
	<!--
===================================================================
-->
	<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[@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>


Current Thread
Keywords