WCM - How to create a news feed in WCM

  • KM507247
  • 20-Sep-2008
  • 20-Sep-2008

Archived Content: This information is no longer maintained and is provided "as is" for your convenience.

Summary

Provides steps for creating news feeeds in WCM.

Reference

How to create a news feed in WCM

Return to WCM Articles page

Note: TRIM WCM Version 6 release 2 is a prerequisite for the sample code in this article.

Both RSS and Atom are XML based standards (or families of standards) for delivering news feeds, which allow users to subscribe to web sites. This article describes how to create a news feed using either of these within WCM.

Page template setup

The following sample code assumes the news feed page uses a template which contains at least two custom fields:

  • a categorised page list named “categorisedPageList”, and
  • a TRIM saved search named “savedSearch”.

In addition the following assumptions are made:

  • WCM pages included in the categorised list are assumed to have an HTML custom field named “content” which has the “Expose in page lists” setting checked (see field profile in page template profile).
  • the categorised page list has the option “Include custom fields exposed to page lists” selected (see page content).

XSLT overview

The following XSLT is designed to allow a single page to output either a RSS or Atom format feed. The chooser XSLT inspects the page query string, if format=atom is contained in the query then an Atom feed is provided otherwise an RSS 2.0 feed is provided.

Feed chooser

This XSLT includes the XSLT for the two different feed formats and checks the query string parameters.

To use:

  • create a new XSL style sheet in WCM
  • paste this XSLT into the style sheet
  • give the style sheet a name of your choice, and
  • select this style sheet as the style sheet to be used by your feed page.
<?xml version="1.0"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:wcm="http://www.towersoft.com/ns/wcm/1.0"xmlns:wcmf="urn:wcm-msxslt-functions"><xsl:output method="xml" />	<xsl:include href="RSS2.0" _fcksavedurl=""RSS2.0"" _fcksavedurl=""RSS2.0"" /><xsl:include href="Atom1.0" /><xsl:template match="/wcm:wcm"><xsl:choose>	<xsl:when test="parameters/query/parameter[@name='format']/value = 'atom'">		<xsl:apply-templates select="." mode="atom" />	</xsl:when>	<xsl:otherwise>		<xsl:apply-templates select="." mode="rss2" />	</xsl:otherwise></xsl:choose></xsl:template></xsl:stylesheet>

Common XSLT

This common XSLT is included by both the Atom and RSS XSLT. It provides XSLT templates to:

  • insert a new line in the XML source (to improve readability),
  • prefix the relative URL generated by WCM with the host name to make the URL absolute,
  • create URL linking from a TRIM object linking to a TRIM electronic document,
  • manipulate dates (e.g. check if date is within past 24 hours or convert date to RFC 3339 format)

To use:

  • create an XSLT style sheet in the same library as the chooser style sheet and call it common,
  • paste the following XSLT into the style sheet.
<?xml version="1.0"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:wcm="http://www.towersoft.com/ns/wcm/1.0"xmlns:wcmf="urn:wcm-msxslt-functions" exclude-result-prefixes="wcm"><xsl:output method="xml" /><!-- Insert a new line in the page source. --><xsl:template name="newline"><xsl:text></xsl:text></xsl:template><!-- Make a relative URL absolute by getting the host name from the page server variables.	--><xsl:template match="@url | url"><xsl:text>http://</xsl:text><xsl:value-of select="/wcm:wcm/parameters/serverVariables/parameter[@name='HTTP_HOST']/value" /><xsl:value-of select="." /></xsl:template><!--  Create an absolute URL from a TRIM object.						--><xsl:template mode="TrimUrl" match="TrimObject"><xsl:text>http://</xsl:text><xsl:value-of select="/wcm:wcm/parameters/serverVariables/parameter[@name='HTTP_HOST']/value" /><xsl:value-of select="/wcm:wcm/docAdmin/applicationPath" /><xsl:text>_extdocuments/</xsl:text><xsl:value-of select="ancestor::TrimResponse/@TrimLocation" /><xsl:text>/</xsl:text><xsl:value-of select="Values/Value[@Name='recSuggestedFileName']/@Val" /><xsl:text>?trimid=</xsl:text><xsl:value-of select="@Uri" /></xsl:template><!-- Various script functions for manipulating dates.		--><msxml:script xmlns:msxml="urn:schemas-microsoft-com:xslt" language="JavaScript" implements-prefix="wcmf">function toDate(dt)	{	var year = dt.substr(0,4);	var month = dt.substr(5,2);	var day = dt.substr(8,2);	var hour = dt.substr(11,2);	var min = dt.substr(14,2);	var sec = dt.substr(17,2);	var dateobj = new Date(year, (month-1), day, hour, min, sec);	return dateobj;};function utcDate(dt){	var dateobj = toDate(dt);	return dateobj.toUTCString();};function toRFCString(dt){	var dateobj = new Date(dt);	return dateobj.getUTCFullYear() 		+ "-" + pad(dateobj.getUTCMonth()) 		+ "-" + pad(dateobj.getUTCDate()) 		+ "T" + pad(dateobj.getUTCHours())		+ ":" + pad(dateobj.getUTCMinutes())		+ ":" + pad(dateobj.getUTCSeconds()) +"Z"		;}function pad(n) {	if (n.toString().length == 1)	{		return "0" + n;	}	return n;}function isToday(dt){	return true;	var dateobj = toDate(dt);	var today = new Date();		if (dateobj.getDate() &lt; (today.getDate()-5))	{		return false;	}	if (dateobj.getMonth() != today.getMonth())	{		return false;	}	if (dateobj.getYear() != today.getYear())	{		return false;	}	return true;}function sortDate(dt){	var sortDate;	if (dt.indexOf("GMT") > 0)		sortDate = new Date(dt);	else		sortDate = toDate(dt);		if (sortDate)		return sortDate.valueOf();	else		return "0";}</msxml:script></xsl:stylesheet>

Atom XSLT

The Atom style sheet creates an Atom feed with an entry for those items created today in the categorised page list and all records in the the TRIM saved search.

Things to note:

  • Atom requires the use of the Atom namespace which, in turn, requires that the XSLT uses the xsl:element element to create all elements (along with the namespace attribute).
  • the exclude-result-prefixes attribute is used in the stylesheet element to prevent the wcm or wcmf namespaces being included in the output.

To use:

  • create a style sheet called Atom1.0 in the same library as the above two style sheets,
  • paste the following XSLT into the stylesheet.
<?xml version="1.0"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:wcm="http://www.towersoft.com/ns/wcm/1.0"xmlns:wcmf="urn:wcm-msxslt-functions"exclude-result-prefixes = "wcm wcmf"><xsl:output method="xml" />	<xsl:include href="_transformations/Shared/commonElements" _fcksavedurl=""_transformations/Shared/commonElements"" _fcksavedurl=""_transformations/Shared/commonElements"" /><xsl:variable name="atomNS">http://www.w3.org/2005/Atom</xsl:variable><xsl:template match="wcm:wcm" mode="atom"><xsl:call-template name="newline" /><xsl:element name="feed" namespace="{$atomNS}">	<xsl:attribute name="xml:lang">en-AU</xsl:attribute>	<xsl:call-template name="newline" />	<xsl:element name="title" namespace="{$atomNS}">		<xsl:text>Demo site news</xsl:text>	</xsl:element>	<xsl:element name="link" namespace="{$atomNS}">		<xsl:attribute name="rel">alternate</xsl:attribute>		<xsl:attribute name="type">text/html</xsl:attribute>		<xsl:attribute name="hreflang">en</xsl:attribute>		<xsl:attribute name="title">WCM Demo Site</xsl:attribute>  		<xsl:attribute name="href">			<xsl:text>http://</xsl:text>			<xsl:value-of select="/wcm:wcm/parameters/serverVariables/parameter[@name='HTTP_HOST']/value" />		</xsl:attribute>	</xsl:element>	<xsl:apply-templates mode="atom" select="		customFields/customField[@name = 'categorisedPageList']/pages/listItem[wcmf:isToday(string(docDates/date[@name='updatedDate']/localTime))]		| customFields/customField[@name = 'savedSearch']//TrimObject">				<xsl:sort order="descending"			select="wcmf:sortDate(			string(				docDates/date[@name='updatedDate']/localTime 				| descendant::Value[@Name='recDateUpdated']/@Val			)		)" />	</xsl:apply-templates></xsl:element></xsl:template><xsl:template mode="atom" match="listItem"><xsl:call-template name="newline" /><xsl:element name="entry" namespace="{$atomNS}">	<xsl:element name="title" namespace="{$atomNS}">		<xsl:value-of select="title" />	</xsl:element>	<xsl:element name="link" namespace="{$atomNS}">		<xsl:attribute name="rel">alternate</xsl:attribute>		<xsl:attribute name="href">			<xsl:apply-templates select="url" />		</xsl:attribute>	</xsl:element>	<xsl:element name="content" namespace="{$atomNS}">		<xsl:attribute name="type">xhtml</xsl:attribute>		<div>		<xsl:apply-templates select="			customFields/customField[@name='content']" />		</div>	</xsl:element>	<xsl:element name="updated" namespace="{$atomNS}">		<xsl:value-of select="docDates/date[@name='updatedDate']/localTime" />	</xsl:element></xsl:element></xsl:template><xsl:template mode="atom" match="TrimObject"><xsl:call-template name="newline" /><xsl:element name="entry" namespace="{$atomNS}">	<xsl:element name="title" namespace="{$atomNS}">		<xsl:value-of select="descendant::Value[@Name='recTitle']/@Val" />	</xsl:element>	<xsl:element name="link" namespace="{$atomNS}">		<xsl:attribute name="rel">alternate</xsl:attribute>		<xsl:attribute name="href">			<xsl:apply-templates mode="TrimUrl" select="." />		</xsl:attribute>	</xsl:element>	<xsl:element name="content" namespace="{$atomNS}">		<xsl:attribute name="type">text</xsl:attribute>		<div>			<xsl:value-of select="descendant::Value[@Name='recNotes']/@Val" />		</div>	</xsl:element>	<xsl:element name="updated" namespace="{$atomNS}">		<xsl:value-of select="wcmf:toRFCString(string(descendant::Value[@Name='recDateUpdated']/@Val))"/>	</xsl:element></xsl:element></xsl:template></xsl:stylesheet>

RSS 2.0 XSLT

The RSS style sheet creates an RSS 2.0 feed with an entry for those items created today in the categorised page list and all records in the the TRIM saved search.

This XSLT is slightly different from the Atom XSLT in that it assumes some extra custom fields exist in the page template underlying the feed page. These are:

  • meta_title (text field)
  • meta_link (link field)
  • meta_description (text field)

To use:

  • create a style sheet called RSS2.0 in the same library as the above three style sheets,
  • paste the following XSLT into the style sheet.
<?xml version="1.0"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:wcm="http://www.towersoft.com/ns/wcm/1.0"xmlns:wcmf="urn:wcm-msxslt-functions"><xsl:output method="xml" />	<xsl:include href="common" _fcksavedurl=""common"" /><xsl:template match="wcm:wcm" mode="rss2"><xsl:call-template name="newline" /><rss version="2.0"><xsl:call-template name="newline" /><channel>	<xsl:call-template name="newline" />	<xsl:apply-templates mode="rss2" select="customFields/customField" />	<xsl:call-template name="newline" />		<xsl:apply-templates mode="rss2" select="		customFields/customField[@name = 'categorisedPageList']/pages/listItem[wcmf:isToday(string(docDates/date[@name='updatedDate']/localTime))]		| customFields/customField[@name = 'savedSearch']//TrimObject">			<xsl:sort order="descending"			select="wcmf:sortDate(			string(				docDates/date[@name='updatedDate']/localTime 				| descendant::Value[@Name='recDateUpdated']/@Val			)		)" />	</xsl:apply-templates></channel><xsl:call-template name="newline" /></rss></xsl:template><xsl:template mode="rss2" match="customField[starts-with(@name,'meta_')]"><xsl:call-template name="newline" /><xsl:element name="{substring-after(@name,'meta_')}">	<xsl:value-of select="." /></xsl:element></xsl:template><xsl:template mode="rss2" match="customField[starts-with(@name,'meta_') and @type='Link']"><xsl:call-template name="newline" /><xsl:element name="{substring-after(@name,'meta_')}">	<xsl:apply-templates mode="rss2" select="link/@url" /></xsl:element></xsl:template><xsl:template mode="rss2" match="listItem"><xsl:call-template name="newline" /><item>	<title>		<xsl:value-of select="title" />	</title>	<description>		<xsl:value-of select="pageAbstract" />	</description>	<link>		<xsl:apply-templates select="url" />	</link>	<pubDate>		<xsl:value-of select="wcmf:utcDate(string(docDates/date[@name='updatedDate']/localTime))" />	</pubDate></item></xsl:template><xsl:template mode="rss2" match="TrimObject"><xsl:call-template name="newline" /><item>	<title>		<xsl:value-of select="descendant::Value[@Name='recTitle']/@Val" />	</title>	<description>		<xsl:value-of select="descendant::Value[@Name='recNotes']/@Val" />	</description>	<link>		<xsl:apply-templates mode="TrimUrl" select="." />	</link>	<pubDate>		<xsl:value-of select="substring-before(descendant::Value[@Name='recDateUpdated']/@Val,'GMT')" />		<xsl:text>UTC</xsl:text>	</pubDate></item></xsl:template><xsl:template mode="rss2" match="customField"></xsl:template></xsl:stylesheet>

Modifying the XSLT

The above two samples are not complete implentations of either Atom or RSS. They may be modified by:

  • adding further custom fields in the source pages and exposing them through the page list, then using them to include extra metadata in each item,
  • removing TRIM objects from the feed (given that they are electronic documents rather than HTML pages),