The following example gives me "[One xmlns=''] was not expected." exception
public abstract class BaseClass{ }
[XmlRoot("One")]
public class ChildOne : BaseClass {}
[XmlRoot("Two")]
public class ChildTwo : BaseClass { }
class Program
{
private static void Main(string[] args)
{
var ser = new XmlSerializer(typeof (BaseClass), new Type[] {typeof (ChildOne), typeof (ChildTwo)});
var obj1 = ser.Deserialize(new StringReader(@"<?xml version=""1.0""?><One></One>"));
var obj2 = ser.Deserialize(new StringReader(@"<?xml version=""1.0""?><Two></Two>"));
}
}
I need to deserialize XML (generated not by me). Root tag may have different names which I have to map to different classes.
PS. I know there is a lot of questions like this around. I have studied them but my problem is still not solved.
No hype building up around my question. Community might be thinking it is just another stupid question asked by an idiot. They might be right. I'll have to answer it myself but beware: the answer might be stupid too.
I ended up probing root element of XML, then mapping it to one of the known types and deserializing using that type. Like so:
public abstract class BaseClass{ }
[XmlRoot("One")]
public class ChildOne : BaseClass {}
[XmlRoot("Two")]
public class ChildTwo : BaseClass { }
class Program
{
private static void Main(string[] args)
{
var known = new Type[] {typeof (ChildOne), typeof (ChildTwo)};
var obj1 = Deserialize<BaseClass>(@"<?xml version=""1.0""?><One></One>", known);
var obj2 = Deserialize<BaseClass>(@"<?xml version=""1.0""?><Two></Two>", known);
}
private static T Deserialize<T>(string xml, Type[] knownTypes)
{
Type rootType = typeof (T);
if (knownTypes.Any())
{
using (var reader = XmlReader.Create(new StringReader(xml)))
{
reader.MoveToContent();
rootType = (from kt in knownTypes
let xmlRoot = kt.GetCustomAttributes<XmlRootAttribute>().FirstOrDefault()
where kt.Name == reader.Name || (xmlRoot != null && xmlRoot.ElementName == reader.Name)
select kt).FirstOrDefault() ?? typeof(T);
}
}
return (T) new XmlSerializer(rootType, knownTypes).Deserialize(new StringReader(xml));
}
}
To expand on your answer you could use a little LinqToXml to parse the xml to get the root name.
private T Deserialize<T>(string xml, Type[] knownTypes)
{
var rootType = knownTypes.FirstOrDefault(t => t.GetCustomAttributes<XmlRootAttribute>()
.Any(a => a.ElementName == XElement.Parse(xml).Name.LocalName));
return (T)new XmlSerializer(rootType ?? typeof(T), knownTypes).Deserialize(new StringReader(xml));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With