Xml反序列化-将两个元素合并为一个ListT.目的 [英] Xml Deserialization - Merging two elements into a single List<T> object

查看:161
本文介绍了Xml反序列化-将两个元素合并为一个ListT.目的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个XML文档,并且使用反序列化,有没有办法将两个元素组合成一个对象?

I have an XML document, and using deserialization, is there a way to combine two elements into one object?

XML示例:

<Parameter1>3</Parameter1>
<Parameter2>4</Parameter2>

我想创建一个包含参数3和4的列表(参数类型).

I want to create a list (of type Parameter) that contains both items, 3 and 4.

我尝试使用XmlArrayItem,例如:

I've tried using XmlArrayItem such as:

[XmlArrayItem("Parameter1")]
[XmlArrayItem("Parameter2")]
[XmlArray]
public Parameter[] Parameters; // have also tried this as public List<Parameter> Parameters = new List<Parameter>();

我尝试使用XmlElements(但是我不知道如何组合它们):

I've tried using XmlElements (but I can't figure out how to combine them):

[XmlElement("Parameter1")]
public List<Parameter> Parameters = new List<Parameter>();

有什么方法可以做到,而不仅仅是创建两个单独的列表并在以后合并它们?

Is there any way to do this without just creating two separate lists and combining them at a later point?

请注意,更改XML格式不是一种选择.

Please note that changing the XML format is not an option.

推荐答案

您的XML具有一个包含选择元素绑定支持中所述:

Your XML has a schema that includes a choice element. A choice element indicates that one of a fixed set of elements -- <Parameter1> and <Parameter2> in your case -- will occur in the XML. XmlSerializer supports choice elements as is explained in Choice Element Binding Support:

如果各个选择元素的类型及其名称不同,则Xsd.exe仅将XmlElementAttribute属性应用于公开成员.如果它们仅在名称上有所不同,Xsd.exe将另外应用XmlChoiceIdentifierAttribute,并添加额外的逻辑以供选择.

If individual choice elements' types differ along with their names, Xsd.exe applies only XmlElementAttribute attributes to a public member. If they differ only by name, Xsd.exe applies an XmlChoiceIdentifierAttribute in addition, and adds extra logic for making the choice.

因此,您具有以下用于反序列化XML的选项:

Thus, you have the following options to deserialize your XML:

  1. 使用

  1. Subclass your Parameter class and specify different types for each element name, using [XmlElementAttribute(String, Type)]. The specific Parameter subclass instantiated would thereby capture the XML element name.

即您可以这样做:

I.e. you could do:

public abstract class Parameter
{
    [XmlText]
    public string Value { get; set; } // Could be int if you prefer.
}

public class Parameter1 : Parameter
{
}

public class Parameter2 : Parameter
{
}

[XmlType("Root")]
public class RootObject
{
    [XmlElement("Parameter1", typeof(Parameter1))]
    [XmlElement("Parameter2", typeof(Parameter2))]
    public Parameter[] Parameters { get; set; }
}

  • 如果要使用相同的Parameter类型反序列化<Parameter1><Parameter2>元素,则必须引入辅助

  • If you want to use the same Parameter type to deserialize both <Parameter1> and <Parameter2> elements, you must introduce an ancillary XmlChoiceIdentifierAttribute array to capture the XML element name:

    public class Parameter
    {
        [XmlText]
        public string Value { get; set; }
    }
    
    [XmlType("Root")]
    public class RootObject
    {
        [XmlElement("Parameter1", typeof(Parameter))]
        [XmlElement("Parameter2", typeof(Parameter))]
        [XmlChoiceIdentifier("ParametersElementName")]
        public Parameter[] Parameters { get; set; }
    
        [XmlIgnore]
        public ParametersChoiceType[] ParametersElementName { get; set; }
    }
    
    [XmlType(IncludeInSchema = false)]
    public enum ParametersChoiceType
    {
        Parameter1,
        Parameter2,
    }
    

    反序列化后,ParametersElementName数组将具有与Parameters数组相同的条目数,并且其中的enum值将指示每个参数实际遇到的XML元素名称.

    After deserialization, the ParametersElementName array will have the same number of entries as the Parameters array, and the enum values therein will indicate the XML element name actually encountered for each parameter.

    作为选项2的变体,如果您不需要捕获XML元素名称而只想反序列化值,则可以创建一个伪"选择数组属性,如下所示:

    As a variation of option 2, if you do not need to capture the XML element name and just want to deserialize the values, you could create a "fake" choice array property as follows:

    [XmlType("Root")]
    public class RootObject
    {
        [XmlElement("Parameter1", typeof(Parameter))]
        [XmlElement("Parameter2", typeof(Parameter))]
        [XmlChoiceIdentifier("ParametersElementName")]
        public Parameter[] Parameters { get; set; }
    
        [XmlIgnore]
        public ParametersChoiceType[] ParametersElementName
        {
            get
            {
                if (Parameters == null)
                    return null;
                return Parameters.Select(p => ParametersChoiceType.Parameter1).ToArray();// Arbitrarily return ItemsChoiceType.Parameter1
            }
            set
            {
                // Do nothing - don't care.
            }
        }
    }
    

  • XmlSerializer要求您使用以下两个选项之一.如果无法通过类型或项目选择标识符确定正确的元素名称,则会抛出InvalidOperationException并显示以下消息:

    XmlSerializer requires you to use one of these two options. If it cannot determine a correct element name by type or by item choice identifier, it will throw an InvalidOperationException with the message:

    You need to add XmlChoiceIdentifierAttribute to the 'Parameters' member.
    

    原型小提琴显示每个选项.

    这篇关于Xml反序列化-将两个元素合并为一个ListT.目的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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