tags:

views:

643

answers:

2

I am new to LINQ and there is an urgent need to finish this project quickly. I need to return the id with the correct price information for todays date for each MPrice. Any advice is well appreciated! Here is an example of the XML:

<Pricing>
<MPrice>
    <Id>0079</Id>
      <Price>
        <Price>31.25</Price>
        <StartDt>2009-8-01</StartDt>
        <EndDt>2009-08-26</EndDt>
      </Price>
      <Price>
        <ListPrice>131.25</ListPrice>
        <StartDt>2009-08-26</StartDt>
        <EndDt>9999-12-31</EndDt>
       </Price>
   </MPrice>
   <MPrice>
    <Id>0081</Id>
      <Price>
        <Price>131.25</Price>
        <StartDt>2009-8-01</StartDt>
        <EndDt>2009-08-26</EndDt>
      </Price>
      <Price>
        <ListPrice>231.25</ListPrice>
        <StartDt>2009-08-26</StartDt>
        <EndDt>9999-12-31</EndDt>
       </Price>
   </MPrice> 
</Pricing>
+4  A: 
string id = yourDocument
                .Descendants("Pricing")
                .Descendants<XElement>("MPrice")
                .Where<XElement>(i => i.Descendants("Price")
                                        .Descendants<XElement>("StartDt")
                                        .Select<XElement, DateTime>(s => DateTime.Parse(s.Value))
                                        .FirstOrDefault<DateTime>().Date == DateTime.Now.Date)
                .Select<XElement, string>(i => i.Descendants("Id").FirstOrDefault<XElement>().Value)
                .FirstOrDefault<string>();

This should work assuming that the id is a string. You can make it an int.

You should do some checks to make sure the date is correct etc.. . . , but this is a quick example that should work for given Xml example if Start Date is changed to 2009-9-03 or the current dates date.

David Basarab
+6  A: 

Here is one way of doing it:

using System;
using System.Linq;
using System.Xml.Linq;

class Program
{
    static void Main()
    {
     String xml = @"<Pricing>
      <MPrice>
          <Id>0079</Id>
          <Price>
       <Price>31.25</Price>
       <StartDt>2009-8-01</StartDt>
       <EndDt>2009-08-26</EndDt>
          </Price>
          <Price>
       <ListPrice>131.25</ListPrice>
       <StartDt>2009-08-26</StartDt>
       <EndDt>9999-12-31</EndDt>
          </Price>
      </MPrice>
        </Pricing>";

     var priceInfo = from e in XElement.Parse(xml).Elements("MPrice").Elements("Price")
       let start = DateTime.Parse(e.Descendants("StartDt").FirstOrDefault().Value)
       let end = DateTime.Parse(e.Descendants("EndDt").FirstOrDefault().Value)
       where start < DateTime.Now && end > DateTime.Now
       select new { Id = e.Parent.Element("Id").Value, ListPrice = e.Element("ListPrice").Value };

     Console.WriteLine(priceInfo.FirstOrDefault().Id);
     Console.WriteLine(priceInfo.FirstOrDefault().ListPrice);
    }
}

Output:

0079
131.25

Please note that there needs to be much more error checking than this example provides. I would specifically add checking around the parsing of the datetime (perhaps by using a function that wraps DateTime.TryParseExact).

Edit: If you want to use an XDocument instead of an XElement you will need to make a subtle change to the query (notice the usage of the Descendants method instead of the Elements method):

var priceInfo = from e in XDocument.Parse(xml).Descendants("MPrice").Elements("Price")
     let start = DateTime.Parse(e.Descendants("StartDt").FirstOrDefault().Value)
     let end = DateTime.Parse(e.Descendants("EndDt").FirstOrDefault().Value)
     where start < DateTime.Now && end > DateTime.Now
     select new { Id = e.Parent.Element("Id").Value, ListPrice = e.Element("ListPrice").Value };

Remember that you don't need to use an XDocument unless you are working with the XML as a true document. In most cases, the XElement type is sufficient.

Edit #2: If you want to load the XDocument from disk then use this approach:

using System;
using System.Linq;
using System.Xml.Linq;

class Program
{
    static void Main()
    {
     XDocument document = XDocument.Load(@"d:\test.xml");

     var priceInfo = from e in document.Descendants("MPrice").Elements("Price")
       let start = DateTime.Parse(e.Descendants("StartDt").FirstOrDefault().Value)
       let end = DateTime.Parse(e.Descendants("EndDt").FirstOrDefault().Value)
       where start < DateTime.Now && end > DateTime.Now
       select new { Id = e.Parent.Element("Id").Value, ListPrice = e.Element("ListPrice").Value };

     Console.WriteLine(priceInfo.FirstOrDefault().Id);
     Console.WriteLine(priceInfo.FirstOrDefault().ListPrice);
    }
}
Andrew Hare
Can I do the same parsing using XDocument instead of XElement?
SDC
Yes, you can! Please see my edit.
Andrew Hare
Still doesn't seem to work. I am using: XDocument xmlDoc = XDocument.Load("my.xml");Now when I call the : XDocument.Parse(xml).Descendants("MPrice").Elements("Price")I receive an error with not converted XDocument to string. Any ideas?
SDC
If you have already loaded the XML into the `XDocument` then you don't need to call `XDocument.Parse`. I will edit again to demonstrate how to do it with an XML file on disk.
Andrew Hare
Thank you for your time and help. The project is almost completed and I learned a few new things. Thanks
SDC