Search code examples
c#xmllinq-to-xmlxelement

maximum DateTime in XML


I am trying to find the maximum DateTime value in my XML.

Here is a sample of the XML:

<?xml version="1.0" encoding="utf-16"?>
<?xml-stylesheet type='text/xsl' href='http://127.0.0.123/sitemaps/xmltemplate/main-sitemap.xsl'?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
  <url>
    <loc>http://127.0.0.123/?????</loc>
    <lastmod>2018-05-13</lastmod>
    <changefreq>daily</changefreq>
    <priority>0.1</priority>
  </url>
  <url>
    <loc>http://127.0.0.123/?????-????</loc>
    <lastmod>2018-05-26</lastmod>
    <changefreq>daily</changefreq>
    <priority>0.1</priority>
  </url>
</urlset>

And here's the code I'm trying to use:

XDocument xdoc = XDocument.Load(FullAddressXML);
var maxId = xdoc.Elements("url").Select(x => new {                
        MaxDateTime = x.Descendants("lastmod").Max(y=>(DateTime)y)
    });

When I run this, maxId is empty.


Solution

  • There are three problems here:

    • You're calling xdoc.Elements("url") which will never return any elements, because there are no url elements as the direct descendant of the document; you'd want xdoc.Root.Elements to find the url elements within the root element
    • You're providing the local name of the elements, but due to namespace defaulting, they're actually in a namespace of "http://www.sitemaps.org/schemas/sitemap/0.9" which you aren't specifying, so it won't find any elements
    • You're finding a sequence of maximum DateTime values, one per url element, which almost certainly isn't what you want to do - you presumably want the maximum across all URLs.

    Additionally, it's not clear why you're creating a new anonymous type with a single property - that's usually not useful.

    Here's an example which works for your sample data:

    using System;
    using System.Linq;
    using System.Xml.Linq;
    
    public class Test
    {
        static void Main()
        {
            var doc = XDocument.Load("test.xml");
            XNamespace ns = "http://www.sitemaps.org/schemas/sitemap/0.9";
            var max = doc.Root
                .Elements(ns + "url")
                .Max(url => (DateTime) url.Element(ns + "lastmod"));
            Console.WriteLine(max);
        }
    }
    

    Alternatively, if there will never be any other lastmod elements, you could just use Descendants on the document itself:

    var max = doc.Descendants(ns + "lastmod").Max(x => (DateTime) x);