Parminder
Parminder

Reputation: 3158

Trouble reading iTunes XML feed

I am trying to read an XML feed from http://itunes.apple.com/us/rss/topsongs/limit=10/genre=2/xml.

I want to access the fields like this:

<im:price amount="1.29000" currency="USD">$1.29</im:price>
<im:releaseDate label="December 31, 1960">1960-12-31T16:00:00-07:00</im:releaseDate>

Here is what I have done so far:

var xml = "http://itunes.apple.com/us/rss/topsongs/limit=10/genre=2/xml";
XmlDocument doc = new XmlDocument();
doc.Load(xml);
XmlNodeList items = doc.SelectNodes("//entry");
foreach (var item in items) {
    // Do something with item.
}

No luck, though. items is null. Why? What am I doing wrong?

Upvotes: 3

Views: 641

Answers (1)

Marcel N.
Marcel N.

Reputation: 13986

You need to create a namespace manager to map the RSS and also the iTunes custom tags namespace URIs to short prefixes (itunes and im in the example below):

var xml = "http://itunes.apple.com/us/rss/topsongs/limit=10/genre=2/xml";

XmlDocument doc = new XmlDocument();
doc.Load(xml);
var namespaceManager = new XmlNamespaceManager(doc.NameTable);
namespaceManager.AddNamespace("itunes", "http://www.w3.org/2005/Atom");
namespaceManager.AddNamespace("im", "http://itunes.apple.com/rss");

XmlNodeList items = doc.SelectNodes("//itunes:entry", namespaceManager);
foreach (XmlNode item in items)
{
    var price = item.SelectSingleNode("im:price", namespaceManager);
    var releaseDate = item.SelectSingleNode("im:releaseDate", namespaceManager);

    if (price != null)
    {
        Console.WriteLine(price.Attributes["amount"].InnerText);
    }

    if (releaseDate != null)
    {
        Console.WriteLine(releaseDate.Attributes["label"].InnerText);
    }
}

For that specific feed you should get 10 entries.

It's in the docs as well:

If the XPath expression does not include a prefix, it is assumed that the namespace URI is the empty namespace. If your XML includes a default namespace, you must still use the XmlNamespaceManager and add a prefix and namespace URI to it; otherwise, you will not get any nodes selected. For more information, see Select Nodes Using XPath Navigation.

Alternatively you can use a namespace-agnostic XPath (from here):

XmlNodeList items = doc.SelectNodes("//*[local-name() = 'entry']");

Finally, not sure why you said items is null. It cannot be. When running your original code you should get this:

enter image description here

Upvotes: 4

Related Questions