Search code examples
c#deserializationxmlserializer

XML deserialization with extra types throws error


I do not know the type of the XML before I deserialize it. So I'm using the overload of XmlSerializer with extraTypes. It does work for the first type, but it does not work for all the extraTypes. I'm getting the following errorMsg "System.InvalidOperationException: There is an error in XML document (1, 40). ---> System.InvalidOperationException: <Bike xmlns=''> was not expected.". Here's a dummy code of what I'm trying to do.

using System;
using System.IO;
using System.Xml.Serialization;

public class Program
{
    private const string CarXml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Car xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"></Car>";
    private const string BikeXml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Bike xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"></Bike>";


    public static void Main(string[] args)
    {
        var xmlSerializer = new XmlSerializer(typeof(Car), new[] { typeof(Bike) });

        using (var stringReader = new StringReader(BikeXml))
        {
            try
            {
                var vehicle = (Vehicle)xmlSerializer.Deserialize(stringReader);
                Console.WriteLine(vehicle.PrintMe());
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }

    }
}

public abstract class Vehicle
{
    public abstract string PrintMe();
}

public class Car : Vehicle
{
    public override string PrintMe()
    {
        return "beep beep I'm a car!";
    }
}

public class Bike : Vehicle
{
    public override string PrintMe()
    {
        return "bing bing I'm a bike!";
    }
}

Solution

  • Apparently the extraTypes are not meant to be used for my case. See msdn documentation.

    I solved it by getting the XmlRoot.

    public static void Main(string[] args)
    {
        var xmlDocument = new XmlDocument();
        xmlDocument.LoadXml(BikeXml);
        var rootName = xmlDocument.DocumentElement.Name;
        var rootType = Type.GetType(rootName);
        var vehicle = rootType != null ? (Vehicle) Activator.CreateInstance(rootType) : null;        
        Console.WriteLine(vehicle != null ? vehicle.PrintMe() : "Error");
    }