tags:

views:

913

answers:

2

I have a noob LINQ to XML question. I have xml like so:

<pages>
    <page Name="Welcome" Control="Welcome" Order="1"></page>
    <page Name="Summary" Control="Summary" Order="10"></page>
</pages>

I need to read in the data and save it to an array ordered by the "Order" attribute. Here's what I have; the compiler is coughing on the order by clause.

//read in app.xml data into _Pages
XDocument doc = XDocument.Parse("app.xml");
XElement Pages = (XElement)doc.Descendants("pages");

var Pages1 =
  (from page in Pages  //<-- error on orderby clause
  orderby page.order
  select page).ToArray();

I've search SO and found several LINQ to XML answers looking like this, but say something about the xml fragment in an object like Pages. But never show it's type.

Thanks

EDIT: The error is: Could not find an implementation of the query pattern for source type 'System.Xml.Linq.XElement'. 'OrderBy' not found.

+1  A: 

Try page.Attribute("order") instead of page.order.

Matt Wrock
thanks for the answer Matt. I've edited by question to make it more clear. It's throwing the error on the Pages (XElement) object. Perhaps XElement isn't the proper object type for this type of query?
Chad
The return value of `doc.Descendants("pages")` is of type `IEnumerable<XElement>` - you cannot cast that to `XElement`. Use either `.First()` if there are actually several elements and you just want the first one, or `.Single()` if you know there's going to be only one (and want an exception if there will be more).
Pavel Minaev
I'm upvoting because this is a useful answer.
RichardOD
+1  A: 

I'm guessing you want something like this:

using System.Linq;
using System.Xml.Linq;
namespace SampleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            string xml = @"<pages>   
                <page Name=""Summary"" Control=""Summary"" Order=""10""></page> 
                <page Name=""Welcome"" Control=""Welcome"" Order=""1""></page>
            </pages>";
            XDocument doc = XDocument.Parse(xml);
            XElement[] pages = doc
              .Descendants("page")
              .OrderBy(x => (int)x.Attribute("Order"))
              .ToArray();
        }
    }
}

Does that work for you? This works providing the Order attribute is always an int (I have made an assumption here).

RichardOD
Richard, the Order is always an int.However this throws a compiler error on me(VS2k8 SP1).'System.Collections.Generic.IEnumerable<System.Xml.Linq.XElement>' does not contain a definition for 'OrderBy' and no extension method 'OrderBy' accepting a first argument of type 'System.Collections.Generic.IEnumerable<System.Xml.Linq.XElement>' could be found (are you missing a using directive or an assembly reference?) C:\Users\devloper\Documents\Visual Studio 2008\Projects\OCHSHP_APP_FC\OCHSHP_APP_FC\WebApp.cs 59 18 OCHSHP_APP_FC
Chad
Ah OK- make sure you have these using statements- using System.Linq;using System.Xml.Linq;
RichardOD
I've update the code sample with a complete listing.
RichardOD
Thanks Richard. I didn't have System.Linq included -- I only had System.xml.Linq on mine.
Chad
That's one of the gotchas with extension methods. Glad it is now sorted!
RichardOD