一种选择是在反序列化之前使用 XSLT 转换将所有节点和属性名称转换为小写。看这个答案进行必要的 XSLT 转换,以及这个问题有关在 C# 中使用 XSLT 转换的说明。
另一种选择是使用 Json.NET 从 XML 转换为 JSON,如下所示JSON 和 XML 之间的转换,然后用Json.NET反序列化,即不区分大小写。您需要注意 XML 和 JSON 之间的一个不一致之处,即 JSON 有数组的概念,而 XML 没有,因此使用重复元素来表示数组。 Json.NET 的XML 到 JSON 转换器检测重复元素并将其转换为数组,但当 XML 数组只有一个元素时,这种情况不会发生。在这种情况下,必须遵循以下指示:将 XML 转换为 JSON 并强制数组并添加json:Array='true'
属性到 XML 中。
因此,您可以引入以下扩展方法:
public static class JsonExtensions
{
const string JsonNamespace = @"http://james.newtonking.com/projects/json";
const string ArrayAttributeName = @"Array";
public static JToken ToJToken(this XElement xElement, bool omitRootObject, string deserializeRootElementName)
{
return xElement.ToJToken(omitRootObject, deserializeRootElementName, Enumerable.Empty<Func<XElement, IEnumerable<XElement>>>());
}
public static JToken ToJToken(this XElement xElement, bool omitRootObject, string deserializeRootElementName, IEnumerable<Func<XElement, IEnumerable<XElement>>> arrayQueries)
{
foreach (var query in arrayQueries)
{
var name = XName.Get(ArrayAttributeName, JsonNamespace);
foreach (var element in query(xElement))
{
element.SetAttributeValue(name, true);
}
}
// Convert to Linq to XML JObject
var settings = new JsonSerializerSettings { Converters = { new XmlNodeConverter { OmitRootObject = omitRootObject, DeserializeRootElementName = deserializeRootElementName } } };
var root = JToken.FromObject(xElement, JsonSerializer.CreateDefault(settings));
return root;
}
}
然后,给出以下 XML:
<root>
<perSon ID='1'>
<name>Alan</name>
<url>http://www.google.com</url>
</perSon>
</root>
以及以下类型:
public class Person
{
public string Name { get; set; }
public string URL { get; set; }
[XmlAttribute(AttributeName = "id")]
[JsonProperty("@id")]
public string Id { get; set; }
}
public class Root
{
[XmlElement]
public List<Person> Person { get; set; }
}
您可以按如下方式反序列化 XML:
var xElement = XElement.Parse(xml);
var jToken = xElement.ToJToken(true, "",
new Func<XElement, IEnumerable<XElement>> [] { e => e.Elements().Where(i => string.Equals(i.Name.LocalName, "Person", StringComparison.OrdinalIgnoreCase)) });
var root = jToken.ToObject<Root>();
Sample fiddle.