Multiple namespaces when using LINQ to XML
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<?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: &quot;You have a long terrible journey ahead of you, Hobbit.&quot;</title> <content type="html">The installation of DTCPing should come with a warning that says: &amp;quot;You have a long terrible journey ahead of you, Hobbit.&amp;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>&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;</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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
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: