I have an XML file with the following structure:
<Entities> <Request> <ID> A1 </ID> <!-- Can be multiple records with same values --> <Finance> <StartDate> Some Date </StartDate> <!-- Unique per ID --> </Finance> <Request> <Request> ... </Request> </Entities>
There can be multiple requests with same ID but in such cases, the StartDate needs to be different per Request.
I need to take out the latest two dates per ID.
If this were an SQL table with ID and StartDate columns, I’d use the following query which is working fine:
SELECT ID, StartDate
FROM ( SELECT ID, StartDate, RANK()
OVER (PARTITION BY ID ORDER BY StartDate DESC) rank
FROM Request )
WHERE rank IN ('1','2')
But I have the data in XML format and the best I could come up with was ordering the data according to ID, StartDate. I still need to dug out latest two dates for every ID there is.
var cafrequests =
from request in xdoc.Descendants("Request") orderby (int)request.Element("ID"), (DateTime)request.Element("Finance").Element("StartDate") ascending select new { ID = request.Element("ID"), StartDate = request.Element("Finance").Element("StartDate"), };
Using Take(2) would only fetch me the top 2 lines of data, not top 2 per ID.
So can anybody tell me what is the equivalent of the above SQL statement in LINQ? I don’t want to parse and manage XML using loops and conditionals in C# and I’m quite new to LINQ (read about it yesterday and started using it) and I’m still going through the documentation.
This works, I tested it:
doc.Element("Entities")– gets element named Entity which is a root element of the document, another way of retrieving this element would bedoc.RootElements("Request")– gets elements named Request that are children of EntityGroupBy– is a method somewhat similar toGROUP BYin SQL, first parameter is element that is going to be used for grouping, it is a child of a Request element, second parameter is an element selector function that parsesDateTimefrom StartDate element (which is a child of Finance element which is a child of Request element).Select(el => new...)– method that creates anonymous type that holds ID and 2 records that have highest dates for IDHere is a query that gets the same result, but written in an query syntax (example above is method syntax):