views:

636

answers:

3

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!

+4  A: 

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
    }
}
Marc Gravell
+1 Thanks! If that's the problem, then I can probably include an XML comment stating precisely that. I don't imagine these values will change often (if ever). Is there a built-in mechanism in .NET for deserializing XML Element values as DateTime objects without using the format you've provided (i.e. maybe a converter class that I supply or something)?
Pwninstein
Since I'm only interested in times (not dates), I'm using xsd:time now. Valid times are shown at the bottom of this page: http://books.xmlschemata.org/relaxng/ch19-77311.html , and can deserialize as .NET DateTime objects. The example you provided was helpful. Thanks!
Pwninstein
A: 

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;

monksy
+1  A: 

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();
        }
    }
Thomas Levesque