使用XmlSerializer对DataType =“time”字段进行序列化

问题描述:

使用XmlSerializer序列化DateTime字段时,出现了奇怪的结果。使用XmlSerializer对DataType =“time”字段进行序列化

我有以下类:

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; 
     } 
    } 
} 

当我打电话的使用XmlSerializer以下测试代码:

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()); 

我得到一些奇怪的结果,这里的所产生的XML:

<?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> 

任何想法的如何我可以让“TheTime”元素包含一个时间wh ich看起来更像是这样的:

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

......这就是我所期待的?

感谢

戴夫

+0

[Serializing DateTime to time without milliseconds and gmt](http://*.com/questions/101533/serializing-datetime-to-time-without-milliseconds-and-gmt) – 2011-11-17 13:58:44

+0

Wooo是for真实。看起来像一个肮脏的黑客我没有更好的方法来做到这一点? – CraftyFella 2010-03-08 15:53:28

+1

@CraftyFella,你可以实现'IXmlSerializable',但是你需要为所有的序列化逻辑提供一个实现。 – 2010-03-08 15:56:57

+1

据我所知,这是唯一的解决方案。当我必须这样做时,我会用第二个属性来做到这一点。如果你找到更好的解决方案,请让我知道。一个解决方案,不涉及编写自己的XmlSerializer – IordanTanev 2010-03-08 15:57:34

我有不同的使用问题,我自己...但是我试图序列TimeSpan对象。解决方案是有两个属性,一个保存TimeSpan,另一个是获得序列化的TimeSpan的字符串表示。这里是图案:

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

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

但是,在该代码中,时间被以下面的格式打印出:

<ScheduledTime>PT23H30M</ScheduledTime> 

The W3C definition of duration is here which explains it

扩大我对其他答案之一的评论。

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")); 
    } 
} 

序列化是这样的:

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()); 

输出例如:

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

谢谢..这是一个明确的选择。也不知道UtcNow。 – CraftyFella 2010-03-09 09:53:00

我与其他的答案(我没有写完的时候,他们弹出)同意。它看起来不可能,直接的方式。 使用Reflector查看源代码显示时间值最终转换为具有以下硬编码格式的System.Xml.XmlConvert.ToString的字符串:

HH:mm:ss.fffffffzzzzzz

因此,有两个属性,真正的是[XmlIgnore]和你自己构建的字符串是一个好方法。

+0

非常彻底的谢谢检查出来.. – CraftyFella 2010-03-09 09:50:12