Friday, 12 March 2010

Umbraco, XSLT :: Reading RSS Feeds, Aggregating and Sorting

Here's a quick summary of how to read multiple RSS feeds, merge them, sort them and then output the first 30 items.  You can easily combine and concatenate nodes from external sources into an xsl:variable with xsl:copy-of and GetXmlDocumentByUrl.

Preparation

  1. Set up a doc type named 'RssFeed' with a property called 'url' (textstring)
  2. Create RSS Feed nodes in the Content section with your chosen feed urls
  3. Create an XSLT macro with the code that follows.

XSLT

Just put this into an <xsl:template> and it will output the first 30 items.

<!-- Find all RSS Feed nodes, create new XML tree with all rss nodes merged into the 'container' node -->
<xsl:variable name="rssFeeds">
  <container>
    <xsl:for-each select="$currentPage/ancestor-or-self::root//node [@nodeTypeAlias='Feed Item']">
      <xsl:variable name="url" select="string(data[@alias='url'])" />
      <!-- Is the url populated? -->
      <xsl:if test="string-length($url) &gt; 0">
        <!-- Import the feed-->
        <xsl:copy-of select="umbraco.library:GetXmlDocumentByUrl( $url )"/>
      </xsl:if>
    </xsl:for-each>
  </container>
</xsl:variable>
<!-- Iterate through the container doc -->
<xsl:for-each select="msxsl:node-set($rssFeeds)/container/rss/channel/item">
  <!-- Sort the items -->
  <xsl:sort select="pubDate" order="descending"/>
  <!-- Only output the first 30 items -->
  <xsl:if test="position() &lt;= 30">
    <h1>
      <a>
        <xsl:attribute name="href">
          <xsl:value-of select="link/text()"/>
        </xsl:attribute>
        <xsl:value-of select="title/text()"/>
      </a>
    </h1>
    <p>
      <xsl:value-of select="description/text()" />
    </p>
  </xsl:if>
</xsl:for-each>