Saturday, November 22, 2008

Xml Deserialization: a home grown method

Download source code Download source code
If you have ever called System.Xml.Serialization.XmlSerializer.Deserialize and got this exception: System.InvalidOperationException: '' was not expected, you know that getting the xml namespaces right for deserialization can sometimes be a trial and error process.

If you have access to the class you want to deserialize to you can add a custom attribute to define the xml namespace to use for serialization.
[System.Xml.Serialization.XmlTypeAttribute(Namespace="MyNamespace")]
public class MyClass {
    ...
}
If the class is in one of the built in libraries or in a third party library and you can't modify it you can modify the xml to add a namespace attribute instead.
<MyClass xmlns="MyNamespace">
Another alternative is to use different deserialization code that is more forgiving about things like xml namespaces and case sensitivity. I have created one that uses the XML DOM parser System.Xml.XmlDocument and System.Reflection to iterate through the public fields and properties of an object and find the xml elements and attributes that best match the field names.
// simplified snippet
public static T XmlStrToObjBestWeCan<T>(string xml) {
    System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
    doc.LoadXml(xml);
    foreach (System.Reflection.FieldInfo field in typeof(T).GetFields()) {
        foreach (object attribute in field.GetCustomAttributes(typeof(System.Xml.Serialization.XmlElementAttribute), false)) {
            ...
        }
        foreach (System.Xml.XmlNode child in doc.DocumentElement.ChildNodes) {
            ...
        }
Download complete file

You can download the code and include it in your project to see how it compares to the built in deserializer.

No comments: