Configuring XmlSerializer to reproduce XDocument.Save format

Clean-up job in a recent project that uses XML to store certain data. What I found:

  • an XSD describing the XML schema
  • C# proxy classes previously generated by the VS xsd.exe tool
  • the actual XML files
  • all of them not always in sync

The code reading and writing the XML files used LinqToXml to query the files and manually instantiate the XSD-generated classes.

Since the purpose of the proxy classes is to simplify read, write and query operations on statically typed classes, I replaced the Xml.Linq with compile-time type-safe object operations.

In order to verify that my changes did not corrupt the file or change any of the data, I needed to compare the original .xml files and the ones generated by XmlSerializer. I noticed differences between the two sets caused by the classes that wrote the files:

  • XDocument.Root.Save does not generate namespace declarations, and writes a <element></element> closing tag for empty data.
  • XmlSerializer does not write an explicit closing tag but uses the <element /> notation, and generates some namespace declarations in the <?xml> header.

I found the first hints of dealing with the closing tag here and here by implementing an XmlTextWriter, and the final code looks like this:

class MyXmlTextWriter : XmlTextWriter
{
  public MyXmlTextWriter(Stream w)
    : base(w, Encoding.UTF8)
  {
    Indentation = 2;
    IndentChar = ' ';
    Formatting = System.Xml.Formatting.Indented;
  }

  public override void WriteEndElement()
  {
    if (this.WriteState == System.Xml.WriteState.Element)
      Formatting = System.Xml.Formatting.None;
    base.WriteFullEndElement();
    Formatting = System.Xml.Formatting.Indented;
  }
}

To omit the namespace declarations, one needs to provide an XmlSerializerNamespaces object for the XmlSerializer:

XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add(string.Empty, string.Empty);
ns.Add(string.Empty, "http://www.w3.org/2001/XMLSchema-instance");
ns.Add(string.Empty, "http://www.w3.org/2001/XMLSchema");

using (var fs = new FileStream(filename, FileMode.Create, FileAccess.Write))
  serializer.Serialize(new MyXmlTextWriter(fs), app, ns);

1 thought on “Configuring XmlSerializer to reproduce XDocument.Save format

  1. Pingback: XML Access Modes, Object Models, and Serialization in .Net « devioblog

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.