Deserialize nested XML element into class in C#
Building on Ilya's answer:
This can be optimized slightly, since there is already a loaded node: there is no need to pass the xml down to a string (using vehicle.ToString()
), only to cause the serializer to have to re-parse it (using a StringReader
).
Instead, we can created a reader directly using XNode.CreateReader
:
private static T Deserialize<T>(XNode data) where T : class, new(){ if (data == null) return null; var ser = new XmlSerializer(typeof(T)); return (T)ser.Deserialize(data.CreateReader());}
Or if data is a XmlNode
, use a XmlNodeReader
:
private static T Deserialize<T>(XmlNode data) where T : class, new(){ if (data == null) return null; var ser = new XmlSerializer(typeof(T)); using (var xmlNodeReader = new XmlNodeReader(data)) { return (T)ser.Deserialize(xmlNodeReader); }}
We can then use:
var vehicle = XDocument.Parse(xml) .Descendants("Vehicle") .First();Vehicle v = Deserialize<Vehicle>(vehicle);
I'm not aware of the full context of your problem, so this solution might not fit into your domain. But one solution is to define your model as:
[XmlRoot("Vehicle")] //<-- optionalpublic class Vehicle{ public string Colour { get; set; } public string NumOfDoors { get; set; } public string BodyStyle { get; set; }}
and pass specific node into Deserialize
method using LINQ to XML:
var vehicle = XDocument.Parse(xml) .Descendants("Vehicle") .First();Vehicle v = Deserialize<Vehicle>(vehicle.ToString());//display contents of v Console.WriteLine(v.BodyStyle); //prints HatchbackConsole.WriteLine(v.Colour); //prints BlueConsole.WriteLine(v.NumOfDoors); //prints 3