Re: [xsl] Re: HTML table colspec and spanspec problem

Subject: Re: [xsl] Re: HTML table colspec and spanspec problem
From: "Siddhi Thakkar" <siddhi.thakkar@xxxxxxxxxxxxxx>
Date: Sat, 23 Jan 2010 12:11:53 +0530
Hi again,
Sorry about that Robby, its just that I am really novice when it comes posting queries. Thanks very much for helping me improve on that front. Although I am not quite sure how the text "3D" was inserted before every quote"". I did not put it, might be a formatting issue, if you get it this time- can you please help me on that as well so that I can take care of such things in future? Thanks. I also wanted to keep the mail small but cant really help because it has to cover all the scenarios possible and my current code is also pretty lengthy. Sorry about that again.
Here is the problem again. Please note that its only the colspec and spanspec generation that we need to work for, I am posting the INPUT XML, DESIRED OUTPUT and the CURRENT XSL CODE.


INPUT XML:
<html>
<body>
<div class="divTable">
<table>
<tbody>
<tr>
<td align="center" class="tch">col1</td>
<td align="right" class="tch">col2</td>
<td align="center" class="tch">col3</td>
<td align="right" class="tch">col4</td>
<td align="center" class="tch">col5</td>
</tr>
<tr>
<td align="center" class="tb">col1</td>
<td align="center" class="tb">col2</td>
<td align="center" class="tb">col3</td>
<td align="right" class="tb">col4</td>
<td align="center" class="tb">col5</td>
</tr>
<tr>
<td align="right" colspan="2" class="tb">col1 and col2</td>
<td align="right" colspan="2" class="tb">col3 and col4</td>
<td align="right" class="tb">col5</td>
</tr>
<tr>
<td align="right" colspan="2" class="tb">col1 and col2</td>
<td align="right" colspan="3" class="tb">col3, col4 and col5</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>


DESIRED OUTPUT:
<body>
<table>
<tgroup cols="5">
<!-- For colspec, we only need to generate align attribute, rest is done. The value of align for colspec name="col1" is center because all the entries with name as col1 have it, for colspec name="col 2" number of name="col2" entries containing right is equal to the no. of entries containing center. But for colspec name="col5", number of name=col5 entries containing center is gretear than the ones that contain right. Similarly, for spanspec values.-->
<colspec name="col1" width="" align="center"/>
<colspec name="col2" width="" align="right"/>
<colspec name="col3" width="" align="center"/>
<colspec name="col4" width="" align="right"/>
<colspec name="col5" width="" align="center"/>
<spanspec name="1to2" namestart="col1" nameend="col2" width=""align="right"/>
<spanspec name="3to4" namestart="col3" nameend="col4" width=""align="right"/>
<spanspec name="3to5" namestart="col3" nameend="col5" width=""align="right"/>
<thead>
<row>
<entry class="tch" align="center" name="col1">col1</entry>
<entry class="tch" align="right" name="col2">col2</entry>
<entry class="tch" align="center" name="col3">col3</entry>
<entry class="tch" align="right" name="col4">col4</entry>
<entry class="tch" align="center" name="col5">col5</entry>
</row>
</thead>
<tbody>
<row>
<entry class="tb" align="center" name="col1">col1</entry>
<entry class="tb" align="center" name="col2">col2</entry>
<entry class="tb" align="center" name="col3">col3</entry>
<entry class="tb" align="right" name="col4">col4</entry>
<entry class="tb" align="center" name="col5">col5</entry>
</row>
<row>
<entry class="tb" colspan="2" align="right" name="1to2">col1 and col2</entry>
<entry class="tb" colspan="2" align="right" name="3to4">col3 and col4</entry>
<entry class="tb" align="right" name="col5">col5</entry>
</row>
<row>
<entry class="tb" colspan="2" align="right" name="1to2">col1 and col2</entry>
<entry class="tb" colspan="3" align="right" name="3to5">col3, col4 and col5</entry>
</row>
</tbody>
</tgroup>
</table>
</body>



CURRENT XSL CODE:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns:xs="http://www.w3.org/2001/XMLSchema"; xmlns:xsd="http://www.w3.org/2001/XMLSchema"; exclude-result-prefixes="xs xsd" version="2.0">


<xsl:template name="generate-colspecs">
<xsl:param name="number" as="xsd:integer"/>
<xsl:variable name="max_column">
<xsl:if test="not(table/tbody/tr/td[@colspan])">
<xsl:value-of
select="for $x in table/tbody return (max((for $y in table/tbody/tr return count($y/td))))"
/>
</xsl:if>
<xsl:if test="table/tbody/tr/td[@colspan]">
<xsl:variable name="tr_without_colspan">
<xsl:value-of
select="for $x in table/tbody return if (table/tbody/tr[not(child::td[@colspan])]) then (max((for $y in table/tbody/tr[not(child::td[@colspan])] return count($y/td)))) else 0"
/>
</xsl:variable>
<xsl:variable name="tr_with_colspan">
<xsl:value-of
select="for $x in table/tbody return (max((for $y in table/tbody/tr[child::td[@colspan]] return number(count($y/td[not(@colspan)]) + sum($y/td/@colspan)))))"
/>
</xsl:variable>
<xsl:value-of select="max(($tr_with_colspan,$tr_without_colspan))"/>
</xsl:if>
</xsl:variable>
<xsl:if test="not($number &gt; $max_column)">
<xsl:element name="colspec">
<xsl:attribute name="name">
<xsl:text>col</xsl:text>
<xsl:value-of select="$number"/>
</xsl:attribute>
<xsl:attribute name="width"/>
</xsl:element>
<xsl:call-template name="generate-colspecs">
<xsl:with-param name="number" select="$number+1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>


<xsl:template name="generate-spanspec">
<xsl:for-each select="table/tbody/tr/td[@colspan]">

<xsl:variable name="starting_value">
<xsl:value-of select="(count(preceding-sibling::td)+1+sum(preceding-sibling::td/@colspan)) - count(preceding-sibling::td[@colspan])"/>
</xsl:variable>
<xsl:variable name="end_value">
<xsl:value-of select="(count(preceding-sibling::td)+sum(preceding-sibling::td/@colspan)+@colspan) - count(preceding-sibling::td[@colspan])"/>
</xsl:variable>


<xsl:element name="spanspec">
<xsl:attribute name="name">

<xsl:if test="not(preceding-sibling::td[@colspan])">
<xsl:value-of select="count(preceding-sibling::td)+1"/>
<xsl:text>to</xsl:text>
<xsl:value-of select="(count(preceding-sibling::td)+1+@colspan)-1"/>
</xsl:if>
<xsl:if test="preceding-sibling::td[@colspan]">
<xsl:value-of select="(count(preceding-sibling::td)+1+sum(preceding-sibling::td/@colspan)) - count(preceding-sibling::td[@colspan])"/>
<xsl:text>to</xsl:text>
<xsl:value-of select="(count(preceding-sibling::td)+sum(preceding-sibling::td/@colspan)+@colspan) - count(preceding-sibling::td[@colspan])"/>
</xsl:if>
</xsl:attribute>
<xsl:attribute name="namestart">
<xsl:text>col</xsl:text>
<xsl:if test="not(preceding-sibling::td[@colspan])">
<xsl:value-of select="count(preceding-sibling::td)+1"/>
</xsl:if>
<xsl:if test="preceding-sibling::td[@colspan]">
<xsl:value-of select="(count(preceding-sibling::td)+1+sum(preceding-sibling::td/@colspan)) - count(preceding-sibling::td[@colspan])"/>
</xsl:if>
</xsl:attribute>
<xsl:attribute name="nameend">
<xsl:text>col</xsl:text>
<xsl:if test="not(preceding-sibling::td[@colspan])">
<xsl:value-of select="(count(preceding-sibling::td)+1+@colspan)-1"/>
</xsl:if>
<xsl:if test="preceding-sibling::td[@colspan]">
<xsl:value-of select="(count(preceding-sibling::td)+sum(preceding-sibling::td/@colspan)+@colspan) - count(preceding-sibling::td[@colspan])"/>
</xsl:if>
</xsl:attribute>
<xsl:attribute name="width"/>
</xsl:element>
</xsl:for-each>
</xsl:template>


<xsl:template match="body">
<body>
<xsl:apply-templates/>
</body>
</xsl:template>


<xsl:template match="div">
<table>
<tgroup>
<xsl:attribute name="cols">
<xsl:if test="not(table/tbody/tr/td[@colspan])">
<xsl:value-of
select="for $x in table/tbody return (max((for $y in table/tbody/tr return count($y/td))))"
/>
</xsl:if>
<xsl:if test="table/tbody/tr/td[@colspan]">
<xsl:variable name="tr_without_colspan">
<xsl:value-of
select="for $x in table/tbody return if (table/tbody/tr[not(child::td[@colspan])]) then (max((for $y in table/tbody/tr[not(child::td[@colspan])] return count($y/td)))) else 0"
/>
</xsl:variable>
<xsl:variable name="tr_with_colspan">
<xsl:value-of
select="for $x in table/tbody return (max((for $y in table/tbody/tr[child::td[@colspan]] return number(count($y/td[not(@colspan)]) + sum($y/td/@colspan)))))"
/>
</xsl:variable>
<xsl:value-of select="max(($tr_with_colspan,$tr_without_colspan))"/>
</xsl:if>
</xsl:attribute>
<xsl:call-template name="generate-colspecs">
<xsl:with-param name="number">1</xsl:with-param>
</xsl:call-template>
<xsl:call-template name="generate-spanspec"/>
<xsl:apply-templates/>


</tgroup>
</table>
</xsl:template>


<xsl:template match="tr" mode="abc">
<xsl:if test="preceding::tr[1][child::td[@class='tch']]">
<row>
<xsl:apply-templates/>
</row>
<xsl:apply-templates select="following::tr[1][child::td[@class='tch']]" mode="abc"/>
</xsl:if>
</xsl:template>


<xsl:template match="tr" mode="def">
<xsl:if test="preceding::tr[1][child::td[@class='tbtm']]">
<row>
<xsl:apply-templates/>
</row>
<xsl:apply-templates select="following::tr[1][child::td[@class='tbtm']]" mode="def"/>
</xsl:if>
</xsl:template>


<xsl:template match="tr" mode="xyz">
<xsl:if test="preceding::tr[1][child::td[@class='tb']]">
<row>
<xsl:apply-templates/>
</row>
<xsl:apply-templates select="following::tr[1][child::td[@class='tb']]" mode="xyz"/>
</xsl:if>
</xsl:template>



<xsl:template match="tr">
<xsl:if test="child::td[@class='tch'][not(preceding::tr[1][child::td[@class='tch']])]">
<thead>
<row>
<xsl:apply-templates/>
</row>
<xsl:if test="following::*[1][self::tr[child::td[@class='tch']]]">
<xsl:apply-templates select="following::tr[1][child::td[@class='tch']]"
mode="abc"/>
</xsl:if>
</thead>
</xsl:if>
<xsl:if test="child::td[@class='tbtm'][not(preceding::tr[1][child::td[@class='tbtm']])]">
<tfoot>
<row>
<xsl:apply-templates/>
</row>
<xsl:if test="following::*[1][self::tr[child::td[@class='tbtm']]]">
<xsl:apply-templates select="following::tr[1][child::td[@class='tbtm']]"
mode="def"/>
</xsl:if>
</tfoot>
</xsl:if>
<xsl:if test="child::td[@class='tb'][not(preceding::tr[1][child::td[@class='tb']])]">
<tbody>
<row>
<xsl:apply-templates/>
</row>
<xsl:if test="following::*[1][self::tr[child::td[@class='tb']]]">
<xsl:apply-templates select="following::tr[1][child::td[@class='tb']]"
mode="xyz"/>
</xsl:if>
</tbody>
</xsl:if>
</xsl:template>



<xsl:template match="tbody"> <xsl:apply-templates/> </xsl:template>


<xsl:template match="td">
<entry>
<xsl:attribute name="class">
<xsl:value-of select="@class"/>
</xsl:attribute>
<xsl:if test="@colspan">
<xsl:attribute name="colspan">
<xsl:value-of select="@colspan"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="@align">
<xsl:attribute name="align">
<xsl:value-of select="@align"/>
</xsl:attribute>
</xsl:if>
<xsl:attribute name="name">
<xsl:text>col-</xsl:text>
<xsl:if test="not(@colspan)">
<xsl:if test="not(preceding-sibling::td[@colspan])">
<xsl:value-of select="count(preceding-sibling::td)+1"/>
</xsl:if>
<xsl:if test="preceding-sibling::td[@colspan]">
<xsl:variable name="colspan_values"
select="sum(preceding-sibling::td[@colspan]/@colspan)"/>
<xsl:variable name="td_number" select="count(preceding-sibling::td)"/>
<xsl:variable name="colspan_td_number"
select="count(preceding-sibling::td[@colspan])"/>
<xsl:value-of select="($td_number+$colspan_values+1) - $colspan_td_number"/>
</xsl:if>
</xsl:if>
<xsl:if test="@colspan">
<xsl:if test="not(preceding-sibling::td[@colspan])">
<xsl:value-of select="count(preceding-sibling::td)+1"/>
<xsl:text>to</xsl:text>
<xsl:variable name="td_number" select="count(preceding-sibling::td)"/>
<xsl:variable name="colspan" select="@colspan"/>
<xsl:value-of select="count(preceding-sibling::td)+@colspan"/>
</xsl:if>
<xsl:if test="preceding-sibling::td[@colspan]">
<xsl:variable name="colspan_values"
select="sum(preceding-sibling::td[@colspan]/@colspan)"/>
<xsl:variable name="td_number" select="count(preceding-sibling::td)"/>
<xsl:variable name="colspan_number"
select="count(preceding-sibling::td[@colspan])"/>
<xsl:variable name="starting_value">
<xsl:value-of select="($td_number+$colspan_values+1) - $colspan_number"
/>
</xsl:variable>
<xsl:value-of select="$starting_value"/>
<xsl:text>to</xsl:text>
<xsl:value-of select="($starting_value+@colspan) - 1"/>
</xsl:if>
</xsl:if>
</xsl:attribute>
<xsl:attribute name="name">


<xsl:if test="not(@colspan) and not(preceding-sibling::td[@colspan])">
<xsl:text>col</xsl:text> <xsl:value-of select="count(preceding-sibling::td)+1"/>
</xsl:if>
<xsl:if test="@colspan and not(preceding-sibling::td[@colspan])">
<xsl:value-of select="count(preceding-sibling::td)+1"/>
<xsl:text>to</xsl:text>
<xsl:variable name="td_number" select="count(preceding-sibling::td)"/>
<xsl:variable name="colspan" select="@colspan"/>
<xsl:value-of select="$colspan + $td_number"/>
</xsl:if>
<xsl:if test="not(@colspan) and preceding-sibling::*[self::td[@colspan]]">
<xsl:text>col</xsl:text> <xsl:variable name="colspan_values"
select="sum(preceding-sibling::td[@colspan]/@colspan)"/>
<xsl:variable name="td_number" select="count(preceding-sibling::td)"/>
<xsl:variable name="colspan_number"
select="count(preceding-sibling::td[@colspan])"/>
<xsl:value-of select="($td_number+$colspan_values+1) - $colspan_number"/>
</xsl:if>
<xsl:if test="@colspan and preceding-sibling::*[self::td[@colspan]]">
<xsl:variable name="colspan_values"
select="sum(preceding-sibling::td[@colspan]/@colspan)"/>
<xsl:variable name="td_number" select="count(preceding-sibling::td)"/>
<xsl:variable name="colspan_number"
select="count(preceding-sibling::td[@colspan])"/>
<xsl:variable name="starting_value">
<xsl:value-of select="($td_number+$colspan_values+1) - $colspan_number"/>
</xsl:variable>
<xsl:value-of select="$starting_value"/>
<xsl:text>to</xsl:text>
<xsl:value-of select="($starting_value+@colspan) - 1"/>
</xsl:if>
</xsl:attribute>
<xsl:apply-templates/>
</entry>
</xsl:template>



<xsl:template match="p"> <p> <xsl:apply-templates/> </p> </xsl:template>


</xsl:stylesheet>




------------------------------

Date: Fri, 22 Jan 2010 09:47:45 +0100
To: <xsl-list@xxxxxxxxxxxxxxxxxxxxxx>
From: "Robby Pelssers" <robby.pelssers@xxxxxxxxx>
Subject: RE: [xsl] Re: HTML table colspec and spanspec problem
Message-ID: <7C655C04B6F59643A1EF66056C0E095E034DF434@xxxxxxxxxxxxxxxxxxxxx>


I took a look at the input and output you sent... please check yourself
but the samples are  totally incorrect and there is no way that xslt
transforms your input into the currentoutput...

Please reply to this thread with correct INDENTED samples after you
remove previous content in order to keep the mail small.

Robby Pelssers

Current Thread