XmlSerializer Namespaces

If you worked with NHibernate mappings, you know very well about the namespace declarations on the root element: <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">. We generate these mappings programmatically, and we naturally wondered how to remove the default xmlns:xsd and xmlns:xsi declarations that the XmlSerializer adds, and add the NHibernate URN in the mix. The recipe below outlines the three necessary steps.

Step 1

Suppress the xmlns:xsi andxmlns:xsd declarations that XmlSerializer creates by default.

var namespaces = new XmlSerializerNamespaces();
namespaces.Add(string.Empty, string.Empty);

var serializer = new XmlSerializer(typeof(T));
serializer.Serialize(t, writer, namespaces);

We now have a clean root element, free of any namespace declarations.

Step 2

Add the NHibernate namespace declaration. An overloaded constructor of XmlSerializer does the trick:

var namespaces = new XmlSerializerNamespaces();
namespaces.Add(string.Empty, string.Empty);
var serializer = new XmlSerializer(typeof(T), "urn:nhibernate-mapping-2.2");
serializer.Serialize(t, writer, namespaces);

We now get the namespace declaration, but with a namespace prefix. Besides, since that prefix is not then used on the elements inside the root, the resulting document is not correct. What we want is a default namespace declaration. (See XML Namespaces for a roadmap.)

Step 3

Remove the namespace prefix from the declaration (make it a default namespace declaration.)

var namespaces = new XmlSerializerNamespaces();
namespaces.Add(string.Empty, "urn:nhibernate-mapping-2.2");
var serializer = new XmlSerializer(typeof(T), "urn:nhibernate-mapping-2.2");
serializer.Serialize(t, writer, namespaces);

The document is now consistent with the goal. A default namespace declaration associates the root element and all its child nodes with the desired URI.

What happens if you skip some of these steps? Some things will go wrong:

  • If you don’t use the overloaded constructor in step 2, you get no namespace declarations on the hibernate-mapping element.
  • If you use the overloaded constructor, but not the namespaces collection in step 1, the NHibernate URN gets an XmlSerializer-assigned namespace alias. I got xmlns:q1=urn:nhibernate-mapping-2.2".
  • And finally, if you don’t include the NHibernate URN with an empty alias, as I did in step 3, you get no namespace declarations on the hibernate-mapping element.

Comments 1

  1. Stewart wrote:

    Hi Mihai,
    Thanks for this information as it saved me a lot of time.
    I wasn’t using the overloaded constructor in Step 2 – easy one to miss!
    Regards
    Stewart

    Posted 25 Sep 2008 at 5:05 am

Trackbacks & Pingbacks 1

  1. From Recent Faves Tagged With "xmlserializer" : MyNetFaves on 16 Oct 2008 at 12:35 pm

    [...] public links >> xmlserializer XmlSerializer Namespaces First saved by lordsytar | 2 days ago Porting to Silverlight 2 Beta First saved by KrispeKreme [...]

Post a Comment

You must be logged in to post a comment.