XmlSerializer without xml declaration or namespaces

At work we use .Net XML Serialization pretty extensively.  The simplest case of XmlSerializer.Serialize produces some ugly XML.  I mean, XML with a declaration, some useless w3c xmlns attributes and headaches if you don't intend for your object to be an entire well formed XML doc by itself after serialization.  Today I did a little forum searching and pieced together a lot of disparate advice to come to this conclusion.  This is what I intend for this blog to be: code complete examples of solutions to fairly obscure problems that have poor forum presence.
 
The way we are all taught to use XML Serialization follows.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace ICanHasAnswer
    [XmlRoot("MyObject")]
    public class MyObject
    {
        [XmlElement("x")]
        public int X;
        [XmlElement("y")]
        public int Y;
        [XmlElement("loc")]
        public string Location;

        //Method that serializes the simpl way.
        public static string Serialize(MyObject obj)
        {
            XmlSerializer xs = null;
            StringWriter sw = null;
            String outString = String.Empty;
            try
            {
                StringBuilder sb = new StringBuilder();
                xs = new XmlSerializer(typeof(MyObject));
                sw = new StringWriter(sb);

                xs.Serialize(sw, obj);

                sw.Flush();

                outString = sb.ToString();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
            finally
            {
                if (sw != null)
                {
                    sw.Close();
                    sw.Dispose();
                }
            }
            return outString;
        }
    }   
}
This produces some ungainly, ugly XML, especially if this chunk needs to be included into a larger XML document.
<?xml version="1.0" encoding="utf-16"?>
<MyObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <x>72</x>
  <y>78</y>
  <loc>Somewhere in Indiana.</loc>
</MyObject>
You have to somehow manually remove the <?xml?> declaration, and really the two xmlns attributes in <MyObject> are so much fluff for most programming purposes.  Also the W3C gets bombarded with MILLIONS of hits  a day that aren't really necessary due to those two little xmlns attributes.
At my job some programmer long ago decided to remove the <?xml?> declaration by loading that returned string into an XmlDocument, removing the firstChild and then returning the rest of the XmlDocuments InnerXml.  This is a horrible way to do things. 
Here is a better way
public static string SerializeClean(MyObject obj)
{
    XmlSerializer xs = null;

    //These are the objects that will free us from extraneous markup.
    XmlWriterSettings settings = null;
    XmlSerializerNamespaces ns = null;

    //We use a XmlWriter instead of a StringWriter.
    XmlWriter xw = null;

    String outString = String.Empty;

    try
    {
        //To get rid of the xml declaration we create an 
        //XmlWriterSettings object and tell it to OmitXmlDeclaration.
        settings = new XmlWriterSettings();
        settings.OmitXmlDeclaration = true;

        //To get rid of the default namespaces we create a new
        //set of namespaces with one empty entry.
        ns = new XmlSerializerNamespaces();
        ns.Add("", "");

        StringBuilder sb = new StringBuilder();

        xs = new XmlSerializer(typeof(MyObject));

        //We create a new XmlWriter with the previously created settings 
        //(to OmitXmlDeclaration).
        xw = XmlWriter.Create(sb, settings);

        //We call xs.Serialize and pass in our custom 
        //XmlSerializerNamespaces object.
        xs.Serialize(xw, obj, ns);

        xw.Flush();

        outString = sb.ToString();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }
    finally
    {
        if (xw != null)
        {
            xw.Close();
        }
    }
    return outString;
}
This produces the following clean XML.
<MyObject>
    <x>72</x>
    <y>78</y>
    <loc>Somewhere in Indiana.</loc>
</MyObject>

Comments

Unknown said…
This comment has been removed by a blog administrator.
Unknown said…
I just found this out today. Thanks a lot for the tutorial. It really helped me