Search code examples
c#xmlxml-deserializationxmltypetypename

Changing an element's name during deserialization of xml c#


I have a class that looks like this:

[XmlType(TypeName = "rootType")]
public class myClass
{
    public Class1 class1;
    public Class2 class2;

    [XmlType(TypeName = "type1")]
    public class class1
    { ... class1 definition ...}
    [XmlType(TypeName = "type2")]
    public class class2
    { ... class1 definition ...}    

}

When I serialize it, the resulting xml would be

<rootType>
    <class1>
       ... some stuff
    <class1/>
    <class2>
       ... some stuff
    <class2/>
<rootType/>

However, my problem here is that these xmltype decorations have just been added to the class, meaning that in previous versions (which clients use) the xml would look something like

<myClass>
    <type1>
       ... some stuff
    <type1/>
    <type2>
       ... some stuff
    <type2/>
<myClass/>

Is there a way that I can control the deserialization process (or any other way that will solve this), if possible, and be able to deserialize this xml to myClass with these XmlType decorations?


Solution

  • Your problem is completely solved.

    First, when you create a serializer, add a XmlRootAttribute parameter with the desired name.

    Second, add the event handler to the serializer.

    var serializer = new XmlSerializer(typeof(myClass), new XmlRootAttribute("myClass"));
    serializer.UnknownElement += Serializer_UnknownElement;
    

    The event handler should look like this:

    void Serializer_UnknownElement(object sender, XmlElementEventArgs e)
    {
        myClass my = (myClass)e.ObjectBeingDeserialized;
    
        if (e.Element.Name == "type1")
        {
            var ser = new XmlSerializer(typeof(myClass.Class1));
            using (var sr = new StringReader(e.Element.OuterXml))
                my.class1 = (myClass.Class1)ser.Deserialize(sr);
        }
        else if (e.Element.Name == "type2")
        {
            var ser = new XmlSerializer(typeof(myClass.Class2));
            using (var sr = new StringReader(e.Element.OuterXml))
                my.class2 = (myClass.Class2)ser.Deserialize(sr);
        }
    }
    

    To use as always:

    myClass my;
    using (var fs = new FileStream("test.xml", FileMode.Open))
        my = (myClass)serializer.Deserialize(fs);
    

    It's supposed to work.