Mark Carpenter
Mark Carpenter

Reputation: 17775

How can I deserialize a list of DateTime objects?

If I have the following XML segment:

<Times>
  <Time>1/1/1900 12:00 AM</Time>
  <Time>1/1/1900 6:00 AM</Time>
</Times>

What should the corresponding property look like that, when deserialization occurs, accepts the above XML into a list of DateTime objects?

This works to deserialize the XML segment to a list of string objects:

[XmlArray("Times")]
[XmlArrayItem("Time", typeof(string))]
public List<string> Times { get; set; }

But when I use DateTime as the type instead of string (for both the List type and XmlArrayItem type), I get the following error:

The string '1/1/1900 12:00 AM' is not a valid AllXsd value.

Thanks!

Upvotes: 2

Views: 6170

Answers (3)

Thomas Levesque
Thomas Levesque

Reputation: 292405

The easiest way is to create a new property which is serialized instead of the Times property, and handles the formatting :

    [XmlIgnore]
    public IList<DateTime> Times { get; set; }

    [XmlArray("Times")]
    [XmlArrayItem("Time")]
    public string[] TimesFormatted
    {
        get
        {
            if (this.Times != null)
                return this.Times.Select((dt) => dt.ToString("MM/dd/yyyy hh:mm tt", CultureInfo.InvariantCulture)).ToArray();
            else
                return null;
        }
        set
        {
            if (value == null)
                this.Times = new List<DateTime>();
            else
                this.Times = value.Select((s) => DateTime.ParseExact(s, "MM/dd/yyyy hh:mm tt", CultureInfo.InvariantCulture)).ToList();
        }
    }

Upvotes: 3

Marc Gravell
Marc Gravell

Reputation: 1062600

With DateTime, I expect that a large part of the problem is that the format of the xml is wrong; that isn't the xsd standard for dates... can you influence the xml at all? Otherwise, you might have to stick with strings and process it afterwards.

More standard xml would be:

<Times>
  <Time>1900-01-01T00:00:00</Time>
  <Time>1900-01-01T06:00:00</Time>
</Times>

For example:

using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
public class Data
{

    [XmlArray("Times")]
    [XmlArrayItem("Time")]
    public List<DateTime> Times { get; set; }

    static void Main()
    {
        XmlReader xr = XmlReader.Create(new StringReader(@"<Data><Times>
  <Time>1900-01-01T00:00:00</Time>
  <Time>1900-01-01T06:00:00</Time>
</Times></Data>"));
        XmlSerializer ser = new XmlSerializer(typeof(Data));
        Data data = (Data) ser.Deserialize(xr);
        // use data
    }
}

Upvotes: 5

monksy
monksy

Reputation: 14234

Take a look at the msdn article: http://msdn.microsoft.com/en-us/library/ms950721.aspx

It suggests that a DateTime object should be marked as such: [System.Xml.Serialization.XmlElementAttribute("publication-date", DataType="date")]
public System.DateTime publicationdate;

Upvotes: 0

Related Questions