Pages - Menu

Xml Deserialization with Namespace Prefix in C#

Scope

  • To deserialize an xml from a 3rd party vendor into a strongly typed C# object.
  • The xml has a namespace attached.
  • No DTD or XSD were provided by vendor.

Steps

XML Schema Definition Tool (Xsd.exe)



Basically 2 command lines I executed:
  1. I first created the xsd file from a sample xml file that I have.
  2. Then I created the cs class file for the model by using the xsd scheme. 

Model

It is the best to generate model via Xsd tool because it contains a lot of System.Xml.Serialization Attribute that are needed for the serializer. Especially around the namespace area!! 

The class file will look something like this. A typical model class with lots of attribute hints.



Serializer

All the hard works were done for generating the model and xml attributes. That left this part a bit simple in comparison. It is a bit similar to Autofac, where the hard works are done at the entity level and the actual conversion is just 1 line of ToEntity().

The code looks like this. Some people managed to do this in 2 lines, but I found 4 lines look pretty neat for readability and my troubleshooting.



Troubleshoot


Unbounded Complex Type Bug

1 of the error that I ran into looks like this.

Unable to generate a temporary class (result=1). error CS0030: Cannot convert type

It is a confirmed Microsoft bug and won't be fixed.

The work around is to change the unbounded or add a dummy element for the complex type.


I added the element and regenerated the model class file, and the serializer is happy again.

Xsd generated incorrect schema

The xml schema reverse engineered by using xsd.exe from a sample xml file is slightly incorrect. It predicted I might have multiple child nodes, thus the class generated had all these unnecessary array declaration.

Looks like this.

   1: public MyComplexType Notes []


I would not blame the xsd tool but there are some manual works required to fix it. (Or C# code will end up with a lot of .FirstOrDefault()

XElement.Name.LocalName

As described before, there is a fallency of trying to access the element via XElement.Name. This method only works when there is no namespace. Out of curiosity and I read further that the correct way is to use XElement.Name.LocalName. I wouldn't recommend going down this path, but it is interesting to know that how we conventionally accessing an element name incorrectly (when you have namespace).

http://msdn.microsoft.com/en-us/library/system.xml.linq.xelement.name%28v=vs.110%29.aspx

1 comment: