Subject: RE: [xsl] Omnimark vs. XSL (Saxon) Challenge From: "Andrew Welch" <AWelch@xxxxxxxxxxxxxxx> Date: Thu, 18 Mar 2004 10:20:39 -0000 |
Heres a potential solution... It works by first creating a variable with the colspans normalized, which is easy enough. It then normalizes the rowspans by iterating over the variable a row at time, using two nodesets. One is the current row, one is the previous row ($rowBlock). Where the previous row has a <td> with a rowspan > 1, it copies it to a result variable with the rowspan decremented. Where the previous row just has a normal <td>, it copies the correct <td> from the current row to the result variable. It maintains a pair of pointers to ensure the correct <td>'s are being compared. The 'result variable' is then used as the previous row in the next iteration of the <tr> processing. This is based on the fact that the first row of the table is always complete - it contains the correct number of columns. Currently it gives the result: Col 1= 40% Col 2= 30% Col 3= 20% Col 4= Hopefully you can get what you need from that (and that it's correct!) Performance wise, it produced: 4 rows 256 rows 2.125 106.752 2.135 116.569 2.115 106.027 (using Xselerator with msxml4, pentium 4-M 2ghz 512mb) This is linear, so hopefully you can use it. Please post back any comments/improvements. cheers andrew (apologies for the lack of comments) <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" xmlns:msxsl="urn:schemas-microsoft-com:xslt" extension-element-prefixes="exsl msxsl"> <xsl:variable name="table_with_no_colspans-rtf"> <xsl:apply-templates mode="colspan"/> </xsl:variable> <xsl:variable name="table_with_no_colspans" select="exsl:node-set($table_with_no_colspans-rtf)"/> <xsl:variable name="table_with_no_rowspan-rtf"> <xsl:for-each select="$table_with_no_colspans"> <xsl:apply-templates mode="rowspan"/> </xsl:for-each> </xsl:variable> <xsl:variable name="table_with_no_rowspan" select="exsl:node-set($table_with_no_rowspan-rtf)"/> <xsl:template match="tbody" mode="colspan"> <xsl:apply-templates mode="colspan"/> </xsl:template> <xsl:template match="@*|*" mode="colspan"> <xsl:copy> <xsl:apply-templates select="@*|*" mode="colspan"/> </xsl:copy> </xsl:template> <xsl:template match="td" mode="colspan"> <xsl:choose> <xsl:when test="@colspan"> <td> <xsl:copy-of select="@rowspan"/> <xsl:value-of select="."/> </td> <xsl:call-template name="give_me_tds"> <xsl:with-param name="number-of-tds" select="number(@colspan) - 1"/> <xsl:with-param name="rowspan"> <xsl:choose> <xsl:when test="@rowspan > 1"> <xsl:value-of select="@rowspan"/> </xsl:when> <xsl:otherwise>1</xsl:otherwise> </xsl:choose> </xsl:with-param> </xsl:call-template> </xsl:when> <xsl:otherwise> <td> <xsl:choose> <xsl:when test="@rowspan"> <xsl:copy-of select="@rowspan"/> </xsl:when> <xsl:otherwise> <xsl:copy-of select="@width"/> </xsl:otherwise> </xsl:choose> <xsl:value-of select="."/> </td> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="give_me_tds"> <xsl:param name="number-of-tds" select="'1'"/> <xsl:param name="rowspan"/> <xsl:choose> <xsl:when test="$number-of-tds > 1"> <td rowspan="{$rowspan}"> <xsl:value-of select="."/> </td> <xsl:call-template name="give_me_tds"> <xsl:with-param name="number-of-tds" select="$number-of-tds - 1"/> <xsl:with-param name="rowspan" select="$rowspan"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <td rowspan="{$rowspan}"> <xsl:value-of select="."/> </td> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="/"> <div> <XXXXX><xsl:copy-of select="$table_with_no_colspans"/></XXXXX> <ZZZZZ><xsl:copy-of select="$table_with_no_rowspan"/></ZZZZZ> <xsl:for-each select="$table_with_no_rowspan/*/tr[1]/td"> <xsl:variable name="pos" select="position()"/> <xsl:text/>Col <xsl:value-of select="$pos"/>= <xsl:text/> <xsl:value-of select="$table_with_no_rowspan//tr/td[$pos]/@width"/> <xsl:text> </xsl:text> </xsl:for-each> </div> </xsl:template> <xsl:template match="td" mode="final"> <xsl:copy> <xsl:copy-of select="@width"/> <xsl:apply-templates/> </xsl:copy> </xsl:template> <xsl:template match="table" mode="rowspan"> <div> <xsl:copy-of select="tr[1]"/> <xsl:apply-templates select="tr[2]" mode="rowspan"> <xsl:with-param name="rowBlock" select="tr[1]"/> </xsl:apply-templates> </div> </xsl:template> <xsl:template match="tr" mode="rowspan"> <xsl:param name="rowBlock" select="/.."/> <xsl:variable name="current" select="."/> <xsl:variable name="rowBlockVar"> <xsl:call-template name="makeRow"> <xsl:with-param name="rowBlock" select="$rowBlock"/> <xsl:with-param name="current" select="$current"/> </xsl:call-template> </xsl:variable> <tr> <xsl:copy-of select="$rowBlockVar"/> </tr> <xsl:apply-templates select="following-sibling::tr[1]" mode="rowspan"> <xsl:with-param name="rowBlock" select="exsl:node-set($rowBlockVar)"/> </xsl:apply-templates> </xsl:template> <xsl:template name="makeRow"> <xsl:param name="rowBlock"/> <xsl:param name="current"/> <xsl:param name="rowBlockPointer" select="1"/> <xsl:param name="currentPointer" select="1"/> <xsl:variable name="rbRowspan"> <xsl:for-each select="$rowBlock"> <xsl:choose> <xsl:when test="td[$rowBlockPointer]/@rowspan"> <xsl:value-of select="td[$rowBlockPointer]/@rowspan"/> </xsl:when> <xsl:otherwise>1</xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:variable> <xsl:if test="$rowBlock/td[$rowBlockPointer]"> <xsl:choose> <xsl:when test="$rbRowspan > 1 or not($current/td[$currentPointer])"> <td rowspan="{$rbRowspan - 1}"> <xsl:value-of select="$rowBlock/td[$rowBlockPointer]"/> </td> <xsl:call-template name="makeRow"> <xsl:with-param name="rowBlock" select="$rowBlock"/> <xsl:with-param name="current" select="$current"/> <xsl:with-param name="rowBlockPointer" select="$rowBlockPointer + 1"/> <xsl:with-param name="currentPointer" select="$currentPointer"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:for-each select="$current"> <xsl:copy-of select="td[$currentPointer]"/> <xsl:call-template name="makeRow"> <xsl:with-param name="rowBlock" select="$rowBlock"/> <xsl:with-param name="current" select="$current"/> <xsl:with-param name="rowBlockPointer" select="$rowBlockPointer + 1"/> <xsl:with-param name="currentPointer" select="$currentPointer + 1"/> </xsl:call-template> </xsl:for-each> </xsl:otherwise> </xsl:choose> </xsl:if> </xsl:template> </xsl:stylesheet> XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Omnimark vs. XSL (Saxon) , bry | Thread | [xsl] Table Normalization, Michael Müller-Hille |
RE: [xsl] Using key to group large , Michael Kay | Date | RE: [xsl] xsl search engine, Ricaud Matthieu |
Month |