Parse podcast RSS feed in C#

I am having some difficulty with podcast RSS feeds.  I am able to read the feed in and parse the tags without a problem, but I run into problems as I iterate through each item in the channel and trying to figure out which attribute actually has the link to the MP3.  

Some feeds use the link tag, others use the enclosure and then there are the itunes tags.  Is there any advice on the best way to handle this?

This is the code I'm currently working with.
if (string.IsNullOrEmpty(url))
                throw new ArgumentNullException("url");
 
           RSSFeed feed = new RSSFeed();
 
            try
            {
                string content = GetURLSource(url);
                XmlDocument rssDoc = new XmlDocument();
                rssDoc.LoadXml(content);
                XmlNodeList rssNodes = rssDoc.SelectNodes("/rss/channel/item");
 
                feed.Link = rssDoc.SelectSingleNode("/rss/channel/link") != null ? rssDoc.SelectSingleNode("/rss/channel/link").InnerText : string.Empty;
                feed.Title = rssDoc.SelectSingleNode("/rss/channel/title") != null ? rssDoc.SelectSingleNode("/rss/channel/title").InnerText : string.Empty;
                feed.Description = rssDoc.SelectSingleNode("/rss/channel/description") != null ? rssDoc.SelectSingleNode("/rss/channel/description").InnerText : string.Empty;
 
                if (rssNodes != null)
                    foreach (XmlNode node in rssNodes)
                    {
                        RSSEvent rssEvent = new RSSEvent
                        {
                            CopyRight = node.SelectSingleNode("copyright") != null ? node.SelectSingleNode("copyright").InnerText : string.Empty,
                            Description = node.SelectSingleNode("description") != null ? node.SelectSingleNode("description").InnerText : string.Empty,
                            Link = node.SelectSingleNode("link") != null ? node.SelectSingleNode("link").InnerText : string.Empty,
                            PubDate = node.SelectSingleNode("pubdate") != null ? node.SelectSingleNode("pubdate").InnerText : string.Empty,
                            Title = node.SelectSingleNode("title") != null ? node.SelectSingleNode("title").InnerText : string.Empty,
                            EnclosureUrl = node.SelectSingleNode("enclosure") != null ? node.SelectSingleNode("enclosure").Attributes["url"].InnerText : string.Empty,
                            EnclosureType = node.SelectSingleNode("enclosure") != null ? node.SelectSingleNode("enclosure").Attributes["type"].InnerText : string.Empty,
                            EnclosureLength = node.SelectSingleNode("enclosure") != null ? node.SelectSingleNode("enclosure").Attributes["length"].InnerText : string.Empty
                        };
 
                        feed.Events.Add(rssEvent);
                    }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message, ex.InnerException);
            }
 
            return feed;

Open in new window

andy_eeAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

MogalManicCommented:
Instead of doing an if for every node, I would try to determine the type and then delegate the parsing to the specific handler.  That way you will have only one logical expression and the code would be much easier to read.

Something like this:

 

  IRssHandler handler=null;
  if (rssDoc.SelectNodes(...)=="???")
    handler=new ITunesRSSHandler(rssDoc);
  else if (rssDoc.SelectNodes(...2)==""???2"
    handler - new PodCast1Handler(rssDoc)
  //......One if for each handler type
 
 feed=handler.parseFeed();
feed.Events.addRange(handler.ParseEvents());
 
 
//And one handler would look like this
public class PodCastHandler : IRSSHandler
{
    PodCastHandler(XmldDocument rssDoc)
    {
       //Initialze class...
       XmlNodeList rssNodes = rssDoc.SelectNodes("/rss/channel/item");
       //...
    }
 
    public Feed parseFeed()
    {
         RSSFeed feed = new RSSFeed();
 
         feed.Link = rssDoc.SelectSingleNode("/rss/channel/link").InnerText;
         feed.Title = rssDoc.SelectSingleNode("/rss/channel/title").InnerText;
         feed.Description = rssDoc.SelectSingleNode("/rss/channel/description").InnerText;
 
         return feed;
 
    }
 
    public RSSEvent[] parseEvents()
    {
       RssEvent[] events=null;
       if (rssNodes != null)
       {
          events=new RssEvents[rssNodes.Count];
          foreach (XmlNode node in rssNodes)
          {
               RSSEvent rssEvent = new RSSEvent
               CopyRight = node.SelectSingleNode("copyright").InnerText;
               //...Set Other properties...
               events[evtIdx++]=rssEvent;
          }
       }
       return events;
     }
}

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
andy_eeAuthor Commented:
Excellent response.  However I need to find a clean way of differentiating between a podcast feed and an iTunes feed.
0
andy_eeAuthor Commented:
... also, you list an interface called IRssHandler.  Is there code for that please?
0
HTML5 and CSS3 Fundamentals

Build a website from the ground up by first learning the fundamentals of HTML5 and CSS3, the two popular programming languages used to present content online. HTML deals with fonts, colors, graphics, and hyperlinks, while CSS describes how HTML elements are to be displayed.

MogalManicCommented:
IRssHandler is the base interface for all of the "RSS Handlers".  It would look something like this:
public interface IRssHandler
{
    ///<Summary>Parse the root element of the feed and build a Feed object</Summary>
    public Feed parseFeed();
    ///<Summary>Parse the feed events into RSSEvent collection</Summary>
    public RSSEvent[] parseEvents();
}

Open in new window

0
MogalManicCommented:
To check if it is a iTunes feed you should just check to see if it has an itunes namespace.  Something like this:
if (rssDoc.DocumentElement.GetAttribute("xmlns:itunes")!="")
  handler=new iTunesRSSHandler(rssDoc);
else if //Other rss types here

Open in new window

0
andy_eeAuthor Commented:
Thanks!  Excellent advice.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Web Languages and Standards

From novice to tech pro — start learning today.