Convertir un objet en chaîne XML

89

J'ai une classe nommée que WebserviceTypej'ai obtenue de l'outil xsd.exe à partir d'un fichier XSD.

Maintenant, je veux désérialiser une instance d'un WebServiceTypeobjet en une chaîne. Comment puis-je faire ceci?

L' MethodCheckTypeobjet a comme paramètres un WebServiceTypetableau.

Mon premier essai était comme je l'avais sérialisé: avec a XmlSerializeret a StringWriter(pendant la sérialisation, j'ai utilisé a StringReader).

C'est la méthode dans laquelle je sérialise l' WebServiceTypeobjet:

XmlSerializer serializer = new XmlSerializer(typeof(MethodCheckType));
        MethodCheckType output = null;
        StringReader reader = null;

        // catch global exception, logg it and throw it
        try
        {
            reader = new StringReader(path);
            output = (MethodCheckType)serializer.Deserialize(reader);
        }
        catch (Exception)
        {
            throw;
        }
        finally
        {
            reader.Dispose();
        }

        return output.WebService;

Éditer:

Peut-être pourrais-je le dire en des termes différents: j'ai une instance de cet MethodCheckTypeobjet et d'autre part j'ai le document XML à partir duquel j'ai sérialisé cet objet. Maintenant, je veux convertir cette instance en un document XML sous la forme d'une chaîne. Après cela, je dois prouver si les deux chaînes (des documents XML) sont identiques. C'est ce que je dois faire, car je fais des tests unitaires de la première méthode dans laquelle je lis un document XML dans un StringReaderet le sérialise en un MethodCheckTypeobjet.

FluepkeSchaeng
la source
2
Quelle erreur obtenez-vous? Et vous pouvez confondre les termes: la sérialisation (dans le monde XML) consiste à convertir un objet en XML ; la désérialisation consiste à convertir du XML en objet . Voulez-vous désérialiser un objet d' une chaîne XML?
carlosfigueira

Réponses:

190

Voici la méthode de conversion pour les deux manières. this = instance de votre classe

public string ToXML()
    {
        using(var stringwriter = new System.IO.StringWriter())
        { 
            var serializer = new XmlSerializer(this.GetType());
            serializer.Serialize(stringwriter, this);
            return stringwriter.ToString();
        }
    }

 public static YourClass LoadFromXMLString(string xmlText)
    {
        using(var stringReader = new System.IO.StringReader(xmlText))
        {
            var serializer = new XmlSerializer(typeof(YourClass ));
            return serializer.Deserialize(stringReader) as YourClass ;
        }
    }
Tomas Grosup
la source
14
Vous devez utiliser un usingmodèle ou une Disposeméthode d' appel pour libérer correctement les ressources.
Ivan Kochurkin
Vous devez vous assurer que pour toutes les versions de CLR que le code non managé n'est pas utilisé.
AlphaOmega
3
Pourquoi? Parce que vous devez éliminer tout ce qui est gourmand en ressources (non géré et géré ). Le simple fait que le ramasse-miettes nettoiera pour vous (éventuellement) ne signifie pas que vous devriez rendre son travail indûment difficile. Nettoyez au fur et à mesure et votre code sera plus efficace. Plus d'informations sur les raisons pour lesquelles l'élimination explicite est une bonne idée ici
Liam
1
juste pour plus de clarté. vous parlez de supprimer StringWriter et StringReader (car XmlSerializer n'a pas de méthode Dispose)
symbiont
la fin de la fonction ne libère-t-elle pas les ressources aussi efficacement que using? @KvanTTT?
Mark Entingh
77

Je me rends compte que c'est un article très ancien, mais après avoir examiné la réponse de LB, j'ai réfléchi à la façon dont je pourrais améliorer la réponse acceptée et la rendre générique pour ma propre application. Voici ce que j'ai trouvé:

public static string Serialize<T>(T dataToSerialize)
{
    try
    {
        var stringwriter = new System.IO.StringWriter();
        var serializer = new XmlSerializer(typeof(T));
        serializer.Serialize(stringwriter, dataToSerialize);
        return stringwriter.ToString();
    }
    catch
    {
        throw;
    }
}

public static T Deserialize<T>(string xmlText)
{
    try
    {
        var stringReader = new System.IO.StringReader(xmlText);
        var serializer = new XmlSerializer(typeof(T));
        return (T)serializer.Deserialize(stringReader);
    }
    catch
    {
        throw;
    }
}

Ces méthodes peuvent désormais être placées dans une classe d'assistance statique, ce qui signifie qu'aucune duplication de code vers chaque classe qui doit être sérialisée.

William Smith
la source
10
Sur la méthode «Serialize», utilisez dataToSerialize.GetType () au lieu de typeof (T). À première vue, cela semble sûr d'utiliser T comme type, mais si l'objet "dataToSerialize" a été converti en un type parent (ChildClass cast en BaseClass), il générera une erreur. Et vérifiez d'abord la valeur null.
Paul Easter
1
À quoi sert d'attraper juste pour relancer sans rien faire d'autre?
écraser le
Excellente question; Je n'essayais pas de développer une image complète ici juste le cadre de la fonctionnalité, et je ne voulais certainement pas donner un exemple qui avale l'exception. Cela semblait être une bonne alternative générique à l'époque. N'hésitez pas à suggérer des améliorations!
William Smith
Bonne solution réutilisable.
Nitesh Saxena
21
    public static string Serialize(object dataToSerialize)
    {
        if(dataToSerialize==null) return null;

        using (StringWriter stringwriter = new System.IO.StringWriter())
        {
            var serializer = new XmlSerializer(dataToSerialize.GetType());
            serializer.Serialize(stringwriter, dataToSerialize);
            return stringwriter.ToString();
        }
    }

    public static T Deserialize<T>(string xmlText)
    {
        if(String.IsNullOrWhiteSpace(xmlText)) return default(T);

        using (StringReader stringReader = new System.IO.StringReader(xmlText))
        {
            var serializer = new XmlSerializer(typeof(T));
            return (T)serializer.Deserialize(stringReader);
        }
    }
Elanchezhian Narayanasamy
la source
1
Serialize a besoin de génériques. L'objet suffit. if (dataToSerialize == null) return null; ... var serializer = new XmlSerializer (dataToSerialize.GetType ()); ...
AlphaOmega
0

C'est ma solution, pour tout objet de liste, vous pouvez utiliser ce code pour convertir en mise en page XML. KeyFather est votre balise principale et KeySon est le point de départ de votre Forech.

public string BuildXml<T>(ICollection<T> anyObject, string keyFather, string keySon)
    {
        var settings = new XmlWriterSettings
        {
            Indent = true
        };
        PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T));
        StringBuilder builder = new StringBuilder();
        using (XmlWriter writer = XmlWriter.Create(builder, settings))
        {
            writer.WriteStartDocument();
            writer.WriteStartElement(keyFather);
            foreach (var objeto in anyObject)
            {
                writer.WriteStartElement(keySon);
                foreach (PropertyDescriptor item in props)
                {
                    writer.WriteStartElement(item.DisplayName);
                    writer.WriteString(props[item.DisplayName].GetValue(objeto).ToString());
                    writer.WriteEndElement();
                }
                writer.WriteEndElement();
            }
            writer.WriteFullEndElement();
            writer.WriteEndDocument();
            writer.Flush();
            return builder.ToString();
        }
    }
Fred Peixoto
la source
0
 public static class XMLHelper
    {
        /// <summary>
        /// Usage: var xmlString = XMLHelper.Serialize<MyObject>(value);
        /// </summary>
        /// <typeparam name="T">Kiểu dữ liệu</typeparam>
        /// <param name="value">giá trị</param>
        /// <param name="omitXmlDeclaration">bỏ qua declare</param>
        /// <param name="removeEncodingDeclaration">xóa encode declare</param>
        /// <returns>xml string</returns>
        public static string Serialize<T>(T value, bool omitXmlDeclaration = false, bool omitEncodingDeclaration = true)
        {
            if (value == null)
            {
                return string.Empty;
            }
            try
            {
                var xmlWriterSettings = new XmlWriterSettings
                {
                    Indent = true,
                    OmitXmlDeclaration = omitXmlDeclaration, //true: remove <?xml version="1.0" encoding="utf-8"?>
                    Encoding = Encoding.UTF8,
                    NewLineChars = "", // remove \r\n
                };

                var xmlserializer = new XmlSerializer(typeof(T));

                using (var memoryStream = new MemoryStream())
                {
                    using (var xmlWriter = XmlWriter.Create(memoryStream, xmlWriterSettings))
                    {
                        xmlserializer.Serialize(xmlWriter, value);
                        //return stringWriter.ToString();
                    }

                    memoryStream.Position = 0;
                    using (var sr = new StreamReader(memoryStream))
                    {
                        var pureResult = sr.ReadToEnd();
                        var resultAfterOmitEncoding = ReplaceFirst(pureResult, " encoding=\"utf-8\"", "");
                        if (omitEncodingDeclaration)
                            return resultAfterOmitEncoding;
                        return pureResult;
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception("XMLSerialize error: ", ex);
            }
        }

        private static string ReplaceFirst(string text, string search, string replace)
        {
            int pos = text.IndexOf(search);

            if (pos < 0)
            {
                return text;
            }

            return text.Substring(0, pos) + replace + text.Substring(pos + search.Length);
        }
    }
O Thạnh Ldt
la source