Counting top 5 most-commted posts in a SharePoint blog using XSL
-
13-04-2021 - |
Question
I'm basically editing ItemStyle.xsl to get it to retrieve what I need and display through a CQWP (Content Query Web Part). I need it to display only the top 5 posts with the most comments. The comments can be retrieved via @NumComments. I'm not familiar enough with XSL to know how to do it, I'm assuming using count? Any tips?
Here's the current XSL code for that template which just displays all posts.
<xsl:template name="MostCommented" match="Row[@Style='MostCommented']" mode="itemstyle">
<xsl:variable name="SafeLinkUrl">
<xsl:call-template name="OuterTemplate.GetSafeLink">
<xsl:with-param name="UrlColumnName" select="'LinkUrl'"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="DisplayTitle">
<xsl:call-template name="OuterTemplate.GetTitle">
<xsl:with-param name="Title" select="@Title"/>
<xsl:with-param name="UrlColumnName" select="'LinkUrl'"/>
</xsl:call-template>
</xsl:variable>
<div>
<a href="{$SafeLinkUrl}" target="{$LinkTarget}" title="{@LinkToolTip}">
<xsl:value-of select="$DisplayTitle"/>
</a>
</div>
</xsl:template>
Solution 2
I was able to do this directly in the CQWP web part instead of the ItemStyle.xsl
Replacing
<property name="QueryOverride" type="string" />
With
<property name="QueryOverride" type="string"><![CDATA[<OrderBy><FieldRef Name="NumComments" Nullable="True" Type="Lookup" Ascending="False"/></OrderBy>]]></property>
OTHER TIPS
You need to add this code -- within a template that matches the parent of Row
<xsl:apply-templates select="Row[@Style='MostCommented']" mode="itemstyle">
<xsl:sort select="@NumComments" data-type="number" order="descending"/>
</xsl:apply-templates>
Also, inside your template (the one that will be selected for execution as result of the xsl:apply-templates
above) wrap all existing code in a conditional as shown below:
<xsl:template name="MostCommented" match="Row[@Style='MostCommented']" mode="itemstyle">
<xsl:if test="not(position() > 5)">
<!-- Put all already-existing code here -->
</xsl:if>
</xsl:template>
Here is a complete example, illustrating this technique:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<t>
<xsl:apply-templates select="*">
<xsl:sort select="@valued"
data-type="number" order="descending"/>
</xsl:apply-templates>
</t>
</xsl:template>
<xsl:template match="post">
<xsl:if test="not(position() >5)">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the following XML document (as you forgot to provide one !!!):
<t>
<post valued="5"/>
<post valued="2"/>
<post valued="9"/>
<post valued="8"/>
<post valued="6"/>
<post valued="3"/>
<post valued="4"/>
<post valued="10"/>
<post valued="2"/>
<post valued="7"/>
</t>
the wanted, correct result is produced:
<t>
<post valued="10"/>
<post valued="9"/>
<post valued="8"/>
<post valued="7"/>
<post valued="6"/>
</t>