web-dev-qa-db-fra.com

Comment empêcher XmlSerializer de tuer NewLines in Strings?

Supposons que j'ai une classe simple avec un seul membre par 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 et que je le désérialise avec le XmlSerializer, un texte douteux, tout texte contenant des nouvelles lignes ('\ r\n' ou Environment.NewLine) est transformé en '\ n'.

Comment conserver les nouvelles lignes?

37
Thomas

Ce n'est pas XmlSerializer mais XmlWriter qui supprime votre CR. Pour le conserver, le rédacteur doit convertir 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 avons-nous besoin de faire cela?

En effet, avant d'analyser, les analyseurs XML conformes doivent traduire CRLF et tous les CR non suivis d'un LF en un seul LF. Ce comportement est défini dans la section Traitement en fin de ligne de la spécification XML 1.0.

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

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

}
2
user2757577

classe publique BinarySerialize où T: new () { chaîne publique statique Serialize (options T, chemin de la chaîne) {

            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;

        }
    }
1
user2757577

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