Reading RSS is a common and simple task in Python using the standard library, unfortunately it uses parts of the standard library that are not implemented in IronPython. Luckily it isn't very difficult using the .NET framework either. There is an example Parsing RSS on the IronPython Cookbook site that demonstrates it.
In the implementation below I've used all XML processing code from the Parsing RSS example. I removed the class RSSFeedSubscriptions as I didn't need the functionality and I felt it made the sample more clear. I split the RSSFeedFetcher into an RSSFeed class for the feed data and an RSSFeedReader class for handling the downloading and XML processing. I think it is much a better separation of functionality.
I found the the exception handling code in the original sample that outputs an exception message was itself throwing an exception, so I removed it. I don't think its ideal effectively suppressing exceptions and printing a message but its good enough for what I'm using it for. If anyone has a suggestion or I improve the module myself, I'll update this post.
The example usage is shown in the Main section. I used an AutoResetEvent in the test to keep the tread alive until the asynchronous event is fired and the results are output.
import clr clr.AddReference('System.Xml') from System.Net import WebClient from System.Xml import XmlDocument, XmlTextReader from System.IO import StreamReader, MemoryStream import System class RSSFeedItem(object): def __init__(self): self.Title = "" self.Description = "" self.Link = "" self.GUID = "" class RSSFeed(): def __init__(self, URL): self.FeedURL = URL self.ChannelName = "" self.Items =  self.BadCount = 0 class RSSFeedReader(object): def __init__(self,URL, onComplete): self.onComplete = onComplete self.feed = RSSFeed(URL) def Parse(self, sender, args): rssBytes = args.Result try: xmlDoc = XmlDocument() stream = MemoryStream(rssBytes) xmlDoc.Load(stream) rssNode = xmlDoc.SelectSingleNode("rss") channelNodes = rssNode.ChildNodes for channelNode in channelNodes: itemNodes = channelNode.SelectNodes("item") self.feed.ChannelName = channelNode.SelectSingleNode("title").InnerText for itemNode in itemNodes: try: newitem = RSSFeedItem() newitem.Title = str(itemNode.SelectSingleNode("title").InnerText) newitem.Description = str(itemNode.SelectSingleNode("description").InnerText) newitem.Link = str(itemNode.SelectSingleNode("link").InnerText) if itemNode.SelectSingleNode("guid"): newitem.GUID = str(itemNode.SelectSingleNode("guid").InnerText) self.feed.Items.append(newitem) except: self.feed.BadCount = self.feed.BadCount + 1 except: print "Error Parsing Results" self.onComplete(self.feed) def ReadAsync(self): try: webClient = WebClient() webClient.DownloadDataCompleted += self.Parse uri = System.Uri(self.feed.FeedURL) webClient.DownloadDataAsync(uri) except: print "Error Starting Read" if __name__ == "__main__": from System.Threading import * are = AutoResetEvent(False) def callback(feed): print "Results!" for item in feed.Items: print item.Title print item.Description print item.Link are.Set() feedReader = RSSFeedReader("http://feeds.feedburner.com/sharpthinking", callback) feedReader.ReadAsync() are.WaitOne()
One of the things I like about IronPython 2 is that this code alone can be run from the command line. Simply saving this code as rssreader.py and running it from the command line with ipy rssreader.py will run the test code at the bottom which will output recent posts from this weblog.