RE: [xsl] Slow XSLT

Subject: RE: [xsl] Slow XSLT
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Sat, 1 Mar 2008 23:34:11 -0000
> I have written the XSLT below and it works fine.
> However, when the XML has lots of RowGrp elements then it 
> becomes quite slow to transform.

I see no RowGrp elements, I assume you mean ColGrp...

Its easy to see why your code is slow. But I'm afraid I can't suggest any
way to speed it up, because I simply can't work out what it is trying to do.
You haven't given any clues, and reverse engineering the requirements from
some rather strangely-written code is not easy.

Michael Kay
http://www.saxonica.com/


> 
> The difficulty that I am having is to find a way to speed it 
> up. I think there could be two problems with my XSLT:
> 
> 1 - Recursion in the ColGrp Template mode="header"  
> 
> <xsl:for-each
> select="//ColGrp[count(ancestor::ColGrp)=$depth]">
> 
> 2 - Also, when I am in the Col Template I have to go back to 
> the measures element for each Col
> 
> <xsl:for-each select="//Col">
>   <xsl:apply-templates select="//Measures">
>     <xsl:with-param name="pos" select="position()" />
>   </xsl:apply-templates>
> </xsl:for-each>
> 
> I would appreciate if someone could sched some light.
> I have read Jeni's XSLT pages (key and grouping) but have not 
> found any posts or example similar to mine.
> 
> Cheers
> 
> C
> ===========================
> XML
> <Reports>
> <Report xmlns="">
>   <Measures>
>     <Measure idx="1" heading="Total Pages" />
>     <Measure idx="2" heading="Cost" />
>   </Measures>
>   <Columns>
>     <ColGrp heading="Quarter">
>       <ColGrp heading="2003">
>         <Col heading="Quarter 1" />
>         <Col heading="Quarter 2" />
>         <Col heading="Quarter 3" />
>         <Col heading="Quarter 4" />
>       </ColGrp>
>       <ColGrp heading="2004">
>         <Col heading="Quarter 1" />
>         <Col heading="Quarter 2" />
>         <Col heading="Quarter 3" />
>         <Col heading="Quarter 4" />
>       </ColGrp>
>     </ColGrp>
>     <!--===TOTALS====-->
>     <ColGrp>
>       <ColGrp>
>         <Col heading="Total" />
>       </ColGrp>
>     </ColGrp>
>   </Columns>
> </Report>
> </Reports>
> 
> ==============================
> 
> XSLT
> 
> <xsl:param name="axisHeads" select="'false'" />
> 
>   <xsl:variable name="msrs">
>     <xsl:choose>
>       <xsl:when test="//Measure">
>         <xsl:value-of select="count(//Measure)"/>
>       </xsl:when>
>       <xsl:otherwise>
>         <xsl:value-of select="1"/>
>       </xsl:otherwise>
>     </xsl:choose>
>   </xsl:variable>
> 
>  <xsl:template match="Reports">
>     <xsl:apply-templates
> select="Report"></xsl:apply-templates>
>   </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="//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//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="//Col">
>         <xsl:apply-templates select="//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>
> 
> 
> 
>       ___________________________________________________________
> Rise to the challenge for Sport Relief with Yahoo! For Good  
> 
> http://uk.promotions.yahoo.com/forgood/

Current Thread