C#将不同类型的xml数组反序列化为多个数组

Posted

技术标签:

【中文标题】C#将不同类型的xml数组反序列化为多个数组【英文标题】:C# deserialize xml array of different types into multiple arrays 【发布时间】:2016-05-05 02:22:00 【问题描述】:

我有以下 xml:

<Applications>
    <AccessibleApplication></AccessibleApplication>
    <AccessibleApplication></AccessibleApplication>
    <EligibleApplication></EligibleApplication>
    <EligibleApplication></EligibleApplication>
</Applications>

有没有办法将其反序列化为 C# 对象,以便 AccessibleApplications 和 EligibleApplications 是两个独立的数组?我尝试了以下方法,但出现异常,因为“应用程序”被多次使用。

[XmlArray("Applications")]
[XmlArrayItem("AccessibleApplication")]
public List<Application> AccessibleApplications  get; set; 

[XmlArray("Applications")]
[XmlArrayItem("EligibleApplication")]
public List<Application> EligibleApplications  get; set; 

例外情况是: 命名空间“”中的 XML 元素“应用程序”已存在于当前范围内。使用 XML 属性为元素指定另一个 XML 名称或命名空间。

这可能吗?

谢谢!

编辑:我忘了说我不想仅仅为了为两个数组提供一个容器对象而有一个“应用程序”类。我有几种这样的情况,我不希望这些类杂乱无章,其唯一目的是拆分两个相同类型的数组。

我希望能够使用诸如 [XmlArrayItem="Application/AccessibleApplication"] 之类的某种标签将两个数组反序列化为外部对象,而无需创建“应用程序”类。

【问题讨论】:

【参考方案1】:

我找到了一个相当巧妙的方法,首先创建一个这样的类:

using System.Xml.Serialization;

[XmlRoot]
public class Applications

    [XmlElement]
    public string[] AccessibleApplication;
    [XmlElement]
    public string[] EligibleApplication;

请注意元素如何成为单独的数组。现在使用这个类(我的 XML 在一个单独的文件中,因此是 XmlDocument 类)。

var doc = new XmlDocument();
doc.Load("../../Apps.xml");
var serializer = new XmlSerializer(typeof(Applications));
Applications result;

using (TextReader reader = new StringReader(doc.InnerXml))

    result = (Applications)serializer.Deserialize(reader);

现在为了证明这是可行的,您可以将其全部写入控制台应用程序并执行 foreach 以打印数组中的所有值,如下所示:

foreach (var app in result.AccessibleApplication)

    Console.WriteLine(app);

foreach (var app in result.EligibleApplication)

    Console.WriteLine(app);

【讨论】:

【参考方案2】:

您可以使用 XmlElement 属性来反序列化到不同的列表:

public class Applications

    [XmlElement("AccessibleApplication")]
    public List<Application> AccessibleApplications  get; set; 

    [XmlElement("EligibleApplication")]
    public List<Application> EligibleApplications  get; set; 


public class Application

    [XmlText]
    public string Value  get; set; 

所以对于一个示例 XML:

<Applications>
    <AccessibleApplication>xyz</AccessibleApplication>
    <AccessibleApplication>abc</AccessibleApplication>
    <EligibleApplication>def</EligibleApplication>
    <EligibleApplication>zzz</EligibleApplication>
</Applications>

以下 sn-p 将输出以下内容:

using (var reader = new StreamReader("XMLFile1.xml"))

    var serializer = new XmlSerializer(typeof(Applications));
    var applications = (Applications)serializer.Deserialize(reader);

    Console.WriteLine("AccessibleApplications:");
    foreach (var app in applications.AccessibleApplications)
    
        Console.WriteLine(app.Value);
    

    Console.WriteLine();

    Console.WriteLine("EligibleApplications:");
    foreach (var app in applications.EligibleApplications)
    
        Console.WriteLine(app.Value);
    

输出:

可访问的应用程序:

xyz

abc

符合条件的申请:

定义

zzz

【讨论】:

【参考方案3】:

你可以使用这个类从字符串创建对象,从对象创建字符串和从对象创建字节[]

StringToObject

var applicationObject = new XmlSerializerHelper<Applications>().StringToObject(xmlString);

ObjectToString

var xmlString = new XmlSerializerHelper<Applications>().ObjectToString(applicationObject);

ObjectToByteArray

var byteArray = new XmlSerializerHelper<Applications>().ObjectToByteArray(applicationObject);

XmlSerializerHelper:

namespace ***

    public class XmlSerializerHelper<T> where T : class
    
        private readonly XmlSerializer _serializer;

        public XmlSerializerHelper()
        
            _serializer = new XmlSerializer(typeof(T));

        

        public T ToObject(string xml)
        
            return (T)_serializer.Deserialize(new StringReader(xml));
        

        public string ToString(T obj, string encoding)
        
            using (var memoryStream = new MemoryStream())
            
                _serializer.Serialize(memoryStream, obj);
                return Encoding.GetEncoding(encoding).GetString(memoryStream.ToArray());
            
        

        public byte[] ToByteArray(T obj, Encoding encoding = null)
        
            var settings = GetSettings(encoding);
            using (var memoryStream = new MemoryStream())
            
                using (var writer = XmlWriter.Create(memoryStream, settings))
                
                    _serializer.Serialize(writer, obj);
                
                return memoryStream.ToArray();
            
        

        private XmlWriterSettings GetSettings(Encoding encoding)
        
            return new XmlWriterSettings
            
                Encoding = encoding ?? Encoding.GetEncoding("ISO-8859-1"),
                Indent = true,
                IndentChars = "\t",
                NewLineChars = Environment.NewLine,
                ConformanceLevel = ConformanceLevel.Document
            ;
        
    
 

你的班级:

[XmlRoot]
public class Applications

    [XmlElement("AccessibleApplication")]
    public string[] AccessibleApplication  get; set; 
    [XmlElement("EligibleApplication")]
    public string[] EligibleApplication  get; set; 

或者

[XmlRoot]
public class Applications

    [XmlElement("AccessibleApplication")]
    public List<string> AccessibleApplication  get; set; 
    [XmlElement("EligibleApplication")]
    public List<string> EligibleApplication  get; set; 

干杯。

【讨论】:

以上是关于C#将不同类型的xml数组反序列化为多个数组的主要内容,如果未能解决你的问题,请参考以下文章

Json.NET:将嵌套数组反序列化为强类型对象

将 JSON 数组反序列化为 List<T> C# 时出错

C# XMLSerializer 将错误的类型反序列化为 List

将位置坐标的 Mongo BSON 数组反序列化为自定义 C# 类

无法反序列化 xml 数组以列出 web api 模型 c#

如何将不同名称的 XML 节点反序列化为相同的基本类型