115

I have got a class named WebserviceType I got from the tool xsd.exe from an XSD file.

Now I want to deserialize an instance of an WebServiceType object to a string. How can I do this?

The MethodCheckType object has as params a WebServiceType array.

My first try was like I serialized it: with a XmlSerializer and a StringWriter (while serializing I used a StringReader).

This is the method in which I serialize the WebServiceType object:

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;

Edit:

Maybe I could say it in different words: I have got an instance of this MethodCheckType object an on the other hand I have got the XML document from which I serialized this object. Now I want to convert this instance into a XML document in form of a string. After this I have to proof if both strings (of XML documents) are the same. This I have to do, because I make unit tests of the first method in which I read an XML document into a StringReader and serialize it into a MethodCheckType object.

bluish
  • 26,356
  • 27
  • 122
  • 180
FluepkeSchaeng
  • 1,441
  • 2
  • 11
  • 15
  • 2
    What error do you get? And you may be confusing the terms: serialization (in XML world) is converting *from an object into XML*; deserialization is converting *from XML into an object*. Do you wanto to deserialize an object **from** a XML string? – carlosfigueira Jul 12 '12 at 08:13

5 Answers5

236

Here are conversion method for both ways. this = instance of your class

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 ;
        }
    }
weeksdev
  • 4,265
  • 21
  • 36
Tomas Grosup
  • 6,396
  • 3
  • 30
  • 44
  • 15
    You should use `using` pattern or call `Dispose` method for correct resource releasing. – Ivan Kochurkin Nov 23 '13 at 12:01
  • You must be sure for all CLR versions than unmanaged code is not used. – AlphaOmega Apr 23 '14 at 15:10
  • 3
    Why? Because you should Dispose everything that is resource intensive (unmanaged and **managed**). Just becasue the garbage collector will clean up for you (eventually) doesn't mean you should make it's job unduely difficult. Clean up as you go along and your code will be more efficent. [More info on why explicit disposing is a good idea here](http://stackoverflow.com/a/538193/542251) – Liam Jun 22 '16 at 14:20
  • 1
    just for clarity. you guys are talking about disposing StringWriter and StringReader (as XmlSerializer doesn't have a Dispose method) – symbiont Mar 06 '17 at 09:14
  • doesn't the end of the function release resources just as efficiently as `using`? @KvanTTT ? – Mark Entingh Apr 28 '17 at 14:53
90

I realize this is a very old post, but after looking at L.B's response I thought about how I could improve upon the accepted answer and make it generic for my own application. Here's what I came up with:

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

These methods can now be placed in a static helper class, which means no code duplication to every class that needs to be serialized.

William Smith
  • 1,949
  • 4
  • 25
  • 45
  • 10
    On the "Serialize" method, use dataToSerialize.GetType() instead of typeof(T). At first glance this seems safe to use T as the type, but if the "dataToSerialize" object has been cast to a parent type (ChildClass cast to BaseClass) it will throw an error. And check it for null first of course. – Paul Easter Oct 22 '15 at 03:13
  • 2
    What's the point of catching just to rethrow without doing anything else? – crush Feb 20 '18 at 22:10
  • 1
    Great question; I wasn't trying to develop a complete picture here just the framework for the functionality, and I definitely didn't want to give an example that swallows the exception. Seemed like a good, generic alternative at the time. Feel free to suggest improvements! – William Smith Feb 21 '18 at 18:52
  • Good reusable solution. – Nitesh Saxena Nov 30 '18 at 10:54
  • 1
    The try catch block is completely redundant and should be removed from what is otherwise a good example. – Ste Brown Jun 08 '22 at 11:53
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 does need generics. Object is enough. if(dataToSerialize==null) return null; ... var serializer = new XmlSerializer(dataToSerialize.GetType()); ... – AlphaOmega Apr 23 '14 at 15:21
1
 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
  • 1,103
  • 10
  • 11
0

This is my solution, for any list object you can use this code for convert to xml layout. KeyFather is your principal tag and KeySon is where start your 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();
        }
    }