My first play with LINQ and XML

posted in: Uncategorized | 0

BronwenWeeGo.jpgI’ve been experimenting with the .Net 3.5 framework, so I thought this was a good opportunity to play with LINQ.  I’ve starting doing some spikes to see what’s going to bite me.  For this spike project I’m accessing all my data from XML files rather than SQL Server and using Orcas Beta 2.

So if I’m doing something wrong, or I could do it much simpler..please let me know

Normally I would have created an xsd and used the xsd.exe tool to generate my .Net Classes.  This has always annoyed me since moving to .Net 2 as it generates arrays..which I try never to use anymore and I always end up manually editing the classes to turn the object[] to List<> .

When I first hooked up my XML file that was based on an XSD to LINQ I found it didn’t like the namespace as it’s a strongly typed XML file.  I came across the LinqtoXSD tool and quickly discovered it is for Orcas Beta 1..doh!

So I bit the bullet and created all the classes myself that the XSD tool would normally generate for me. Normally I’d be dead bored, turning all my fields into properties etc and end up with a bunch of really long classes I have to maintain…but wth the changes in .net 3.5, this means i can use Automatic Properties .. YAY.

So a lot of my classes look something like this:

    public class Food
    {        public string FoodName { get; set; }
        public string FoodGroup { get; set; }
        public int CaloriesServe { get; set; }    }

How awesome is that! So many less lines of code!

So I started with a number of food items in an XML file like this:

 <?xml version="1.0" encoding="utf-8"?>
<FOODITEMS>  <FOOD>    <FOODNAME>Banana</FOODNAME>
    <FOODGROUP>Fruit</FOODGROUP>    <CALORIESSERVE>66</CALORIESSERVE>  </FOOD>
  <FOOD>    <FOODNAME>TBone 300Gms</FOODNAME>    <FOODGROUP>Meat</FOODGROUP>
    <CALORIESSERVE>300</CALORIESSERVE>  </FOOD>  <FOOD>
    <FOODNAME>Carrot Small</FOODNAME>    <FOODGROUP>Vegetables</FOODGROUP>
    <CALORIESSERVE>23</CALORIESSERVE>  </FOOD></FOODITEMS>

To load all my food into a list I used to do something like:

            List items = new List();
            FoodItems foodItems = new FoodItems ();
            XmlSerializer reader = new XmlSerializer(foodItems.GetType());
            StreamReader file = new StreamReader(GetFileName(FOOD));
            foodItems = (FoodItems)reader.Deserialize(file);
            file.Close();

Now using LINQ it looks something like this

            XDocument FoodItemsXml = XDocument.Load(GetFileName(FOOD));
            var temp = from feed in FoodItemsXml.Descendants("Food")
                            select new Food                            {
                                FoodName = feed.Element("FoodName").Value,
                                FoodGroup = feed.Element("FoodGroup").Value,
                                CaloriesServe = Convert.ToInt32(feed.Element("CaloriesServe").Value)
                            };            return temp.ToList();

So then I got a bit more complicated and had a xml elements that can have many xml elements.  So I had a Meal Plan that had many Meals which had many food items along with a number of other properties.  My LINQ Statement to grab this looks like:

            XDocument MealPlansXml = XDocument.Load(GetFileName(MEAL_PLAN));
            var temp = from feed in MealPlansXml.Descendants("MealPlan")
                       select new MealPlan                       {
                           MealPlanType = feed.Element("MealPlanType").Value,
                           Meals = (from meals in feed.Elements("Meal")
                                    select new Meal
                                    {
                                        MealType = meals.Element("MealType").Value,
                                        DayNo = Convert.ToInt32(meals.Element("DayNo").Value),
                                        Serves = Convert.ToInt32(meals.Element("Serves").Value),
                                        FoodItem = (from fooditem in meals.Elements("Food")
                                                    select new Food
                                                    {
                                                        FoodName = fooditem.Element("FoodName").Value,
                                                        FoodGroup = fooditem.Element("FoodGroup").Value,
                                                        CaloriesServe = Convert.ToInt32(fooditem.Element("CaloriesServe").Value)
                                                       
                                                    }
                                                   ).ToList()
                                    }
                                    ).ToList()                       };
            return temp.ToList();

Now I’ve just gotta work out how to load this in more simply.




kick it on DotNetKicks.com