«

»

Jul 13 2010

Print this Post

Displaying the First N Words of Announcement Bodies with XSL in a DVWP

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, '&lt;')">
				<xsl:call-template name="StripHTML">
					<xsl:with-param name="HTMLText" select="concat(substring-before($HTMLText, '&lt;'), substring-after($HTMLText, '&gt;'))"/>
				</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 &gt; 1 and (string-length(substring-before($TextData, ' ')) &gt; 0 or string-length(substring-before($TextData, ' ')) &gt; 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, ' ')) &gt; 0 or string-length(substring-before($TextData, ' ')) &gt; 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>

Permanent link to this article: http://sympmarc.com/2010/07/13/displaying-the-first-n-words-of-announcement-bodies-with-xsl-in-a-dvwp/

21 comments

1 ping

  1. audunms

    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…)?

    1. Marc

      It’s problematic because your “parser” would need to be HTML savvy. That’s why I took the plain text route.

      M.

  2. Romeo

    Hello Marc,
    Really good your share. I used it and it’s working .
    Thanks for your work

  1. SharePoint 2010 Help » the SPXSLT Project And How To Turn Announcements Into Marquee

    [...] 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 [...]

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>