当元素的大小写不一致时,反序列化/读取xml。 [英] Deserialize/Read xml when casing of elements is inconsistent.

查看:261
本文介绍了当元素的大小写不一致时,反序列化/读取xml。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前很高兴为第三方编写一个接口,该第三方的出色Web服务根据响应类型在不同的xml大小写中进行响应。即使给出相同的请求,根据结果是否成功,错误,错误类型等,大小写也会有所不同。您明白了这一点,这是一场噩梦。

I currently have the joy of writing an interface to a 3rd party whose wonderful webservice responds in different xml casing depending on the response type. Even given the same request the casing will be different depending on whether the result is successful, an error, the type of error etc. You get the point, its a nightmare.

据我所知,尚无不区分大小写的解串器。
到目前为止,最好的方法是将xml解析为XElement并尝试使用一些常见的大小写形式,例如Pasal Casing,Camel Casing,小写字母等。

As far as im aware there are no case insensitive deserializers available. The best ive gotten so far is to parse the xml into an XElement and trying some common casing such as Pasal Casing, Camel Casing, lower case etc.

有更好的建议吗?

推荐答案

一种选择是使用XSLT转换,然后将所有节点和属性名称转换为小写形式反序列化。请参阅此答案以获取必要的XSLT转换,以及这个问题,以获取有关在c#中使用XSLT转换的说明。

One option would be to use an XSLT transform to convert all the node and attribute names to lower case before deserialization. See this answer for the necessary XSLT transform, and this question for instructions on using XSLT transforms in c#.

另一种选择是使用Json.NET将XML转换为JSON,如< a href = https://www.newtonsoft.com/json/help/html/ConvertingJSONandXML.htm rel = nofollow noreferrer>在JSON和XML之间进行转换,然后使用Json.NET反序列化不区分大小写。您需要注意XML与JSON之间的一种不一致,即JSON具有数组的概念,而XML没有,因此使用重复元素来表示数组。 Json.NET的 XML-to-JSON转换器检测重复元素并进行转换将它们转换为数组,但是当XML数组只有一个元素时,则不会发生这种情况。在这种情况下,有必要遵循将XML转换为JSON并强制使用数组并将 json:Array ='true'属性添加到XML中。

Another option would be to convert from XML to JSON using Json.NET as shown in Converting between JSON and XML, then deserialize with Json.NET, which is case insensitive. You need to be aware of one inconsistency between XML and JSON, namely that JSON has the concept of an array while XML does not and so uses repeating elements to represent arrays instead. Json.NET's XML-to-JSON converter detects repeating elements and converts them to arrays, but when an XML array has only one element this does not happen. In this situation it is necessary to follow the instructions from Convert XML to JSON and force array and add json:Array='true' attributes into the XML.

因此,您可以引入以下扩展方法:

Thus, you can introduce the following extension methods:

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:

Then, given the following 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:

You can deserialize the XML as follows:

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

示例小提琴

这篇关于当元素的大小写不一致时,反序列化/读取xml。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆