tags:

views:

32

answers:

2
<?xml version="1.0" encoding="utf-8"?>
<Customers>
   <Customer Id="1">
    <Name>rtertr</Name>
    <DOB>2010-12-12T00:00:00</DOB>
    <EMail>[email protected]</EMail>
  </Customer>
  <Customer Id="2">
    <Name>west</Name>
    <DOB>0001-01-01T00:00:00</DOB>
    <EMail>[email protected]</EMail>
   </Customer> 
  <Customer Id="3">
    <Name>west</Name>
    <DOB>0001-01-01T00:00:00</DOB>
    <EMail>[email protected]</EMail>
   </Customer> 
</Customers>

How to find Min and Max CustomerId from the above sample XML using LinQ to XML? For example for the above sample, Min should be 1 and Max should be 3

+1  A: 
var doc = XDocument.Parse(...);

//.ToArray() so we only iterate once
var ids = doc.Root.Elements("Customer").Select(c => (int)c.Attribute("Id")).ToArray();
var minId = ids.Min();
var maxId = ids.Max();

As dtb´s comment says, this will iterate the array twice but only the xml document once. I feel this is a good compromise between readability and performance - at least when its not used in production code. Iterating the int array will be a small factor of the xml document iteration. The best solution is to only iterate the document once and keep track of the values along the way as dtb shows.

lasseespeholt
Won't this iterate all the XML nodes first, and then the resulting array twice?
dtb
@dtb That is true. But it is a question on what performance you want and how readable it such be. And I thought this is a good compromise because iterating the int array is a small factor compared to iterate a document :) I see you have made a aggregation which keep track of both values which is a fine solution - but not readable for a newbie...
lasseespeholt
A: 

You can use the Min and Max extension methods:

var doc = XDocument.Parse("<Customers>...</Customers>");

var minId = doc.Root.Elements().Min(e => (int)e.Attribute("Id"));
var maxId = doc.Root.Elements().Max(e => (int)e.Attribute("Id"));

or the Aggregate extension method (iterating the XML document only once):

var doc = XDocument.Parse("<Customers>...</Customers>");

var result = doc.Root
                .Elements()
                .Select(e => (int)e.Attribute("Id"))
                .Aggregate(
                    Tuple.Create(int.MinValue, int.MaxValue),
                    (t, x) => Tuple.Create(Math.Max(t.Item1, x),
                                           Math.Min(t.Item2, x)));

var maxId = result.Item1;
var minId = result.Item2;
dtb