Converte un oggetto in una stringa XML


88

Ho una classe denominata che WebserviceTypeho ottenuto dallo strumento xsd.exe da un file XSD.

Ora voglio deserializzare un'istanza di un WebServiceTypeoggetto in una stringa. Come posso fare questo?

L' MethodCheckTypeoggetto ha come parametri un WebServiceTypearray.

Il mio primo tentativo è stato come se l'avessi serializzato: con a XmlSerializere a StringWriter(durante la serializzazione ho usato a StringReader).

Questo è il metodo in cui serializzo l' WebServiceTypeoggetto:

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;

Modificare:

Forse potrei dirlo con parole diverse: ho un'istanza di questo MethodCheckTypeoggetto e d'altra parte ho il documento XML da cui ho serializzato questo oggetto. Ora voglio convertire questa istanza in un documento XML sotto forma di stringa. Dopodiché devo provare se entrambe le stringhe (dei documenti XML) sono uguali. Questo devo fare, perché eseguo test unitari del primo metodo in cui leggo un documento XML in a StringReadere lo serializzo in un MethodCheckTypeoggetto.


2
Che errore ricevi? E potresti confondere i termini: serializzazione (nel mondo XML) è la conversione da un oggetto in XML ; la deserializzazione è la conversione da XML in un oggetto . Deserializzare un oggetto da una stringa XML?
carlosfigueira

Risposte:


189

Ecco il metodo di conversione per entrambi i modi. this = istanza della tua 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
È necessario utilizzare usingpattern o Disposemetodo di chiamata per il corretto rilascio delle risorse.
Ivan Kochurkin

È necessario assicurarsi che per tutte le versioni CLR non venga utilizzato codice non gestito.
AlphaOmega

3
Perché? Perché dovresti eliminare tutto ciò che richiede molte risorse (non gestito e gestito ). Solo perché il garbage collector pulirà per te (alla fine) non significa che dovresti rendere il suo lavoro eccessivamente difficile. Pulisci man mano che procedi e il tuo codice sarà più efficiente. Maggiori informazioni sul perché l'eliminazione esplicita è una buona idea qui
Liam

1
solo per chiarezza. voi ragazzi state parlando di eliminare StringWriter e StringReader (dato che XmlSerializer non ha un metodo Dispose)
simbionte

la fine della funzione non rilascia risorse altrettanto efficientemente come using? @KvanTTT?
Mark Entingh

77

Mi rendo conto che questo è un post molto vecchio, ma dopo aver esaminato la risposta di LB ho pensato a come migliorare la risposta accettata e renderla generica per la mia applicazione. Ecco cosa mi è venuto in mente:

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

Questi metodi possono ora essere inseriti in una classe helper statica, il che significa nessuna duplicazione del codice per ogni classe che deve essere serializzata.


10
Sul metodo "Serialize", utilizzare dataToSerialize.GetType () invece di typeof (T). A prima vista sembra sicuro usare T come tipo, ma se l'oggetto "dataToSerialize" è stato sottoposto a cast a un tipo genitore (ChildClass cast a BaseClass) genererà un errore. E controlla prima se è nullo.
Paul Easter

1
Qual è il punto di catturare solo per rilanciare senza fare nient'altro?
schiacciare il

Ottima domanda; Non stavo cercando di sviluppare un'immagine completa qui solo il framework per la funzionalità, e sicuramente non volevo fare un esempio che inghiottisse l'eccezione. All'epoca sembrava una buona alternativa generica. Sentiti libero di suggerire miglioramenti!
William Smith

Buona soluzione riutilizzabile.
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 ha bisogno di generici. L'oggetto è sufficiente. if (dataToSerialize == null) restituisce null; ... var serializer = new XmlSerializer (dataToSerialize.GetType ()); ...
AlphaOmega

0

Questa è la mia soluzione, per qualsiasi oggetto elenco è possibile utilizzare questo codice per convertire in layout xml. KeyFather è il tuo tag principale e KeySon è dove inizia il tuo 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);
        }
    }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.