tags:

views:

430

answers:

2

Hi, I have a XElement that maps like follows:

<book>
    <author>sadfasdf</author>
    <title>asdfasdf</title>
    <year>1999</year>
</book>
<book>
    <author>asdfasdf</author>
    <title>asdfasdf</title>
    <year>1888</year>
</book>
<book>
    <author>asdfsdf</author>
    <title>asdfasdf</title>
    <year>1777</year>
</book>

How can I sort the books by author or title or year? Thanks

+5  A: 

Do you want to read (query) the data in a specific order, or do you actually want to re-order the data in the xml? To read in a specific order, just use the LINQ OrderBy method:

    var qry = from book in el.Elements("book")
              orderby (int)book.Element("year")
              select new
              {
                  Year = (int)book.Element("year"),
                  Title = (string)book.Element("title"),
                  Author = (string)book.Element("author")
              };

(edited) Changing the xml is trickier... maybe something like:

    var qry = (from book in el.Elements("book")
               orderby (int)book.Element("year")
               select book).ToArray();

    foreach (var book in qry) book.Remove();
    foreach (var book in qry) el.Add(book);
Marc Gravell
I just want to reorder it. could you provide a real world example?
pistacchio
+2  A: 

It's doable, but slightly odd:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

class Test
{
    static void Main()
    {
        string xml = 
@"<books>
  <book>
    <author>sadfasdf</author>
    <title>asdfasdf</title>
    <year>1999</year>
  </book>
  <book>
    <author>asdfasdf</author>
    <title>asdfasdf</title>
    <year>1888</year>
  </book>
  <book>
    <author>asdfsdf</author>
    <title>asdfasdf</title>
    <year>1777</year>
  </book>
</books>";
        XElement root = XElement.Parse(xml);

        List<XElement> ordered = root.Elements("book")
            .OrderBy(element => (int)element.Element("year"))
            .ToList();

        // Clear everything from the root element
        root.RemoveAll();
        root.Add(ordered);

        Console.WriteLine(root);
    }
}

Note that if you have other content under your root node, you should call Remove on each XElement before adding them, instead of just calling RemoveAll.

Jon Skeet
Darn, I was just typing this up... I've been Skeet sniped!
jfar