代码之家  ›  专栏  ›  技术社区  ›  CraftyFella

使用xmlserializer序列化datatype=“time”字段

  •  5
  • CraftyFella  · 技术社区  · 15 年前

    我在使用XmlSerializer序列化日期时间字段时得到了一个奇怪的结果。

    我有以下课程:

    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>
    

    任何方法都可以让“the time”元素包含一个看起来更像这样的时间:

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

    …那正是我所期待的?

    谢谢

    戴夫

    4 回复  |  直到 15 年前
        1
  •  1
  •   Community CDub    8 年前
        2
  •  2
  •   Nick    15 年前

    我自己也有不同的问题…但是,我试图序列化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 .

        3
  •  1
  •   João Angelo    15 年前

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

    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>
    
        4
  •  1
  •   Timores    15 年前

    我同意其他答案(当他们突然出现时我没有写完)。它看起来不可能,以一种直接的方式。 通过使用reflector查看源代码,可以发现时间值最终被转换为带有system.xml.xmlconvert.toString的字符串,其硬编码格式为:

    hh:mm:ss.fffffzzzz时

    所以有两个属性,真正的属性是[xmlignore]和一个你自己构建的字符串是一个很好的方法。