2010-03-08 10 views
5

Obtengo un resultado extraño al serializar un campo DateTime usando XmlSerializer.Serializando un campo DataType = "time" usando XmlSerializer

tengo la clase siguiente:

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

cuando llamo el uso XmlSerializer con el siguiente código de prueba:

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

consigo algunos resultados extraños, aquí está el código XML que se produce:

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

Cualquier idea es cómo puedo conseguir que el elemento "TheTime" contenga un tiempo wh ich se parece más a esto:

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

... como eso era lo que esperaba?

Gracias

de Dave

+0

posible duplicado de [Serializing DateTime a tiempo sin milisegundos y gmt] (http://stackoverflow.com/questions/101533/serializing-datetime-to-time-without-milliseconds-and-gmt) –

Respuesta

1
+0

Wooo es eso para real. Parece un sucio truco para mí ... ¿No hay una forma más agradable de hacer esto? – CraftyFella

+1

@CraftyFella, puede implementar 'IXmlSerializable', pero luego debe proporcionar una implementación para toda la lógica de serialización. –

+1

por lo que sé esta es la única solución. Cuando tengo que hacerlo, lo hago con la segunda propiedad. Si encuentra una mejor solución, por favor, hágamelo saber. Una solución que no implica escribir su propio XmlSerializer – IordanTanev

2

He tenido problemas diferentes con este mismo ... sin embargo yo estaba tratando de serializar un objeto TimeSpan. La solución era tener dos propiedades, una que tuviera TimeSpan, y otra que fuera una representación de cadena del TimeSpan que se serializó. Aquí estaba el patrón:

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

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

Sin embargo, con este código, el tiempo se imprime en el siguiente formato:

<ScheduledTime>PT23H30M</ScheduledTime> 

The W3C definition of duration is here which explains it.

1

Ampliando el comentario que hice en una de las otras respuestas.

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

de números de serie de esta manera:

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

Ejemplo de salida:

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

Gracias ... esa es una opción definitiva. También no sabía sobre el UtcNow. – CraftyFella

1

Estoy de acuerdo con las otras respuestas (no había terminado de escribir cuando aparecieron). no parece que sea posible, de manera directa. Un vistazo a la fuente con Reflector muestra que un valor de tiempo termina siendo convertido a una cadena con el System.Xml.XmlConvert.ToString, que tiene un formato no modificable de:

HH: mm: ss.fffffffzzzzzz

Así que tener dos propiedades, la real siendo [XmlIgnore] y una cadena que construyas tú mismo es una buena forma de hacerlo.

+0

Muchas gracias por verificar eso ... – CraftyFella