Reputation: 3
I need some advice, not being a guru at XSLT...
I have the following code, but the process is slow and results in the page load time being way too long! I know there must be another way, but I can't get my head around it.
Basically, I have a large list of nodes that I'd like to return 3 randomly, without it having to constantly 'for-each' through the entire list every time??
Any help would be greatly appreciated! Thanks.
<msxml:script implements-prefix="random" language="C#">
<msxml:assembly name="umbraco"/>
<msxml:using namespace="umbraco"/>
<![CDATA[
public int GetRandom(int minValue, int maxValue)
{
return umbraco.library.GetRandom().Next(minValue, maxValue);
}
]]>
</msxml:script>
<xsl:template match="/">
<xsl:variable name="bigCount" select="count(umbraco.library:GetXmlNodeById(1070)/descendant::* [@isDoc and string(umbracoNaviHide) != '1'][(self::AddANewsStory or self::AddAFeature or self::AddABlogEntry)])" />
<xsl:for-each select="umbraco.library:GetXmlNodeById(1070)//descendant::*[@isDoc and string(umbracoNaviHide) != '1'][(self::AddANewsStory or self::AddAFeature or self::AddABlogEntry)]">
<xsl:sort select="random:GetRandom(1, $bigCount)" order="ascending"/>
<xsl:if test="position() <= $repeated">
<div class="relative hover-shadow mb">
<a href="{umbraco.library:NiceUrl(@id)}"><img src="/ImageGen.ashx?image={concat(substring-before(umbracoFile ,'.'),'_Article Image.jpg')}" width="100%" alt="{newsTitle}" /></a>
<div class="r_content">
<xsl:variable name="catID" select="umbraco.library:GetXmlNodeById(selectACategory)/@id"/>
<div class="r_title"><a href="{umbraco.library:NiceUrl(@id)}"><xsl:value-of select="newsTitle"/><xsl:value-of select="blogTitle"/><xsl:value-of select="featureTitle"/></a></div>
</div>
</div>
</xsl:if>
</xsl:for-each>
</xsl:template>
Upvotes: 0
Views: 746
Reputation: 667
I am not sure whether the random script call is what makes it slow, I think it is rather the random number generator in the xsl:sort call that messes up everything.
Try the below script:
Set a variable as a source. Don't use .net calls, they will only slow things down.
<xsl:variable name="source" select="$currentPage/ancestor-or-self::@[@level = 1]//*[@isDoc][@id = 1070]"/>
Gather your nodes.
<xsl:variable name="nodes">
<xsl:apply-templates select="msxml:node-set($source)//*[@isDoc and string(umbracoNaviHide) != '1'][(self::AddANewsStory or self::AddAFeature or self::AddABlogEntry)]" mode=filter"/>
</xsl:template>
</xsl:variable>
Get the count from those nodes.
<xsl:variable name="bigCount" selet="count(msxml:nodeset($nodes)/*)"/>
Identity template, adding a random value as an attribute. Using the mode attribute to target specific templates: filter.
<xsl:template match="*" mode="filter">
<xsl:attribute name="randomOrder">
<xsl:value-of select="random:GetRandom(1,$bigCount)"/>
</xsl:attribute>
<xsl:copy-of select="node()|@*"/>
</xsl:template>
Render the nodes. Using the mode attribute to target specific templates: render. Sort based on the new attribute randomOrder.
<xsl:template match="/">
<xsl:apply-templates select="msxml:node-set($nodes)/*" mode="render">
<xsl:sort select="@randomOrder" data-type="number" order="ascending"/>
</xsl:apply-templates>
</xsl:template>
Item template to be rendered for each node.
<xsl:template match="*" mode="render">
<div class="relative hover-shadow mb">
<xsl:value-of select="."/>
</div>
</xsl:template>
And the complete script with the correct namespace added: xmlns:random="urn:my-scripts"
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxml="urn:schemas-microsoft-com:xslt"
xmlns:umbraco.library="urn:umbraco.library"
xmlns:random="urn:my-scripts" version="1.0"
exclude-result-prefixes="random msxml umbraco.library">
<msxml:script implements-prefix="random" language="C#">
<msxml:assembly name="umbraco"/>
<msxml:using namespace="umbraco"/>
<![CDATA[
public int GetRandom(int minValue, int maxValue)
{
return umbraco.library.GetRandom().Next(minValue, maxValue);
}
]]>
</msxml:script>
<xsl:param name="currentPage"/>
<xsl:variable name="source" select="$currentPage/ancestor-or-self::*[@level = 1]//*[@isDoc][@id = 1070]"/>
<xsl:variable name="nodes">
<xsl:apply-templates select="msxml:node-set($source)//*[@isDoc and string(umbracoNaviHide) != '1'][(self::AddANewsStory or self::AddAFeature or self::AddABlogEntry)]" mode="filter"/>
</xsl:variable>
<xsl:variable name="bigCount" select="count(msxml:node-set($nodes)/*)"/>
<xsl:template match="*" mode="filter">
<xsl:attribute name="randomOrder">
<xsl:value-of select="random:GetRandom(1,$bigCount)"/>
</xsl:attribute>
<xsl:copy-of select="node()|@*"/>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="msxml:node-set($nodes)/*" mode="render">
<xsl:sort select="@randomOrder" data-type="number" order="ascending"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="*" mode="render">
<div class="relative hover-shadow mb">
<xsl:value-of select="."/>
</div>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1