Making XmlDataSource Work with RSS 1.0, RSS 2.0 and Atom Feeds

by Al Beecy April 17, 2009
Today at work I needed to modify an existing piece of code that displayed RSS 2.0 feeds to add support for RSS 1.0. I figured I might as well support Atom also while I was at it.

The existing code used an XmlDataSource to bind to the feed and that seemed like a good way to go except for one minor problem: XmlDataSource doesn't support namespaces (why is beyond me). Unfortunately, RSS prior to version 2.0 and Atom feeds use namespaces.

Since just setting the XmlDataSource's XPATH to the appropriate paths would not be enough, off to Google I went. The web is chock full of examples for RSS 2.0 which set the XmlDataSource's XPATH property to "rss/channel/item", bind some templated control to the title, link and description elements, but not so much on RSS 1.0 and Atom.

After Googling around for a while, I had assembled all the pieces needed: Descriptions of the RSS 1.0 (and RSS 2.0) and Atom formats from Wikipedia and this snippet of XSL that removes namespaces from XML documents over at Intrepid Studios' blog:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:template match="*">
        <!-- Remove any prefixes -->
        <xsl:element name="{local-name()}">
            <!-- Work through attributes -->
            <xsl:for-each select="@*">
                <!-- Remove any attribute prefixes -->
                <xsl:attribute name="{local-name()}">
                    <xsl:value-of select="."/>
                </xsl:attribute>
            </xsl:for-each>
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

The XSL snippet above can be saved as a file and assigned to the XmlDataSource's "TransformFile" property or passed as a string to the "Transform" property. When you databind, it will apply the transformation automatically. Although targeted at the Atom and RSS 1.0 formats that use namespaces, the transformation doesn't cause any problems for RSS 2.0 feeds, so you may as well just set it and forget it.

The next thing you need to do is account for the different schemas of Atom, RSS 1.0, and RSS 2.0. The table below summarizes the differences. Yes, I know there is probably a better way to get to "item" element in RSS 1.0, but I couldn't find it -- the rdf:RDF crap kept getting in the way. Sometimes, a blunt instrument is the way to go. 

XPATH Link
Element
Title
Element
Date
Published
Element
Description
Element
RSS 1.0 "*/item" "link" "title" None "description"
RSS 2.0 "rss/channel/item" "link" "title" "pubDate" "description"
Atom "feed/entry" "link/@href" "title" "updated" "summary"

Below is a simple function I wrote to sniff out the type of feed we're dealing with:

#region guessFormat
protected string guessFormat(string xmlFeed)
{
    xmlFeed = xmlFeed.ToLower(); 

    if(xmlFeed.Contains(@"xmlns=""http://purl.org/rss/1.0/"""))

    {
        return "RSS10";
    } 
    else if (xmlFeed.Contains("<rss") && xmlFeed.Contains("<channel"))
    {
        return "RSS20";
    } 
   
else if (xmlFeed.Contains("<feed") && xmlFeed.Contains("<entry"))

    {
        return "Atom";
    }
    return "Unknown";
}
#endregion

You'll need to set up a Repeater or other templated control to display your feed, using binding statements like those below. In an actual page or user control you'll want to use protected variables or properties to supply the names of the elements to bind to so that you have sniffed out the type of feed you are working with, you can configure them for the type of feed you're using but, to keep this simple, I just hard-coded in some RSS 2.0 values.

<asp:Repeater ID="Repeater1" runat="server">
  <ItemTemplate>
    <a target="_blank" href='<%# XPath("link") %>'>
    <%# System.Web.HttpUtility.HtmlEncode(XPath("title").ToString())%>
    </a><br />
  </ItemTemplate>
</asp:Repeater>

Note that I am loading the XSL from a string that I have declared statically at the top of my class (not shown). You can set up the XmlDataSource control either declaratively or in code-behind. I prefer code:

XmlDataSource xds = new XmlDataSource();
// xsl stored in a string
xds.Transform = removeNameSpacesXSL;
xds.EnableCaching = false;
xds.XPath = "rss/channel/item";
xds.DataFile = "http://feeds2.feedburner.com/beecynet";
Repeater1.DataSource = xds;
Repeater1.DataBind();

So that's pretty much it -- all the major pieces needed to put together a ASP.Net page or control that can consume pretty much any valid feed.

Tags:

Asp.Net | XML

Comments

April 18, 2009 #

DotNetKicks.com

Trackback from DotNetKicks.com

Making XmlDataSource Work with RSS 1.0, RSS 2.0 and Atom Feeds

DotNetKicks.com

April 18, 2009 #

Web Development Community

Trackback from Web Development Community

Making XmlDataSource Work with RSS 1.0, RSS 2.0 and Atom Feeds

Web Development Community

June 14, 2009 #

DotNetShoutout

Making XmlDataSource Work with RSS 1.0, RSS 2.0 and Atom Feeds

Thank you for submitting this cool story - Trackback from DotNetShoutout

DotNetShoutout

Powered by BlogEngine.NET1.5.0.7 | Theme by Mads Kristensen