Re: [xsl] Slow XSLT

Subject: Re: [xsl] Slow XSLT
From: Tony Graham <Tony.Graham@xxxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 14 Mar 2008 09:57:31 +0000
On Thu, Mar 13 2008 16:33:02 +0000, cleytonjordan@xxxxxxxxxxx wrote:
> Here is the latest working XSLT however it is slow
> _________________________________________________
>
> <?xml version="1.0" encoding="UTF-8"?>
> <xsl:stylesheet version="1.0"
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
>   <xsl:strip-space elements="*"/>
>
>   <xsl:decimal-format name="fd1" decimal-separator="."
> grouping-separator="," NaN=" \"/>

fd1 appears to be unused.

>   <xsl:param name="axisHeads" select="'false'"/>
>   <xsl:param name="sortCol" select="'0'"/>
>   <xsl:param name="sortCell" select="'0'"/>
>   <xsl:param name="dataType" select="'text'"/>
>   <xsl:param name="sortOrder" select="'ascending'"/>
>   <xsl:param name="ltCurFormat"
> select="'$##,###.00'"/>
>   <xsl:param name="ltNumFormat"
> select="'###,.00'"/>

Saxon 6.5.5 objects to this number format.

>   <xsl:param name="heading"/>
>   <xsl:param name="height" select="'500'"/>
>   <xsl:param name="width" select="'880'"/>
>   <xsl:param name="id" select="'audit'"/>
>
>
>   <xsl:template match="Report">
>     <html>
>       <head>
>         <title>report</title>
>       </head>
>       <body>
>         <table border="1">
>           <xsl:apply-templates/>
>         </table>
>       </body>
>     </html>
>   </xsl:template>
>   
>   <xsl:template match="Row">
>     <tr>
>       <xsl:apply-templates/>
>     </tr>
>   </xsl:template>
>   
>   <xsl:template match="Msr">

Considering the number of times @val is used, you could make a variable
for it before this xsl:choose instead of making $numberVal below.

>     <xsl:choose>
>       <xsl:when test="string(number(@val)) ='NaN'">

boolean(NaN) is not true [1], so you could do "not(number(@val))".

Considering that your most common NaN case appears to be 'val=""', it
might be quicker to do "$val = '' or not(number($val)".

Judging by your sample data, the NaN is the most common case.  If it
isn't, you could try reversing the sense of the test and exchanging the
contents of the xsl:when and the xsl:otherwise to see if that made any
difference.

If you had the option, it might be better to just omit @val from your
XML when it doesn't have a useful value.  Checking for the existence of
an attribute has to be quicker than checking that the attribute's value
is not a number.

>         <td align="left" style="overflow:none">
>           <nobr>
>             <div style="width:80px;overflow:none">
>               <xsl:value-of select="@val"/>
>             </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"/>

This xsl:if and xslchoose could be one xsl:choose.

You could experiment with putting the most frequently true xsl:when
cases first in the xsl:choose to see if that makes any difference to the
speed.

>               <xsl:if test="$numberVal != ''">
>                 <xsl:choose>
>                   <xsl:when test="$numberVal = '-1' or
> $numberVal = '0'">
>                     <xsl:text
> xml:space="preserve">-</xsl:text>
>                   </xsl:when>

This xsl:when is identical to the one above:

>                   <xsl:when test="$numberVal = '-1' or
> $numberVal = '0'">
>                     <xsl:text
> xml:space="preserve">-</xsl:text>
>                   </xsl:when>
>                   <xsl:when test="$style='wholeNum'">
>                     <xsl:value-of
> select="format-number($numberVal,'###,')"/>
>                   </xsl:when>
>                   <xsl:when test="$style='currency'">
>                     <xsl:value-of
> select="format-number($numberVal,$ltCurFormat)"/>
>                   </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 = ''">

How can this ever happen since the xsl:when above in the outermost
xsl:choose would have been chosen when @val is ''?

>                 <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="/Report/Measures/Measure">
>       <td>&#xa0;</td>
>     </xsl:for-each>
>   </xsl:template>
>  
> </xsl:stylesheet>

Regards,


Tony Graham.
======================================================================
Tony.Graham@xxxxxxxxxxxxxxxxxxxxxx   http://www.menteithconsulting.com

Menteith Consulting Ltd             Registered in Ireland - No. 428599
Registered Office: 13 Kelly's Bay Beach, Skerries, Co. Dublin, Ireland
----------------------------------------------------------------------
Menteith Consulting -- Understanding how markup works
======================================================================

[1] http://www.w3.org/TR/xpath#section-Boolean-Functions

Current Thread