I got a ping yesterday from someone who had come across one of my old posts about Displaying the First N Words of a Long Rich Text Column with XSL. While the bits and pieces are there in the post, without a decent knowledge of XSL, it wasn’t obvious to them how you’d actually using the XSL templates.
In this case, the list in question was an Announcements list. I whipped up the XSL below for a DVWP pretty quickly using the StripHTML and FirstNWords templates which I’ve made available in the SPXSLT Codeplex Project. If you drop this into your XSL section, you should have something pretty close to what you want. I’ve got the number of words per announcement body set to 10 in line 36; you can change that to whatever you’d like.
If you have useful XSL templates which you’d like to share, post them to the Discussions over at the SPXSLT Codeplex Project.
<xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal">
<xsl:output method="html" indent="no"/>
<xsl:template match="/">
<xsl:call-template name="dvt_1"/>
</xsl:template>
<xsl:template name="dvt_1">
<xsl:variable name="Rows" select="/dsQueryResponse/Rows/Row"/>
<table border="0" width="100%" cellpadding="2" cellspacing="0">
<xsl:for-each select="$Rows">
<xsl:call-template name="dvt_1.rowview"/>
</xsl:for-each>
</table>
</xsl:template>
<xsl:template name="dvt_1.rowview">
<xsl:variable name="BodyText">
<xsl:call-template name="StripHTML">
<xsl:with-param name="HTMLText" select="@Body"/>
</xsl:call-template>
</xsl:variable>
<tr>
<td class="ms-vb">
<a href="{@FileRef}"><span class="ms-announcementtitle"><xsl:value-of select="@Title"/></span></a><br/>
by <xsl:value-of select="@Author" disable-output-escaping="yes"/>
</td>
<td class="ms-vb">
<xsl:value-of select="ddwrt:FormatDate(string(@Created), 1033, 5)"/>
</td>
</tr>
<tr>
<td class="ms-vb">
<xsl:call-template name="FirstNWords">
<xsl:with-param name="TextData" select="$BodyText"/>
<xsl:with-param name="WordCount" select="10"/>
<xsl:with-param name="MoreText" select="'...'"/>
</xsl:call-template>
</td>
</tr>
</xsl:template>
<xsl:template name="StripHTML">
<xsl:param name="HTMLText"/>
<xsl:choose>
<xsl:when test="contains($HTMLText, '<')">
<xsl:call-template name="StripHTML">
<xsl:with-param name="HTMLText" select="concat(substring-before($HTMLText, '<'), substring-after($HTMLText, '>'))"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$HTMLText"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="FirstNWords">
<xsl:param name="TextData"/>
<xsl:param name="WordCount"/>
<xsl:param name="MoreText"/>
<xsl:choose>
<xsl:when test="$WordCount > 1 and (string-length(substring-before($TextData, ' ')) > 0 or string-length(substring-before($TextData, ' ')) > 0)">
<xsl:value-of select="concat(substring-before($TextData, ' '), ' ')" disable-output-escaping="yes"/>
<xsl:call-template name="FirstNWords">
<xsl:with-param name="TextData" select="substring-after($TextData, ' ')"/>
<xsl:with-param name="WordCount" select="$WordCount - 1"/>
<xsl:with-param name="MoreText" select="$MoreText"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="(string-length(substring-before($TextData, ' ')) > 0 or string-length(substring-before($TextData, ' ')) > 0)">
<xsl:value-of select="concat(substring-before($TextData, ' '), $MoreText)" disable-output-escaping="yes"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$TextData" disable-output-escaping="yes"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
21 comments
1 ping
audunms
October 13, 2011 at 1:54 pm (UTC -4) Link to this comment
Great post!
What if I want to display the text formatted as Rich Text in the DVWP, but I still want to display only the first N words/characters – and not risking cutting of the “text” in the middle of a HTML tag (which can break my “Read more” tag…)?
Marc
October 13, 2011 at 7:53 pm (UTC -4) Link to this comment
It’s problematic because your “parser” would need to be HTML savvy. That’s why I took the plain text route.
M.
Romeo
May 14, 2012 at 4:07 pm (UTC -4) Link to this comment
Hello Marc,
Really good your share. I used it and it’s working .
Thanks for your work
« Previous 1 2
SharePoint 2010 Help » the SPXSLT Project And How To Turn Announcements Into Marquee
June 11, 2011 at 9:41 am (UTC -4) Link to this comment
[...] Designer. Luckily, Marc Anderson, who maintains the SPXSLT project at Codeplex, had a ready xsl template which limits the Body to the first n words, which is even better. You should check Marc’s [...]