PSR
PSR

Reputation: 40328

xslt performance issue with large if conditions

In my xslt i have code like

 <xsl:param name="acceptType"/>
 <xsl:template match="element-1|element-2............|element-n>
   <xsl:if test=".!=''">           
         <xsl:if test="not(contains($acceptType, 'xml'))">
            <xsl:element name="{local-name()}">
               <xsl:value-of select="$pARRAY"/>
            </xsl:element>
         </xsl:if>
      </xsl:if>
   </xsl:template>

Here i have nearly 1000 elements .Because of this condition checking we are having the performance issue.Is there any alternative way for doing this?.I am thinking to put a global boolean variable and want to check that variable.Is it the right way to increase performance.

Thanks in advance..

Upvotes: 0

Views: 345

Answers (2)

kjhughes
kjhughes

Reputation: 111621

Absolutely measure rather than guess regarding performance.

But here are some alternative ideas in the meantime to eliminate the 1000 elements in your single match template:

  1. Change to match="*" and then add separate match="element-i" templates for each of the other i..N elements not in the original 1000. This should help if N is much less than 1000, or see #2:
  2. Change to match="*[ some condition ], where some condition covers each of your element-1, element-2, ...
    • string(number(substring-after(local-name(), '-')) = 'Nan' would test if the matching element name ended with a - number.
    • child would test for a common child element.
    • @attr > 0 would test for positive @attr values
    • etc.

Whether any of these are faster or not, again, should be determined empirically for your particular XSLT processor. However, if applicable, these alternatives could have a code maintenance, if not performance, advantage at least.


Update: Abel's comment doubting that match="x|y|z" would be sinking performance makes sense. Try replacing what concerns him more, the test=". != ''" test, with test="node()" instead:

 <xsl:param name="acceptType"/>
 <xsl:template match="element-1|element-2............|element-n>
   <xsl:if test="node()">           
       <xsl:if test="not(contains($acceptType, 'xml'))">
          <xsl:element name="{local-name()}">
             <xsl:value-of select="$pARRAY"/>
          </xsl:element>
       </xsl:if>
     </xsl:if>
  </xsl:template>

This condition will be true for non-empty matching elements but will avoid asking for the string value of the current node (which you don't really need anyway) to be calculated.

Upvotes: 1

Rudolf Yurgenson
Rudolf Yurgenson

Reputation: 603

In xslt 2.0 I'd do something like this:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>

    <xsl:key name="element-by-name" match="element" use="@name"/>

    <xsl:variable name="acceptedElements">
        <element name="a1"/>
        <element name="a3"/>
        <element name="a5"/>
    </xsl:variable>

    <xsl:template match="*">
        <xsl:if test="key('element-by-name', local-name(), $acceptedElements)">
            <xsl:value-of select="local-name()"/>
        </xsl:if>
        <xsl:apply-templates select="*"/>
    </xsl:template>
</xsl:stylesheet>

Upvotes: 1

Related Questions