Friday, 21 March 2008

Selecting Custom Objects from LINQ

I have been teaching myself WPF and LINQ to XML to objects by working on a very simple game for my children helping them to learn their "key words" and do some basic maths.

I have the key words stored in a fairly simple XML structure:

<?xml version="1.0" encoding="utf-8" ?>
<KeyWords>
   <Group Name="Level 1">
     <KeyWord>and</KeyWord>
     <KeyWord>cat</KeyWord>
     <KeyWord>he</KeyWord>
     <KeyWord>I</KeyWord>
...

and a KeyWord class to store them in.

class KeyWord 
{
     public string Word { get; set; }
     public string Group { get; set; }
}

The foreach way of parsing the XML is simple enough:

foreach (XElement group in xraw.Elements("Group")) 
{
     foreach (XElement word in group.Elements("KeyWord"))
     {
         wordsList.Add(new KeyWord() 
             { Word = word.Value, 
               Group = group.Attribute("Name").Value });
     }
}

But I wanted to remove the nested foreach loops and do it in one simple LINQ query. It took me a little while to work out how it was done, but once you know it is very simple:

keyWords = (from keyWord in 
    xraw.Elements("Group").Elements("KeyWord")
    select new KeyWord 
        { Word = keyWord.Value, 
          Group = keyWord.Parent.Attribute("Name").Value });

and that's all there is to it. Remarkably simple.

4 comments:

vzdesic said...

Is xraw variable contain loaded xml document?

vzdesic said...

Class behind this object should implement IEnumerable? Is this true?

Unknown said...

Hi vzdesic, the code to load xraw is simply:
var xraw = XElement.Load("KeyWords.xml");

James Wilson said...

Very nice! I had a feeling it was possible to do something like this but had yet to figure it out or find a solution that didn't involve a foreach loop. This is impressive, thanks for sharing!