Tuesday, January 05, 2010

GroupBy with XElement

I am working on a new project and experimenting with Linq. It is very powerful and useful however it is a paradigm change for us old geezers.

The problem at hand was an XML string that needs to be sorted by a the value of an inner node:

<a>
  <b>
    <c>value1</c>
  </b>
  <b>
    <c>value2</c>
  </b>
  <b>
    <c>value1</c>
  </b>
</a>

I want to grab a list of "b" sorted by "c".

So I tried:
var xmldoc = XElement.Load("file.xml");
var grouplist1 = xmldoc.Elements("b").GroupBy(x => x.Elements("c").Select(y => y.Value);

When I do that the key is not the value1 but some sort of IEnumerable.
Then I tried:

var grouplist1 = xmldoc.Elements("b").GroupBy(x => x.Elements("c").Select(y => y.Value);

Then the compiler complained that I cannot cast an IEnumerable to string.

The issue is that within XElement you can have multiple "c"s although we know it could not. So this finally works:

var grouplist1 = xmldoc.Elements("b").GroupBy(x => x.Elements("c").Select(y => y.Value).ElementAt(0);

Of course it assumes there is at leaat one "c" node inside or else it would not work.

Lesson learned:
(1) types are still your friend. Declaring them make things easier.
(2) Break up Linq queries into smaller function calls. You will get the right result faster. At least it works for me.
 
Listed on BlogShares