Re: [xsl] Slow XSLT

Subject: Re: [xsl] Slow XSLT
From: "Manfred Staudinger" <manfred.staudinger@xxxxxxxxx>
Date: Fri, 29 Feb 2008 23:08:08 +0100
As David has pointed out the // operator is very costly. So I have
replaced them by explicit xpath expressions and would be interested
about the performance now. However I could not resist to replace
   count(.//Col)*$msrs
by
   count(Col)*$msrs
Most of the rest I have l left unchanged. I also noticed the
depreciated <nobr>, which should be replaced by css white-space:
nowrap.

Manfred

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="2.0"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
<xsl:param name="axisHeads" select="'false'" />
<!--
java -jar D:\Programme\Saxon6\saxon.jar slow.xml slow.xsl
-->
<xsl:output indent="yes"/>

 <xsl:variable name="msrs">
   <xsl:choose>
     <xsl:when test="/Reports/Report/Measures/Measure">
       <xsl:value-of select="count(/Reports/Report/Measures/Measure)"/>
     </xsl:when>
     <xsl:otherwise>
       <xsl:value-of select="1"/>
     </xsl:otherwise>
   </xsl:choose>
 </xsl:variable>

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

 <xsl:template match="Report" >
     <!-- Top -->
     <div id="g1" style="position: absolute; top: 0px; left: 0px;
width: 400px; height: 12px">
       <table class="grdTop" border="0" cellspacing="1" cellpadding="0">
         <tbody>
           <xsl:apply-templates select="Columns" />
         </tbody>
       </table>
     </div>
  </xsl:template>

 <xsl:template match="Columns">
   <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="/Reports/Report/Columns/ColGrp/ColGrp[count(ancestor::ColGrp)=$depth]">
         <td colspan="{count(Col)*$msrs}" 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="ancestor::Columns/ColGrp/ColGrp/Col">
       <td colspan="{$msrs}" valign="top" align="center" style="overflow:none">
         <nobr>
           <!-- 2003/2004 -->
           <div>
             <xsl:value-of select="@heading"/>
           </div>
         </nobr>
       </td>
     </xsl:for-each>
   </tr>
   <tr valign="bottom">
     <xsl:for-each select="/Reports/Report/Columns/ColGrp/ColGrp/Col">
       <xsl:apply-templates select="/Reports/Report/Measures">
         <xsl:with-param name="pos" select="position()" />
       </xsl:apply-templates>
     </xsl:for-each>
   </tr>
 </xsl:template>

 <xsl:template match="Measures">
   <xsl:param name="pos" />
   <xsl:for-each select="Measure">
     <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}, '{@class}')">
           <xsl:value-of select="@heading"/>
         </div>
       </nobr>
     </td>
   </xsl:for-each>
 </xsl:template>

</xsl:stylesheet>

On 29/02/2008, Cleyton Jordan <cleytonjordan@xxxxxxxxxxx> wrote:
> Hi David,
>
>
>
>  >without following in detail what processing you are
>  >doing it's hard to
>  > say
>
> >sorry got to dash, perhaps someone else can say more!
>
>  >David
>
>
>
> I need to build a nested heading Rows/Columns (<TR>
>  and <TD>). The output should look like this for the
>  2003 heading:
>
>
>                           2003
>     Quarter 1        Quarter 2        Quarter 3
>    Quarter 4
>  Total Pages Cost Total Pages Cost Total Pages Cost
>
> Total Pages  Cost
>
>
>  <ColGrp heading="Quarter">
>   <ColGrp heading="2003">
>     <Col heading="Quarter 1" />
>     <Col heading="Quarter 2" />
>     <Col heading="Quarter 3" />
>     <Col heading="Quarter 4" />
>   </ColGrp>
>  </ColGrp>
>
>
> I use the xpath below to get me to the inner most
>  ColGrp (parent of Col elements).
>
>  Normally $depth = 1
>
> //ColGrp[count(ancestor::ColGrp)=$depth]
>
>
> //ColGrp[count(ancestor::ColGrp)=1]
>
>  So, I go to the ancestor:ColGrp whose depth = 1
>
>  This will produce the first <TD>s
>
>  2003      2004
>
>  Then all the Col elements will produce the second row
>  with all the <TD>s
>
>  Quarter 1   Quarter 2      Quarter 3       Quarter 4
>
>  And lastly, for each Col element I have to go back to
>  the Measure elements to produce the final Row which
>  will be the same for all the Col elements
>
>
>  Total Pages Cost Total Pages Cost Total Pages Cost
>
> Total Pages Cost
>
>  Therefore, this is the output I get with my XSLT but
>  it is too slow for big xml docs.
>
>                          2003
>  Quarter 1     Quarter 2    Quarter 3        Quarter 4
>
> Total Pages Cost Total Pages Cost Total Pages Cost
>
>
> Cheers
>
>  C
>
>
>       ___________________________________________________________
>
> Rise to the challenge for Sport Relief with Yahoo! For Good
>
>  http://uk.promotions.yahoo.com/forgood/

Current Thread