Serializing a DataType="time" field using XmlSerializer

14,222

Solution 1

take a look at this question Serializing DateTime to time without milliseconds and gmt

Solution 2

I've had different issues with this myself... however I was attempting to serialize a TimeSpan object. The solution was to have two properties, one that held the TimeSpan, and one that was a string representation of the TimeSpan which got Serialized. Here was the pattern:

[XmlIgnore]
public TimeSpan ScheduledTime
{
    get;
    set;
}

[XmlElement("ScheduledTime", DataType="duration")]
public string XmlScheduledTime
{
    get { return XmlConvert.ToString(ScheduledTime); }
    set { ScheduledTime = XmlConvert.ToTimeSpan(value); }
}

However, with this code, the time is printed out in the following format:

<ScheduledTime>PT23H30M</ScheduledTime>

The W3C definition of duration is here which explains it.

Solution 3

Expanding on the comment I made on one of the others answers.

public class RecordExample : IXmlSerializable
{
    public DateTime TheTime { get; set; }
    public DateTime TheDate { get; set; }

    public XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(XmlReader reader)
    {
        // TODO : Deserialization logic here
    }

    public void WriteXml(XmlWriter writer)
    {
        writer.WriteElementString(
            "date", 
            this.TheDate.ToString("yyyy-MM-dd"));

        writer.WriteElementString(
            "time", 
            this.TheTime.ToString("hh:mm:ss.fK"));
    }
}

Serializing like this:

var rc = new RecordExample()
{
    TheDate = DateTime.Today,
    TheTime = DateTime.UtcNow
};

var serializer = new XmlSerializer(typeof(RecordExample));

var ms = new MemoryStream();

serializer.Serialize(ms, rc);

ms.Seek(0, SeekOrigin.Begin);

Console.WriteLine(new StreamReader(ms).ReadToEnd());

Output example:

<?xml version="1.0"?>
<RecordExample>
  <date>2010-03-08</date>
  <time>04:26:16.1Z</time>
</RecordExample>

Solution 4

I concur with the other answers (I was not done writing when they popped up). it does not look like it is possible, in a direct way. A look at the source with Reflector shows that a time value ends up being converted to a string with the System.Xml.XmlConvert.ToString, that has a hard-coded format of:

HH:mm:ss.fffffffzzzzzz

So having two properties, the real one being [XmlIgnore] and a string that you build yourself is a good way to go.

Share:
14,222
CraftyFella
Author by

CraftyFella

c# Programmer who dreams of being a professional snowboarder.

Updated on June 04, 2022

Comments

  • CraftyFella
    CraftyFella almost 2 years

    I'm getting an odd result when serializing a DateTime field using XmlSerializer.

    I have the following class:

    public class RecordExample
    {
        [XmlElement("TheTime", DataType = "time")]
        public DateTime TheTime { get; set; }
    
        [XmlElement("TheDate", DataType = "date")]
        public DateTime TheDate { get; set; }
    
        public static bool Serialize(
            Stream stream, object obj, Type objType, Encoding encoding)
        {
            try
            {
                var settings = new XmlWriterSettings { Encoding = encoding };
    
                using (var writer = XmlWriter.Create(stream, settings))
                {
                    var xmlSerializer = new XmlSerializer(objType);
                    if (writer != null) xmlSerializer.Serialize(writer, obj);
                }
    
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
    }
    

    When i call the use the XmlSerializer with the following testing code:

    var obj = new RecordExample 
    { 
        TheDate = DateTime.Now.Date, 
        TheTime = new DateTime(0001, 1, 1, 12, 00, 00) 
    };
    
    var ms = new MemoryStream();
    
    RecordExample.Serialize(ms, obj, typeof(RecordExample), Encoding.UTF8);
    txtSource2.Text = Encoding.UTF8.GetString(ms.ToArray());
    

    I get some strange results, here's the xml that is produced:

    <?xml version="1.0" encoding="utf-8"?>
    <RecordExample 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <TheTime>12:00:00.0000000+00:00</TheTime>
        <TheDate>2010-03-08</TheDate>
    </RecordExample>
    

    Any idea's how i can get the "TheTime" element to contain a time which looks more like this:

    <TheTime>12:00:00.0Z</TheTime>
    

    ...as that's what i was expecting?

    Thanks

    Dave

  • CraftyFella
    CraftyFella about 14 years
    Wooo is that for real. Seems like a dirty hack to me.. There's no nicer way to do this?
  • João Angelo
    João Angelo about 14 years
    @CraftyFella, you can implement IXmlSerializable, but then you need to provide an implementation for all the serialization logic.
  • IordanTanev
    IordanTanev about 14 years
    as far as i know this is the only solution. When i have to do it i do it this with second property.If you find a better solution please let me know.A solution that not involves writing your own XmlSerializer
  • CraftyFella
    CraftyFella about 14 years
    Thanks.. that's a definite option. Also didn't know about the UtcNow.