Set Limits on XSLT Recursive Functions

Recently, I had worked to help a client create an intranet portal and suddenly the portal started taking between 8 and 10 seconds to display the home page. All other pages in the solution were snappy and displayed very quickly. Returning to the development environment, the problem could not be reproduced and all pages continued to be displayed quickly. At first, it appeared the farm’s SQL server might be the issue so the developer dashboard was turned on to see where the bottleneck was occurring. After turning on the developer dashboard, it became very clear where the problem existed — a Content Query Web Part was taking on average about 8 seconds to render content.

The content for the CQWP originated in a standard SharePoint Publishing Pages library where the average size of the publishing page ranged between 10 – 20 KB. However, there were two items over 150 KB. Both of these pages contained a long list of hyperlinks and references to images. One of the pages was copied into the development environment and the same bottleneck began appearing — the server would respond and then wait to provide content. At this point, I remember a recursive function in XSLT that was used to decide to show a more link if the page contained more than a summary. Below is the template that was in use:

	<xsl:template name="RemoveHtml">
	    <xsl:param name="text"/>
	    <xsl:choose>
	        <xsl:when test="contains($text, '&amp;lt;')">
	            <xsl:value-of select="substring-before($text, '&amp;lt;')"/>
	            <xsl:call-template name="RemoveHtml">
	                    <xsl:with-param name="text" select="substring-after($text, '&amp;gt;')"/>
	            </xsl:call-template>
	        </xsl:when>
	        <xsl:otherwise>
	            <xsl:value-of select="$text"/>
	        </xsl:otherwise>
	    </xsl:choose>
	</xsl:template>

The basic idea behind the template is to grab the text by ignoring anything between the opening and closing of each tag. Since XSLT does not include a RegEx matching function, the only way to accomplish the goal is to recursively call the function.

The optimization of the template was actually very simple. Since the template is used to determine if one of the publishing items includes additional content and render a more link, the function was restricted to look at very small number of characters in the complete string.

	<xsl:template name="RemoveHtml">
	    <xsl:param name="text"/>
	    <xsl:variable name="length" select="string-length($text)"/>
	    <xsl:variable name="parseText">
	    <xsl:choose>
	    	<xsl:when test="$length &gt; 2000">
	    		<xsl:value-of select="substring($text,1,2000)"/>
	    	</xsl:when>
	    	<xsl:otherwise>
	    		<xsl:value-of select="$text"/>
	    	</xsl:otherwise>
	    </xsl:choose>
	    </xsl:variable>
	    <xsl:choose>
	        <xsl:when test="contains($parseText, '&lt;')">
	            <xsl:value-of select="substring-before($text, '&lt;')"/>
	            <xsl:call-template name="RemoveHtml">
	                    <xsl:with-param name="text" select="substring-after($parseText, '&gt;')"/>
	            </xsl:call-template>
	        </xsl:when>
	        <xsl:otherwise>
	            <xsl:value-of select="$parseText"/>
	        </xsl:otherwise>
	    </xsl:choose>
	</xsl:template>

After this simple change, the loading time for the portal dropped from 8 to 10 seconds to just under 2 seconds. The moral of the post: set limits on how many times a recursive function gets called.

Edit: I mention that XSLT does not include a RegEx function. However, I should qualify that XSLT 1.0 does not include a RegEx function.

Advertisements

2 thoughts on “Set Limits on XSLT Recursive Functions

  1. “Since XSLT does not include a RegEx matching function” is not exactly true – XSLT 1.0 does not have RegEx support, but XSLT 2.0 and 3.0 do. You might want to qualify that statement as “Since XSLT 1.0 does not include a RegEx matching function”. If only Microsoft would provide native support for XSLT 2.0…

    1. You are correct that later versions of XSLT include RegEx support. I agree that it is a shame Microsoft never officially supported XSLT’s later version that include much more powerful capabilities. This has lead to so many crazy workarounds. Thank you for the suggestion and the qualification concerning XSLT 1.0.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s