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.


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

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.


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

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

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);
        }
    }
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.