44 votes

Comment empêcher XmlSerializer de tuer les NewLines dans les chaînes de caractères ?

Supposons que j'ai une classe simple avec un seul membre, une chaîne.

public class Abc
{
    private String text;

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

Maintenant, lorsque je le sérialise puis le désérialise avec le XmlSerializer douteux, tout texte contenant des nouvelles lignes (' \r\n ' ou Environment.NewLine) sont transformés en ' \n '.

Comment puis-je conserver les nouvelles lignes ?

69voto

Lachlan Roche Points 16456

Ce n'est pas le XmlSerializer mais le XmlWriter qui supprime votre CR. Pour le conserver, nous devons faire en sorte que le rédacteur convertisse le CR en son entité de caractère. 
 .

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

C'est exactement la même chose avec DataContractSerializer :

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

Pourquoi devons-nous faire cela ?

En effet, les analyseurs XML conformes doivent, avant l'analyse, traduire CRLF et tout CR non suivi d'un LF en un seul LF. Ce comportement est défini dans la norme Traitement des fins de ligne de la spécification XML 1.0.

Comme cela se produit avant l'analyse syntaxique, vous devez encoder CR comme son entité de caractère si vous voulez que CR existe dans le document.

2voto

user2757577 Points 1
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());
        }
    }

}

1voto

user2757577 Points 1

Public class BinarySerialize où T : new() { public static string Serialize(T options, 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;

        }
    }

0voto

user2757577 Points 1

Utilisez ce code :

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

0voto

Mark Paulsen Points 1

Belle solution, Lachlan Roche !

La fonction ci-dessous (en VB.NET) utilise une fonction StringWriter pour retourner une chaîne de caractères, plutôt que d'écrire le résultat dans un fichier à l'aide d'une commande de type XmlWriter .

  ''' <summary>
  ''' Exports the object data to an XML formatted string.
  ''' Maintains CR characters after deserialization.
  ''' The object must be serializable to work.
  ''' </summary>

  Public Function ExportObjectXml(ByVal obj As Object) As String
    If obj Is Nothing Then
      Return String.Empty
    End If

    Dim serializer As New XmlSerializer(obj.GetType)
    Dim settings As New XmlWriterSettings With {.NewLineHandling = NewLineHandling.Entitize}

    Using output As New StringWriter
      Using writer As XmlWriter = XmlWriter.Create(output, settings)
        serializer.Serialize(writer, obj)
        Return output.ToString
      End Using
    End Using
  End Function

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X