使用正确的xsd:类型解析XML

本文关键字:类型 XML xsd | 更新日期: 2023-09-27 18:03:51

我有一个包含如下元素的XML

<Value xsi:type="xsd:short">0</Value>
<Value xsi:type="xsd:string">foo</Value>
<Value xsi:type="xsd:boolean">false</Value>
<!-- ... many other types -->

我如何自动解析/反序列化这在一种方式,我得到Value元素的内容在正确的。net类型对应于xsd:类型(例如System.Int16, System.String, System.Boolean)?

这是我尝试过的,但它有点脆弱,必须有一个内置的方法在所有这些。net XML api。

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();
}

使用正确的xsd:类型解析XML

假设只能使用内置类型,则可以创建XML序列化器来反序列化值。幸运的是,您的属性名与期望的名称匹配,因此您不需要执行任何转换。

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()));

试试这个

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication11
{
    class Program
    {
        static void Main(string[] args)
        {
            List<object> values = new List<object>();
            string xml =
                "<Root xmlns:xsi = '"abc'">" +
                    "<Value xsi:type='"xsd:short'">0</Value>" +
                    "<Value xsi:type='"xsd:string'">foo</Value>" +
                    "<Value xsi:type='"xsd:boolean'">false</Value>" +
                "</Root>";
            XElement root = XElement.Parse(xml);
            XNamespace ns = root.GetDefaultNamespace();
            foreach(XElement value in root.Descendants("Value"))
            {
                string _type = (string)value.Attributes().Where(x => x.Name.LocalName == "type").FirstOrDefault();
                switch (_type)
                {
                    case "xsd:short"  :
                        values.Add((short)value);
                        break;
                    case "xsd:string":
                        values.Add((string)value);
                        break;
                    case "xsd:boolean":
                        values.Add((Boolean)value);
                        break;
                }
            }
        }
    }
}