I have a problem with deserialization of a not so common XML structure. Unfortunately I have no influence on the source site.
The XML has a root named Bus
that can have multiple Device
elements.
The Device
element can have multiple values. (so long so good).
<Bus protocol="Meterbus" baud="2400">
<Device Name="DHZ-1" PrimaryAddr="62">
<Energie _="value" Name="Energie" size="13"/>
<Spannung _="value" Name="Spannung" size="13"/>
<Strom _="value" Name="Strom" size="13"/>
<Leistung _="value" Name="Leistung" size="13"/>
<Seriennummer _="value" Name="Seriennummer" size="13"/>
<... _="..." Name="..." size=".."/>
</Device>
</Bus>
The problem is that the values have complete dynamic element names, but same parameter.
It can be something like <somename _="value" Name="somename" size="13"/>
.
But they should all be serialized as a Value
type, no matter the are named.
Something like this:
public class Value
{
[XmlAttribute("_")]
public String _
{
get;
set;
}
[XmlAttribute("Name")]
public String Name
{
get;
set;
}
[XmlAttribute("size")]
public String Size
{
get;
set;
}
}
The Device
class looks like this:
public class Device
{
[XmlAttribute("Name")]
public String Name
{
get;
set;
}
[XmlAttribute("PrimaryAddr")]
public String PrimaryAddr
{
get;
set;
}
[???]
public Array<Value> Values
{
get;
set;
}
}
How can I explain this to the serializer?
The XmlSerializer
class implements an UnknownElement
event which is invoked whenever an undefined/unknown element is being parser. You can subscribe an handler to this event and deserialize the undefined/unknown elements manually:
XmlSerializer serializer = new XmlSerializer(typeof(Bus));
serializer.UnknownElement += new XmlElementEventHandler(Serializer_UnknownElement);
A worked example:
private void Serializer_UnknownElement(Object sender, XmlElementEventArgs e)
{
var device = e.ObjectBeingDeserialized as Device;
if (device != null)
{
XmlElement element = e.Element;
using (StringReader reader = new StringReader(element.OuterXml))
{
XmlSerializer valueSerializer = new XmlSerializer(typeof(Value), (new XmlRootAttribute(element.Name)));
Value value = (Value)valueSerializer.Deserialize(reader);
value.Name = element.Name; // implement it so you can rebuild the tag back
device.Values.Add(value);
}
}
}
Official MSDN documentation here.