c# – Xml反序列化 – 将两个元素合并为一个List对象

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

XML示例:

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

我想创建一个包含项目3和4的列表(类型为Parameter).

我尝试过使用XmlArrayItem,例如:

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

我尝试过使用XmlElements(但我无法弄清楚如何将它们组合起来):

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

有没有办法做到这一点,而不只是创建两个单独的列表,并在以后组合它们?

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

最佳答案 您的XML具有包含
choice元素的模式.选择元素表示固定元素集之一 – < Parameter1>和< Parameter2>在你的情况下 – 将发生在XML中. XmlSerializer支持选择元素,如
Choice Element Binding Support中所述:

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:

>使用[XmlElementAttribute(String, Type)]对您的Parameter类进行子类化,并为每个元素名称指定不同的类型.实例化的特定Parameter子类将捕获XML元素名称.

即你可以这样做:

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; }
}

>如果要使用相同的参数类型来反序列化< Parameter1>和< Parameter2>元素,您必须引入一个辅助XmlChoiceIdentifierAttribute数组来捕获XML元素名称:

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数组相同数量的条目,其中的枚举值将指示实际遇到的每个参数的XML元素名称.
>作为选项2的变体,如果您不需要捕获XML元素名称并且只想反序列化值,则可以创建“假”选择数组属性,如下所示:

[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并显示以下消息:

06003

原型fiddle显示每个选项.

点赞