I have XML that contains elements like this
<Value xsi:type="xsd:short">0</Value>
<Value xsi:type="xsd:string">foo</Value>
<Value xsi:type="xsd:boolean">false</Value>
<!-- ... many other types -->
How can I automatically parse/deserialize this in a way that I get the content of Value
element in the correct .NET type that corresponds with the xsd: type (e.g. System.Int16
, System.String
, System.Boolean
)?
This is what I tried, but it is kind of brittle, there must be a built-in way in all those .NET XML APIs.
foreach (var value in XDocument.Load(new StreamReader(@"c:\bar.xml")).Descendants("Value"))
{
var actualValue = GetValue(value);
}
...
// TODO: Get rid of this hand written method, .NET should do this for me
private static object GetValue(XElement value)
{
XNamespace ns = "http://www.w3.org/2001/XMLSchema-instance";
var type = value.Attributes(ns + "type").Single().Value;
switch (type)
{
case "xsd:short":
return (short)value;
case "xsd:boolean":
return (bool)value;
case "xsd:string":
return (string)value;
...
}
throw new UnknownTypeException();
}
Assuming you can only expect builtin types, you could create an XML serializer to deserialize the values. Fortunately your attribute names match the expected names so you won't need to perform any transformations.
XNamespace xsd = "http://www.w3.org/2001/XMLSchema";
XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
var doc = new XDocument(
new XElement("root",
new XAttribute(XNamespace.Xmlns + "xsd", xsd),
new XAttribute(XNamespace.Xmlns + "xsi", xsi),
new XElement("Value", new XAttribute(xsi + "type", "xsd:short"), (short)0),
new XElement("Value", new XAttribute(xsi + "type", "xsd:string"), "foo"),
new XElement("Value", new XAttribute(xsi + "type", "xsd:boolean"), false)
)
);
var serializer = new XmlSerializer(typeof(object), new XmlRootAttribute("Value"));
var values = doc.Descendants("Value")
.Select(v => serializer.Deserialize(v.CreateReader()));