This blog post is about using LINQ to XML when the XML document has multiple namespaces defined. I’m using the Twitter API as example.
The sample XML
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns:google="http://base.google.com/ns/1.0" xml:lang="en-US" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns="http://www.w3.org/2005/Atom" xmlns:twitter="http://api.twitter.com/">
<entry>
<id>tag:search.twitter.com,2005:12568401714</id>
<published>2010-04-21T10:07:04Z</published>
<link type="text/html" href="http://twitter.com/bergdaniel/statuses/12568401714" rel="alternate"/>
<title>The installation of DTCPing should come with a warning that says: "You have a long terrible journey ahead of you, Hobbit."</title>
<content type="html">The installation of DTCPing should come with a warning that says: &quot;You have a long terrible journey ahead of you, Hobbit.&quot;</content>
<updated>2010-04-21T10:07:04Z</updated>
<link type="image/png" href="http://a3.twimg.com/profile_images/622795701/daniel-square_normal.jpg" rel="image"/>
<twitter:geo>
</twitter:geo>
<twitter:metadata>
<twitter:result_type>recent</twitter:result_type>
</twitter:metadata>
<twitter:source><a href="http://www.tweetdeck.com" rel="nofollow">TweetDeck</a></twitter:source>
<twitter:lang>en</twitter:lang>
<author>
<name>bergdaniel (Daniel Berg)</name>
<uri>http://twitter.com/bergdaniel</uri>
</author>
</entry>
</feed>
This is the partial XML result of the Twitter API query “http://search.twitter.com/search.atom?q=bergdaniel”. It includes a number of namespaces – the two most important being “http://www.w3.org/2005/atom” and “http://api.twitter.com/”.
Using LINQ to XML
public class Twitter
{
private static XNamespace NAMESPACE_ATOM = "http://www.w3.org/2005/Atom";
private static XNamespace NAMESPACE_TWITTER = "http://api.twitter.com/";
public static List<Tweet> ParseTwitterFeed(string twitterUrlQuery)
{
XDocument tweetResults = XDocument.Load(twitterUrlQuery);
var tweets = from tweet in tweetResults.Descendants(NAMESPACE_ATOM + "entry")
select new Tweet
{
Author = tweet.Element(NAMESPACE_ATOM + "author").Element(NAMESPACE_ATOM + "name").Value,
Content = tweet.Element(NAMESPACE_ATOM + "content").Value,
Published = (DateTime)tweet.Element(NAMESPACE_ATOM + "updated"),
Source = tweet.Element(NAMESPACE_TWITTER + "source").Value
};
return tweets.ToList<Tweet>();
}
}
In order to query the XML with LINQ we need to define the namespaces and pass them as parameters along with the element names. Since the “atom”-namespace is the default namespace all elements that are not prefixed with <correspondingNamespace:someElement> need to pass the “atom”-namespace as parameter. The elements that are prefixed with <twitter:elementName> need to have the “twitter”-namespace passed as parameter.
Important
Make sure that the namespace is defined exactly as it is in the XML. If you miss a trailing slash (“http://api.twitter.com” instead of “http://api.twitter.com/”) you’ll end up with an NullReferenceException like this:
