I am new to LINQ. I need to return the id with the correct price information for today's date for each MPrice.
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>
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);
}
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With