Convertir un objeto en una cadena XML


88

Tengo una clase llamada WebserviceTypeObtuve de la herramienta xsd.exe de un archivo XSD.

Ahora quiero deserializar una instancia de un WebServiceTypeobjeto en una cadena. ¿Cómo puedo hacer esto?

El MethodCheckTypeobjeto tiene como parámetros una WebServiceTypematriz.

Mi primer intento fue como si lo serializara: con a XmlSerializery a StringWriter(mientras serializaba usé a StringReader).

Este es el método en el que serializo el WebServiceTypeobjeto:

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;

Editar:

Tal vez podría decirlo en otras palabras: tengo una instancia de este MethodCheckTypeobjeto y, por otro lado, tengo el documento XML desde el cual serialicé este objeto. Ahora quiero convertir esta instancia en un documento XML en forma de cadena. Después de esto, tengo que probar si ambas cadenas (de documentos XML) son iguales. Tengo que hacer esto, porque hago pruebas unitarias del primer método en el que leo un documento XML en un StringReadery lo serializo en un MethodCheckTypeobjeto.


2
¿Qué error obtienes? Y puede confundir los términos: serialización (en el mundo XML) es convertir de un objeto a XML ; la deserialización es la conversión de XML en un objeto . ¿Desea deserializar un objeto de una cadena XML?
carlosfigueira

Respuestas:


189

Aquí hay un método de conversión para ambas formas. this = instancia de tu clase

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
Debe utilizar un usingpatrón o un Disposemétodo de llamada para la correcta liberación de recursos.
Ivan Kochurkin

Debe asegurarse de que en todas las versiones de CLR no se utilice código no administrado.
AlphaOmega

3
¿Por qué? Porque debe deshacerse de todo lo que consume muchos recursos (no administrado y administrado ). El hecho de que el recolector de basura se encargue de limpiar por usted (eventualmente) no significa que deba hacer su trabajo excesivamente difícil. Limpia a medida que avanzas y tu código será más eficiente. Más información sobre por qué la eliminación explícita es una buena idea aquí
Liam

1
solo por claridad. ustedes están hablando de deshacerse de StringWriter y StringReader (ya que XmlSerializer no tiene un método Dispose)
symbiont

¿El final de la función no libera recursos tan eficientemente como using? @KvanTTT?
Mark Entingh

77

Me doy cuenta de que esta es una publicación muy antigua, pero después de ver la respuesta de LB, pensé en cómo podría mejorar la respuesta aceptada y hacerla genérica para mi propia aplicación. Esto es lo que se me ocurrió:

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

Estos métodos ahora se pueden colocar en una clase auxiliar estática, lo que significa que no hay duplicación de código en cada clase que necesita ser serializada.


10
En el método "Serialize", use dataToSerialize.GetType () en lugar de typeof (T). A primera vista, parece seguro usar T como tipo, pero si el objeto "dataToSerialize" se ha convertido en un tipo principal (ChildClass convertido en BaseClass), arrojará un error. Y verifique si es nulo primero, por supuesto.
Paul Easter

1
¿Qué sentido tiene atrapar para volver a lanzar sin hacer nada más?
aplasta

Gran pregunta; No estaba tratando de desarrollar una imagen completa aquí, solo el marco para la funcionalidad, y definitivamente no quería dar un ejemplo que se trague la excepción. Parecía una buena alternativa genérica en ese momento. ¡No dude en sugerir mejoras!
William Smith

Buena solución reutilizable.
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 necesita genéricos. El objeto es suficiente. if (dataToSerialize == null) return null; ... var serializer = new XmlSerializer (dataToSerialize.GetType ()); ...
AlphaOmega

0

Esta es mi solución, para cualquier objeto de lista, puede usar este código para convertirlo a formato xml. KeyFather es su etiqueta principal y KeySon es donde comienza su 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);
        }
    }
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.