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