2010-02-26 7 views
34

Supongamos que tengo una clase simple con solo un miembro en una cadena.¿Cómo evitar que XmlSerializer mate NewLines en cadenas?

public class Abc 
{ 
    private String text; 

    public String Text 
    { 
     get { return this.text; } 
     set { this.text = value; } 
    } 
} 

Ahora cuando serializar y luego deserializar con el XmlSerializer cuestionable cualquier saltos de línea de texto que contiene ('\ r \ n' o Environment.NewLine) se transforman a '\ n'.

¿Cómo guardo las nuevas líneas?

+0

Usted serializarlo donde? ¿Qué secuencia o escritor de texto? –

+0

Hice una aplicación de demostración para mostrar mi problema: http://c0065612.cdn.cloudfiles.rackspacecloud.com/XmlDeSerTextBox.zip – Thomas

+0

La aplicación muestra dos campos de texto y un botón. Cuando ingresa texto con saltos de línea en el campo de texto superior y presiona "Ok", el XmlSerializer destruye los saltos de línea por usted. – Thomas

Respuesta

52

No es el XmlSerializer sino el XmlWriter que está eliminando su CR. Para retenerlo, debemos hacer que el escritor convierta CR en su entidad de caracteres 
.

XmlWriterSettings ws = new XmlWriterSettings(); 
ws.NewLineHandling = NewLineHandling.Entitize; 

XmlSerializer ser = new XmlSerializer(typeof(Abc)); 
using (XmlWriter wr = XmlWriter.Create("abc.xml", ws)) { 
    ser.Serialize(wr, s); 
} 

Esto es exactamente lo mismo con DataContractSerializer:

var ser = new DataContractSerializer(typeof(Abc)); 
using (XmlWriter wr = XmlWriter.Create("abc.xml", ws)) { 
    ser.Serialize(wr, s); 
} 

¿Por qué tenemos que hacer esto?

Esto se debe a que los analizadores XML compatibles deben, antes del análisis, traducir CRLF y cualquier CR no seguido de una LF en una sola LF. Este comportamiento se define en la sección End-of-Line handling de la especificación XML 1.0.

Como esto sucede antes del análisis, debe codificar CR como su entidad de caracteres si desea que el CR exista en el documento.

+0

¡Sí! Eso funciona. Gracias. – Thomas

+2

Creo que el retorno de carro es no – Juan

+0

@Lachlan Roche Encontré esta solución como una de las únicas respuestas a cómo XML elimina CR de la cadena de texto. Mi problema, sin embargo, es que está sucediendo a través de un servicio web, código que se genera automáticamente para construir el wsdl. Me preguntaba si tenía alguna sugerencia sobre cómo vencer el problema. – htm11h

0

Usar este código:

public static FilterOptions Deserialize(string serializedData) 
{ 
    try 
    { 
     var xmlSerializer = new XmlSerializer(typeof(FilterOptions)); 
     var xmlReader = new XmlTextReader(serializedData,XmlNodeType.Document,null); 
     var collection = (FilterOptions)xmlSerializer.Deserialize(xmlReader); 
     return collection; 
    } 
    catch (Exception) 
    { 


    } 

    return new FilterOptions(); 
} 
+0

Hoy debería usar 'XmlReader' y no' XmlTextReader'. Usted puede lograr lo mismo usando el primero también. Buena respuesta, sin embargo. – nawfal

+0

Bien, ¿podría explicarme qué hace su código? –

+0

@nawfal: ¿podría explicarme cómo hacerlo con XmlReader? –

2
public class SerializeAny<TF> where TF : new() 
{ 
    public static TF Deserialize(string serializedData) 
    { 
     try 
     { 
      var xmlSerializer = new XmlSerializer(typeof(TF)); 
      TF collection; 
      using (var xmlReader = new XmlTextReader(serializedData, XmlNodeType.Document, null)) 
      { 
       collection = (TF)xmlSerializer.Deserialize(xmlReader); 
      } 
      return collection; 
     } 
     catch (Exception) 
     { 


     } 

     return new TF(); 
    } 


    public static TF DeserializeZip(string path) 
    { 
     try 
     { 
      var bytes = File.ReadAllBytes(path); 

      string serializedData = Unzip(bytes); 

      TF collection = Deserialize(serializedData); 


      return collection; 
     } 
     catch (Exception) 
     { 


     } 

     return new TF(); 
    } 

    public static string Serialize(TF options) 
    { 
     var xml = ""; 

     try 
     { 
      var xmlSerializer = new XmlSerializer(typeof(TF)); 
      using (var stringWriter = new StringWriter()) 
      { 
       xmlSerializer.Serialize(stringWriter, options); 
       xml = stringWriter.ToString(); 
      } 
     } 
     catch (Exception ex) 
     { 

      return ex.Message; 
     } 



     return xml; 
    } 

    public static string SerializeZip(TF options, string path) 
    { 
     var xml = ""; 

     try 
     { 
      xml = Serialize(options); 
      var zip = Zip(xml); 
      File.WriteAllBytes(path, zip); 
     } 
     catch (Exception ex) 
     { 

      return ex.Message; 
     } 



     return xml; 
    } 



    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")] 
    internal static String SerializeObject<T>(T obj, Encoding enc) 
    { 
     using (var ms = new MemoryStream()) 
     { 
      var xmlWriterSettings = new System.Xml.XmlWriterSettings() 
      { 
       // If set to true XmlWriter would close MemoryStream automatically and using would then do double dispose 
       // Code analysis does not understand that. That's why there is a suppress message. 
       CloseOutput = false, 
       Encoding = enc, 
       OmitXmlDeclaration = false, 
       Indent = true 
      }; 
      using (var xw = XmlWriter.Create(ms, xmlWriterSettings)) 
      { 
       var s = new XmlSerializer(typeof(T)); 
       s.Serialize(xw, obj); 
      } 

      return enc.GetString(ms.ToArray()); 
     } 
    } 

    private static void CopyTo(Stream src, Stream dest) 
    { 
     byte[] bytes = new byte[4096]; 

     int cnt; 

     while ((cnt = src.Read(bytes, 0, bytes.Length)) != 0) 
     { 
      dest.Write(bytes, 0, cnt); 
     } 
    } 

    private static byte[] Zip(string str) 
    { 
     var bytes = Encoding.UTF8.GetBytes(str); 

     using (var msi = new MemoryStream(bytes)) 
     using (var mso = new MemoryStream()) 
     { 
      using (var gs = new GZipStream(mso, CompressionMode.Compress)) 
      { 
       //msi.CopyTo(gs); 
       CopyTo(msi, gs); 
      } 

      return mso.ToArray(); 
     } 
    } 

    private static string Unzip(byte[] bytes) 
    { 
     using (var msi = new MemoryStream(bytes)) 
     using (var mso = new MemoryStream()) 
     { 
      using (var gs = new GZipStream(msi, CompressionMode.Decompress)) 
      { 
       CopyTo(gs, mso); 
      } 

      return Encoding.UTF8.GetString(mso.ToArray()); 
     } 
    } 

} 
1

BinarySerialize clase pública donde T: new() { pública cadena Serialize estática (opciones T, string path) {

  var xml = ""; 
      try 
      { 
       File.Delete(path); 
      } 
      catch (Exception) 
      { 


      } 

      try 
      { 
       using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.ReadWrite)) 
       { 
        var bf = new BinaryFormatter(); 


        bf.Serialize(fs, options); 
       } 


      } 
      catch (Exception ex) 
      { 

       return ex.Message; 
      } 



      return xml; 





     } 

     public static T Deserialize(string path) 
     { 
      T filteroptions; 
      using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) 
      { 
       var bf = new BinaryFormatter(); 
       filteroptions = (T)bf.Deserialize(fs); 
      } 
      return filteroptions; 

     } 
    } 
Cuestiones relacionadas