简体   繁体   English

使用XmlSerializer反序列化XML的替代方法

[英]Alternative for deserializing XML with XmlSerializer

I am programming an UWP app and want to deserialize a list inside a xml to a list of Objects: 我正在编写一个UWP应用程序,并希望将xml中的列表反序列化为对象列表:

<List>
    <Element Name="A">
        <SubElement Name="A1"> 
            <Color> Blue </Color> 
            <Color> Red </Color> 
        </SubElement>
        <SubElement Name="A2"> 
            <Color> Blue </Color> 
            <Color> Green </Color>  
        </SubElement>
    </Element>
    <Element Name="B">
        <SubElement Name="B1"> 
            <Color> Yellow </Color> 
            <Color> Red </Color> 
        </SubElement>
        <SubElement Name="B2"> 
            <Color> Yellow </Color> 
            <Color> Green </Color>  
        </SubElement>
    </Element>
    <Element Name="C"/>
        <SubElement Name="C1"> 
            <Color> Purple </Color> 
            <Color> Red </Color> 
        </SubElement>
        <SubElement Name="C2"> 
            <Color> Purple </Color> 
            <Color> Green </Color>  
        </SubElement>
    </Element>
</List> 

The classes look like this: 这些类看起来像这样:

public class Element
{
    [XmlAttribute]
    public string Name { get; set; }

    [XmlElement("SubElement")]
    public List<SubElement> _subelement { get; set; }
}

public class SubElement
{
      [XmlElement("Color")]
      public string Color{ get; set; }

      [XmlAttribute("Name")]
      public string Name { get; set; } 
}

My C# code looks like this: 我的C#代码如下所示:

XDocument doc = XDocument.Load("list.xml");
XElement node = doc.Descendants(XName.Get("List")).FirstOrDefault();
var serializer = new XmlSerializer(typeof(List<Element>), new XmlRootAttribute("List"));
var elementList = serializer.Deserialize(node.CreateReader()) as List<Element>;

In debug mode this application works fine. 在调试模式下,此应用程序正常工作 In release mode I get a PlatformNotSupportedException error as in this thread. 在发布模式下,我收到线程中的PlatformNotSupportedException错误。 I found out that the problem must have something to do with the Compile with .NET Native tool chain Option in the project settings. 我发现问题必须与项目设置中的Compile with .NET Native tool chain选项有关。 But I found no solution for the problem. 但我找不到解决问题的办法。

My Question: Is there a simple alternative for the code shown above to deserialize XML to Objects, which doesn't use XmlSerializer and works in an UWP app? 我的问题:上面显示的代码是否有一个简单的替代方法可以将XML反序列化为对象,它不使用XmlSerializer并在UWP应用程序中工作?

In your rewritten question , your XML would seem to have arbitrary complexity with a mixture of elements and attributes. 在您重写的问题中 ,您的XML似乎具有任意复杂性,并且具有元素和属性的混合。 You are seeking a way to deserialize this XML automatically without use of XmlSerializer , which basically amounts to writing another XML serializer . 您正在寻找一种在不使用XmlSerializer情况下自动反序列化此XML的方法,这基本上相当于编写另一个XML序列化程序

Since this is nontrivial (and outside the scope of a stackoverflow answer), one quick workaround would be to translate the XML to a format recognized by some other serializer, and use that. 由于这是非常重要的(并且超出了stackoverflow答案的范围),因此一个快速的解决方法是将XML转换为某些其他序列化程序识别的格式,并使用它。 Possibilities include: 可能性包括:

  1. DataContractSerializer . DataContractSerializer This serializer is intended for XML deserialization, but does not support: 此序列化程序用于XML反序列化,但不支持:

    • XML attribute deserialization . XML属性反序列化
    • Deserialization of sequences (such as <Element /><Element/> ) as collections without an outer element. 序列的反序列化(例如<Element /><Element/> )作为没有外部元素的集合。

    So, while it would be possible to deserialize your XML to some appropriate data model with this serializer, substantial preprocessing using LINQ to XML would be required. 因此,虽然可以使用此序列化程序将XML反序列化为某些适当的数据模型,但仍需要使用LINQ to XML进行大量预处理。

  2. Json.NET . Json.NET This serializer supports conversion of XML to JSON as documented in Converting between JSON and XML and thus may be appropriate to your needs. 此序列化程序支持将XML转换为JSON,如在JSON和XML之间转换中所述 ,因此可能适合您的需要。

If you choose option #2, you could define your data model as follows: 如果选择选项#2,则可以按如下方式定义数据模型:

public class RootObject
{
    [JsonConverter(typeof(SingleOrArrayConverter<Element>))]
    public List<Element> Element { get; set; }
}

public class Element
{
    [XmlAttribute]
    [JsonProperty("@Name")]
    public string Name { get; set; }

    [XmlElement("SubElement")]
    [JsonProperty("SubElement")]
    [JsonConverter(typeof(SingleOrArrayConverter<SubElement>))]
    public List<SubElement> _subelement { get; set; }
}

public class SubElement
{
    [XmlElement("Color")]
    [JsonConverter(typeof(SingleOrArrayConverter<string>))]
    public List<string> Color { get; set; }

    [XmlAttribute("Name")]
    [JsonProperty("@Name")]
    public string Name { get; set; }
}

And deserialize as follows: 并反序列化如下:

var doc = XDocument.Parse(xmlString);

// Convert the XDocument to an intermediate JToken hierarchy.
var converter = new Newtonsoft.Json.Converters.XmlNodeConverter { OmitRootObject = true };
var rootToken = JObject.FromObject(doc, JsonSerializer.CreateDefault(new JsonSerializerSettings { Converters = { converter } }));

// Convert the JTOken to a RootObject
var rootObj = rootToken.ToObject<RootObject>();

Notes: 笔记:

  • In your question your SubElement has a single Color property, but in your XML there are clearly multiple <Color> elements for each <SubElement> . 在您的问题中,您的SubElement具有单个Color属性,但在XML中,每个<SubElement>显然有多个<Color>元素。 Thus I had to change it to public List<string> Color { get; set; } 因此我不得不将其更改为public List<string> Color { get; set; } public List<string> Color { get; set; } public List<string> Color { get; set; } . public List<string> Color { get; set; }

  • SingleOrArrayConverter<> is taken verbatim from this answer to How to handle both a single item and an array for the same property using JSON.net by Brian Rogers . SingleOrArrayConverter<>是从如何使用 Brian Rogers的 JSON.net处理同一属性的单个项目和数组的 答案中逐字逐句采用的 It is needed to handle the case where a single child node is converted to a JSON object rather than a JSON array. 需要处理将单个子节点转换为JSON对象而不是JSON数组的情况。

Working .Net fiddle . 工作.Net小提琴

Given the XML shown in the initial version of your question: 鉴于您的问题的初始版本中显示的XML:

<List>
    <Element Name="A"/>
    <Element Name="B"/>
    <Element Name="C"/>
</List> 

And assuming your Element type looks like: 假设您的Element类型如下:

public class Element
{
    [XmlAttribute]
    public string Name { get; set; }
}

Then this type is so simple that you can construct it manually like so: 然后这种类型非常简单,您可以手动构建它,如下所示:

var list = doc
    // Get the first elements named List
    .Descendants("List").Take(1)
    // Get all children of List named Element
    .SelectMany(l => l.Elements("Element"))
    // Get the attribute of Element named Name, cast its value to a string, 
    // and create a c# Element from it using the specified name.
    .Select(e => new Element { Name = (string)e.Attribute("Name") } )
    // Materialize as a List<Element>
    .ToList();

Here I am using an explicit casting operator of XAttribute to convert the Name attribute to a string value. 这里我使用XAttribute显式转换运算符Name属性转换为字符串值。 There are also explicit casting operators for XElement to convert an element value to a primitive such as a string , an int or a nullable DateTime among others. XElement还有显式的转换运算符 ,可以将元素值转换为基元,例如stringint空的DateTime等。 These operators can be used when populating ac# type as shown above. 如上所示,在填充ac#类型时可以使用这些运算符。

(Switching to DataContractSerializer would not be easier since this serializer does not support XML attributes out of the box meaning you would have to do something manual anyway.) (切换到DataContractSerializer并不容易,因为此序列化程序不支持开箱即用的XML属性,这意味着您无论如何都必须执行某些操作。)

Sample working .Net fiddle . 样品工作.Net小提琴

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 XMLSerializer不反序列化XML - XMLSerializer not deserializing XML XmlSerializer 不会将 XML 反序列化为 IEnumerable - XmlSerializer not deserializing XML to IEnumerable 使用 XmlSerializer 将 XML 反序列化为类型 - Deserializing XML to a type with XmlSerializer XMLSerializer未正确地为List类型的属性反序列化XML - XMLSerializer is not correctly deserializing XML for a property of type List 反序列化XML(C#)时出错:XML文档(2、2)中存在错误(但XmlSerializer创建了它) - Error Deserializing XML (C#): There is an error in XML document (2, 2) (but XmlSerializer created it) 反序列化 XML 文件使用 XmlSerializer.Deserialize 从 MemoryStream 不起作用 - Deserializing XML File using XmlSerializer.Deserialize from MemoryStream not working 使用XmlSerializer反序列化RSS xml提要的pubDate元素时的错误 - The error when deserializing the pubDate element of an RSS xml feed using XmlSerializer 使用XmlSerializer将xml元素反序列化为Array不起作用 - Deserializing xml element to Array with XmlSerializer doesn't work 在C#中使用XMLSerializer将xml字符串反序列化为对象时出错 - Error while deserializing xml string into object using XMLSerializer in C# 根元素使用XmlSerializer反序列化XML响应时丢失 - Root Element Missing when deserializing an XML response using XmlSerializer
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM