Hi Manfred,
Thanks again for your assistance. It is really
appreciated.
I will try your sample code and let you know what
happens.
Also, as I mentined before, I am trying to build a
GRID and will send to you a copy of my latest XSLT so
that you can see what I have achieved so far. Slowly I
am getting there :-)
THE GRID
Basically, I use four <DIV> and <TABLE> tags. I have
the Top Left DIV, Top Right DIV, Bottom Left DIV and
Bottom Rght DIV.
Because I use Javascript to align my GRID, I have to
apply templates in a certain order i.e:
1- build the bottom right section first (grdBody)
2- next build the top right section (column headings)
3- Build the bottom left section (row headings)
4- Finaly build the top left section which is just an
empty div with the right hight and width to align with
the rest of the grid.
Please note that I still have to change my XSLT code
to use the sample code you showed me (call template
and tail recursion). I am still using my old key way I
mentioned to you.
I am struggling a bit with some of the suggestions I
have received specially the sample code provided by
David Carlisle. He showed me how to use a technique
that Michael calls vanilla push-processing.
However, since I have to sort the xml based on some
parameters passed to the stylesheet, I am not sure
where to add the <xsl:sort> command with
<apply-templates>.
I have to sort 3 sections of the xml. This is how I
used to do:
<xsl:sort select
="Cell[number($sortCell)]/descendant::Msr[number($sortCol)]/@val"
data-type="{$dataType}" order ="{$sortOrder}" />
I have to sort all the rows except for the last one -
the Total row of course :-). That is the reason for
the when test:
OLD REPORT TEMPLATE WITH SORTING
<xsl:template match="Report" >
<!-- grdBdy -->
<div id="{$id}grdBdy">
<table id="tblTop" cellpadding="0">
<tbody>
<xsl:choose>
<xsl:when test="number($sortCol) != 0">
<xsl:apply-templates
select="/Reports/Report/Rows//Row" mode="data">
<xsl:sort select
="Cell[number($sortCell)]/descendant::Msr[number($sortCol)]/@val"
data-type="{$dataType}" order ="{$sortOrder}" />
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates
select="/Reports/Report/Rows//Row" mode="data" />
</xsl:otherwise>
</xsl:choose>
</tbody>
</table>
</div>
</xsl:template>
I also have to add a sort command to sort the Row
Headings:
OLD REPORT TEMPLATE WITH ROW HEADING SORTING
<xsl:template match="Report" >
<!-- grdLeft -->
<div id="{$id}grdLft" style="position: absolute;
top: 12px; left: 0px; width: 150px; height:
{$height}px">
<table width="100%" class="grdMain" border="0"
cellspacing="1" cellpadding="0">
<tbody>
<xsl:choose>
<xsl:when test="number($sortCol) != 0">
<xsl:apply-templates
select="Rows//Row" mode="heading">
<xsl:sort select
="Cell[number($sortCell)]/descendant::Msr[number($sortCol)]/@val"
data-type="{$dataType}" order ="{$sortOrder}" />
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates
select="Rows//Row" mode="heading" />
</xsl:otherwise>
</xsl:choose>
</tbody>
</table>
</div>
</xsl:template>
Please note that I used to be able to control all
these sections using the MODE ATTRIBUTE
<xsl:apply-templates select="Rows//Row"
mode="heading">
However, with apply-templates I might not have this
control. What do you think?
The last place I have to sort is in the Cell template.
Please note that I have removed this sort command from
my latest XSLT because I am not sure how to do that
now.
<xsl:template match="Cell">
<xsl:choose>
<xsl:when test="Msr">
<xsl:for-each select="Msr">
<xsl:sort select="@idx" order="ascending"
data-type="number"/>
<xsl:choose>
.....
....
</xsl:template>
I would appreciate your suggestion about the sorting
issues I mentioned above and also any other
improvement you may find possible.
Just one last note, I still have to figure out the
best way to deal with the ROW HEADINGS. Still using
old code like <xsl:if
test="preceding-sibling::Row=false() or
number($sortCol) != 0">
<xsl:apply-templates select="parent::RowGrp"
mode="heading" />.
How difficult do you think it would be to change my
approach of using 4 DIVs and 4 Tables to build the
grid and instead creating just one table?
However, I would have to make sure I get my rowspan
and colspan right for the first TD in the first <tr>.
Cheers
C
XSLT
____
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" version="1.0"
encoding="iso-8859-1" indent="yes"/>
<xsl:strip-space elements="*"/>
<!--<xsl:decimal-format name="fd1"
decimal-separator="." grouping-separator=","
NaN=" \"/>-->
<xsl:param name="axisHeads" select="'false'"/>
<xsl:param name="sortCol" select="'0'"/>
<xsl:param name="sortCell" select="'0'"/>
<xsl:param name="dataType" select="'number'"/>
<xsl:param name="sortOrder" select="'descending'"/>
<xsl:param name="ltCurFormat"
select="'$##,###.00'"/>
<xsl:param name="ltNumFormat"
select="'###,.00'"/>
<xsl:param name="heading"/>
<xsl:param name="height" select="'500'"/>
<xsl:param name="width" select="'880'"/>
<xsl:param name="id" select="'audit'"/>
<xsl:variable name="nrmr"
select="count(/Report/Measures/Measure)"/>
<xsl:variable name="msrs"
select="/Report/Measures/Measure"/>
<xsl:variable name="colSet"
select="/Report/Columns/ColGrp/descendant::Col"/>
<xsl:key name="c" match="ColGrp"
use="count(ancestor::ColGrp)"/>
<xsl:template match="Report">
<!-- outer div to contain all four grid elements
-->
<div id="{$id}dvGrid" class="grdVP"
style="position: relative; height: {$height}px; width:
{$width}px; overflow: hidden; clip: rect(0px,
{$width}px, {$height}px, 0px);">
<!-- grdBdy -->
<div id="{$id}grdBdy" style="position: relative;
width: {$width}px; height: {$height}px; overflow:auto"
onscroll="scrollFullGrid(this)">
<table class="grdMain" id="tblTop" border="0"
cellspacing="1" cellpadding="0">
<tbody>
<xsl:choose>
<xsl:when test="number($sortCol) != 0">
<xsl:apply-templates>
<xsl:sort select
="Cell[number($sortCell)]/descendant::Msr[number($sortCol)]/@val"
data-type="{$dataType}" order ="{$sortOrder}" />
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</tbody>
</table>
</div>
<div id="{$id}grdTop" style="position: absolute;
top: 0px; left: 0px; width: {$width}px; height: 12px">
<table class="grdTop" border="0"
cellspacing="1" cellpadding="0">
<tbody>
<xsl:apply-templates select="Columns"
mode="Column"/>
</tbody>
</table>
</div>
<!-- grdLeft -->
<div id="{$id}grdLft" style="position: absolute;
top: 12px; left: 0px; width: 150px; height:
{$height}px">
<table width="100%" class="grdMain" border="0"
cellspacing="1" cellpadding="0">
<tbody>
<xsl:choose>
<xsl:when test="number($sortCol) != 0">
<xsl:apply-templates
select="Rows//Row" mode="heading">
<xsl:sort select
="Cell[number($sortCell)]/descendant::Msr[number($sortCol)]/@val"
data-type="{$dataType}" order ="{$sortOrder}" />
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates
select="Rows//Row" mode="heading" />
</xsl:otherwise>
</xsl:choose>
</tbody>
</table>
</div>
<!-- grdTL the filler space - formerly the td
with colspan and rowspan -->
<div id="{$id}grdTL" class="grdTL"
style="position: absolute; width:150px;height:12px">
<div></div>
</div>
</div>
</xsl:template>
<!--== ROW DATA ==-->
<xsl:template match="Row">
<tr>
<xsl:apply-templates/>
</tr>
</xsl:template>
<xsl:template match="Msr">
<xsl:variable name="numberVal" select="@val"/>
<xsl:choose>
<!--<xsl:when test="string(number(@val))
='NaN'">-->
<xsl:when test="not(number($numberVal))">
<td align="left" style="overflow:none">
<nobr>
<div style="width:80px;overflow:none">
<xsl:value-of select="$numberVal"/>
</div>
</nobr>
</td>
</xsl:when>
<xsl:otherwise>
<td align="right" style="overflow:none">
<nobr>
<div style="width:80px;overflow:none">
<!--<xsl:variable name="numberVal"
select="@val"/>-->
<xsl:variable name="style"
select="@class"/>
<xsl:if test="$numberVal != ''">
<xsl:choose>
<xsl:when test="$style='num1'">
<xsl:value-of
select="format-number($numberVal,'###,')"/>
</xsl:when>
<xsl:when test="$style='cur1'">
<xsl:value-of
select="format-number($numberVal,$ltCurFormat)"/>
</xsl:when>
<!--<xsl:when test="$numberVal =
'-1' or $numberVal = '0'">
<xsl:text
xml:space="preserve">-</xsl:text>
</xsl:when>-->
<xsl:when test="$numberVal = '-1' or
$numberVal = '0'">
<xsl:text
xml:space="preserve">-</xsl:text>
</xsl:when>
<xsl:when test="$style='percent'">
<xsl:value-of
select="format-number($numberVal * 100,'0.00')"/>
<xsl:text>%</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of
select="format-number($numberVal,$ltNumFormat)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
<xsl:if test="$numberVal = ''">
<xsl:text
xml:space="preserve">-</xsl:text>
</xsl:if>
</div>
</nobr>
</td>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="Cell[not(*)]">
<xsl:for-each select="$msrs">
<td align="right" style="overflow:none">
<nobr>
<div style="width:80px">
</div>
</nobr>
</td>
<!--<td> </td>-->
</xsl:for-each>
</xsl:template>
<!--== ROW DATA ==-->
<!--== Columns ==-->
<xsl:template match="Columns" mode="Column">
<xsl:apply-templates select="ColGrp[1]"
mode="Header">
<!-- 0 for top level heading, 1 to cut it out
-->
<xsl:with-param name="depth">
<xsl:choose>
<xsl:when test="$axisHeads='true'">
<xsl:value-of select="0"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:with-param>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="ColGrp" mode="Header">
<xsl:param name="depth" />
<tr>
<!-- the very first row needs a padding cell -->
<!--<xsl:for-each
select="//ColGrp[count(ancestor::ColGrp)=$depth]">-->
<xsl:for-each select="key('c', $depth)">
<!--<td colspan="{count(.//Col)*$msrs}"
align="center" style="overflow:none">-->
<td colspan="{count(.//Col)*$nrmr}"
align="center" style="overflow:none">
<nobr>
<div>
<xsl:value-of select="@heading"/>
</div>
</nobr>
</td>
</xsl:for-each>
</tr>
<xsl:choose>
<xsl:when test="ColGrp">
<xsl:apply-templates select="ColGrp[1]"
mode="Header">
<xsl:with-param name="depth"
select="$depth+1" />
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="Col[1]"
mode="colHead" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="Col" mode="colHead">
<tr>
<xsl:for-each select="$colSet">
<td colspan="{$nrmr}" valign="top"
align="center" style="overflow:none">
<nobr>
<div>
<xsl:value-of select="@heading"/>
</div>
</nobr>
</td>
</xsl:for-each>
</tr>
<tr valign="bottom">
<xsl:for-each select="$colSet">
<xsl:apply-templates select="/Report/Measures"
mode ="ColumnMeasure">
<xsl:with-param name="pos"
select="position()" />
</xsl:apply-templates>
</xsl:for-each>
</tr>
</xsl:template>
<xsl:template match="Measures" mode="ColumnMeasure">
<xsl:param name="pos" />
<xsl:for-each select="$msrs">
<xsl:variable name="mPos">
<xsl:value-of select="position()" />
</xsl:variable>
<td align="center">
<nobr>
<div class="action" style="width:90px;
overflow:none" onclick="sortFullGrid({$mPos}, {$pos},
'{(_at_)class}')">
<xsl:value-of select="@heading"/>
</div>
</nobr>
</td>
</xsl:for-each>
</xsl:template>
<!--== Columns ==-->
<!--== ROW MODE HEADING ==-->
<xsl:template match="Row" mode="heading">
<tr>
<xsl:if test="preceding-sibling::Row=false() or
number($sortCol) != 0">
<xsl:apply-templates select="parent::RowGrp"
mode="heading" />
</xsl:if>
<xsl:variable name="theHeading">
<xsl:call-template name="js-escapeAmp">
<xsl:with-param name="string">
<xsl:call-template name="js-escapeApos">
<xsl:with-param name="string"
select="@heading" />
</xsl:call-template>
</xsl:with-param>
</xsl:call-template>
</xsl:variable>
<td title="{$theHeading}" style="overflow:none">
<nobr>
<div>
<xsl:value-of select="$theHeading"/>
</div>
</nobr>
</td>
</tr>
</xsl:template>
<xsl:template match="RowGrp" mode="heading">
<xsl:if test="preceding-sibling::RowGrp=false() or
number($sortCol) != 0">
<xsl:apply-templates select="parent::RowGrp"
mode="heading" />
</xsl:if>
<xsl:if test="parent::Rows=false() or
$axisHeads='true'">
<td style="overflow:none; vertical-align:top"
title="{(_at_)heading}" valign="top">
<xsl:if test="number($sortCol) = 0">
<xsl:attribute name="rowspan">
<xsl:value-of select="count(.//Row)"/>
</xsl:attribute>
</xsl:if>
<nobr>
<div>
<xsl:value-of select="@heading"/>
</div>
</nobr>
</td>
</xsl:if>
</xsl:template>
<xsl:template name="js-escapeApos">
<xsl:param name="string" />
<xsl:call-template name="substitute">
<xsl:with-param name="string"
select="normalize-space($string)" />
<xsl:with-param name="find"
select='"&apos;"' />
<xsl:with-param name="replace" select='"'"'
/>
</xsl:call-template>
</xsl:template>
<xsl:template name="js-escapeAmp">
<xsl:param name="string" />
<xsl:call-template name="substitute">
<xsl:with-param name="string"
select="normalize-space($string)" />
<xsl:with-param name="find" select='"&amp;"'
/>
<xsl:with-param name="replace" select='"&"'
/>
</xsl:call-template>
</xsl:template>
<xsl:template name="substitute">
<xsl:param name="string" />
<xsl:param name="find" />
<xsl:param name="replace" />
<xsl:choose>
<xsl:when test="$find and $string and
contains($string, $find)">
<xsl:value-of
select="substring-before($string, $find)" />
<xsl:value-of select="$replace" />
<xsl:call-template name="substitute">
<xsl:with-param name="string"
select="substring-after($string,$find)" />
<xsl:with-param name="find" select="$find"
/>
<xsl:with-param name="replace"
select="$replace" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$string" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
--- Manfred Staudinger <manfred(_dot_)staudinger(_at_)gmail(_dot_)com>
wrote:
On 14/03/2008, Michael Kay <mike(_at_)saxonica(_dot_)com>
wrote:
A lot has already been said and many suggestions
have already
> been made in this thread to speed up the
processing of your
> stylesheet, but since your stylesheet is rather
> straightforward I doubt if any of the
suggestions really
___________________________________________________________
Win a BlackBerry device from O2 with Yahoo!. Enter now.
http://www.yahoo.co.uk/blackberry
--~------------------------------------------------------------------
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>
--~--