Quick and Dirty Linq to XML
Hi All,
So this is a topic that I personally found semi difficult to find some good documentation AND explanation on. The goal here is to provide a single sample of Linq to XML and a peice by peice explanation of it. Lets first start off with, Why? Well parsing xml can be a painful task and definitely very time consuming. Linq is a powerful tool for querying many different formats for storing information, so it is a pretty good thing to just generally master because its similiar across the board. It also greatly reduces the time to code and the code complexity for querying complex xml data.
So Lets move on to the example. I have seen a lot of questions regarding having a string that contains xml data and not knowing what to do with that, because XMLReader takes a stream and so do many other classes. Well Linq to XML makes this task easy without having to create an in memory stream. If you haven't already, add references to System.Xml and System.Xml.Linq to your project; you will need to add using statements for the both as well in each class that uses these libraries.
The below code takes an xml string (from the engadget rss feed) and puts it into an object named FeedItem for doing whatever you want to. Please post any questions you may have. I tried to use as simple of language (in the comments) as I could to make it as easy to understand as possible.
/// <summary>
/// Uses Linq to XML to transform the XML string into items that is then fed into a FeedItem
/// Which in turn is shoved into the feed item list.
/// </summary>
/// <param name="xmlData">xmlData as a string.</param>
private void createFeedItemsFromXML(String xmlData)
{
//Parse the String into an XMLDocument, because thats what Linq likes.
XDocument nXDocument = XDocument.Parse(xmlData);
//Linq to XML query
//item is a run time object (anyonymous type) created where the "item" tag is
//the delineator (any tags under it are considered children within it)
var data = from item in nXDocument.Descendants("item")
select new
{
//creates new properties for item, and grabs the specified tag
//that matches the exact string and the value
//to set each property equal to.
title = item.Element("title").Value,
link = item.Element("link").Value,
description = item.Element("description").Value,
pubDate = item.Element("pubDate").Value
};
//Iterate through each item in data and create a FeedItem out of it.
foreach (var item in data)
{
FeedItem nItem = new FeedItem();
nItem.feedTitle = item.title;
nItem.feedLink = item.link;
nItem.imageSrc = item.description;
nItem.pubDate = item.pubDate;
feedItemList.Add(nItem);
//don't want to kill memory, so limit the feed items to 20.
if (feedItemList.Count > 20)
feedItemList.RemoveAt(0);
}
}
Hope that helps.
~Dave
P.S. Sorry about the bad colorization of the code, the code block doesn't seem to be co-operating with me at the moment.
UPDATE:
There is another way to actually do the query if you have an object such as FeedItem, instead of building an anonymous class on the fly, if you already have a class, you can do the following as well.
var data = from item in nXDocument.Descendants("item")
select new FeedItem
{
//Where FeedTitle, FeedLink, ImageSrc, and PubDate are publicly accessible items in FeedItem.
FeedTitle = item.Element("title").Value,
FeedLink = item.Element("title").Value,
ImageSrc = item.Element("description").Value,
PubDate = item.Element("pubDate").Value
};
Comments
Anonymous
January 05, 2012
Great Post!Anonymous
January 06, 2012
niceAnonymous
January 06, 2012
Nice post, very handy! You can also reduce the size of the result set with the .Take() method on IEnumerable. ex: var result = (from myint in myints select myint).Take(50);Anonymous
January 08, 2012
Nice posting