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)
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:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<!-- Remove any prefixes -->
<!-- Work through attributes -->
<!-- Remove any attribute prefixes -->
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.
Below is a simple function I wrote to sniff out the type of feed we're dealing with:
protected string guessFormat(string xmlFeed)
xmlFeed = xmlFeed.ToLower();
else if (xmlFeed.Contains("<rss") && xmlFeed.Contains("<channel"))
else if (xmlFeed.Contains("<feed") && xmlFeed.Contains("<entry"))
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">
<a target="_blank" href='<%# XPath("link") %>'>
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;
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.