XML Parser return specific nodes

I have XML like that

<?xml version="1.0" ?>
<customers>
  <customer>
    <date>22 Aug 2014</date>
    <name>Kevin Anders</name>
    <phone>555.555.5555</phone>
  </customer>
  <customer>
    <date>23 Aug 2014</date>
    <name>Staci Richard</name>
    <phone>555.122.1552</phone>
  </customer>
  <customer>
    <date>25 Aug 2014</date>
  </customer>
</customers>

In the XML some nodes are missing but date node is present in every element. I have around 200 of nodes but i want to parse the xml based on date and just need to return top 4 dates. For example today is 16 june then my xml get the latest date node and return next three days matching nodes. I am able to parse the nodes but not sure how to return top nodes based on date

public static IEnumerable<Customer> StreamBooks(string uri) 
{
    using (XmlReader reader = XmlReader.Create(uri))
    {
        string name = null;
        string phone = null;

        reader.MoveToContent();
        while (reader.Read())
        {
            if (reader.NodeType == XmlNodeType.Element
                && reader.Name == "customer")
            {
                while (reader.Read())
                {
                     if (reader.NodeType == XmlNodeType.Element &&
                         reader.Name == "name")
                     {
                         name = reader.ReadString();
                         break;
                     }
                }
                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Element &&
                        reader.Name == "phone")
                    {
                        phone = reader.ReadString();
                        break;
                    }
                }
                yield return new Customer() { Name = name, Phone  = phone };
            }
        }
    }
}
Jon Skeet
people
quotationmark

I'd start off by removing your current code to retrieve a sequence of customers, and instead just use LINQ to XML:

var customers = XDocument.Load(uri)
                         .Root.Elements("customer")
                         .Select(x => new Customer {
                                     Date = (DateTime) x.Element("date"),
                                     Name = (string) x.Element("name"),
                                     Phone = (string) x.Element("phone")
                                 });

This requires you to change your date format to "yyyy-MM-dd" which is a standard XML date format. (So "2014-08-23" instead of "23 Aug 2014" for example.)

If you have to keep the existing date format, you can use:

var customers = XDocument.Load(uri)
    .Root.Elements("customer")
    .Select(x => new Customer {
        Date = DateTime.ParseExact(x.Element("date").Value, "d MMM yyyy",
                                   CultureInfo.InvariantCulture),
        Name = (string) x.Element("name"),
        Phone = (string) x.Element("phone")
    });

You might also want to add a call to ToList() after Select, if you want the whole list of customers for other reasons.

After this, the fact that the original data source was XML is irrelevant. You can then use OrderByDescending to sort by date with the most recent first, and Take to limit the results:

var recentCustomers = customers.OrderByDescending(c => c.Date)
                               .Take(4);

LINQ is a very useful technique for querying data. I strongly recommend that you learn more about is - search for information on MSDN, tutorials etc.

people

See more on this question at Stackoverflow