0

I have the following XML structure, I need to filter it using LINQ by attribute "date" where the value of the "date" attribute is less than today.

The attribute date is on the format "yyyymmddhhmmss +Zone".

For example in the given XML first node date="20200318123000 +0000" means:

year=2020,

month=03,

day=18,

hours=12,

minutes=30,

seconds=00 &

timezone = UTC +0000.

<?xml version="1.0" encoding="utf-8"?>
<books>
 <book date="20200318123000 +0000">
   <length units="pages">270</length>
   <title>Book 1 Title</title>
   <category>Book 1 Category</category>
   <desc>Book 1 Description</desc>
 </book>
 <book date="20200319123000 +0000">
   <length units="pages">144</length>
   <title>Book 2 Title</title>
   <category>Book 2 Category</category>
   <desc>Book 2 Description</desc>
 </book>
</books>

I have tried doing it using the below code but it returns nothing in "IEnumerable elements" instead of filtered nodes.

  XDocument xDocument = XDocument.Load(fileName);

  DateTime t;

  IEnumerable<XElement> elements = xDocument.Descendants("book")
  .Where(d => d.NodeType == XmlNodeType.Attribute && d.Name.Equals("date") && 
  DateTime.TryParse(d.ToString().Split('+').First().Trim(), out t) && t < 
  DateTime.Today)
  .ToList();
Gowri G
  • 420
  • 4
  • 18
Max
  • 470
  • 2
  • 9
  • 22
  • @Fabio updated the question to include what I have tried. – Max Mar 19 '20 at 07:33
  • You probably can try to parse date with `TryParseExact` method where you can provide format used for dates in xml. – Fabio Mar 19 '20 at 07:44
  • 1
    `DateTimeOffset.ParseExact("20200319123000 +0000", "yyyyMMddHHmmss zzzz", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);`. Use `DateTimeStyles.AssumeLocal`, if you need to assumed that. – Jimi Mar 19 '20 at 07:49
  • 1
    Also, it doesn't look like you're parsing the Elements correctly. Try something like: `var elements = xDocument.Descendants("book").Where(b => b.NodeType == XmlNodeType.Element && DateTimeOffset.ParseExact(b.FirstAttribute.Value, "yyyyMMddHHmmss zzzz", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal) < DateTimeOffset.Now);` – Jimi Mar 19 '20 at 08:04

1 Answers1

1

Try following :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);

            Dictionary<DateTime, List<XElement>> dict = doc.Descendants("book")
                .GroupBy(x => DateTime.ParseExact((string)x.Attribute("date"),"yyyyMMddHHmmss zzzz", System.Globalization.CultureInfo.InvariantCulture), y => y)
                .ToDictionary(x => x.Key, x => x.ToList());

            List<KeyValuePair<DateTime, XElement>> beforeToday = dict.Where(x => x.Key < DateTime.Now.Date).SelectMany(x => x.Value.Select(y => new KeyValuePair<DateTime, XElement>(x.Key, y))).ToList(); 
        }
    }
}
jdweng
  • 33,250
  • 2
  • 15
  • 20