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

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

XML示例:

3 4 

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

我尝试过使用XmlArrayItem,例如:

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

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

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

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

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

如果你这样做会怎么样:

 //get the xml doc const string str = @" 3 4 "; var xml = new XmlDocument(); //load it xml.LoadXml(str); //get the nodes where the names contain the string parameter var xnList = xml.SelectNodes("//*[contains(name(),'Parameter')]"); //create a list of parameters var list = new List(); //populate the list with the value in the node's innertext foreach (XmlNode xn in xnList) { list.Add(new Parameter{ Value = int.Parse(xn.InnerText) } ); } foreach(var param in list) Console.WriteLine(param.Value); //should print 3 and 4 

我使用这个类作为例子:

 class Parameter{ public int Value { get; set; } } 

您的XML具有包含choice元素的架构。 一个choice元素表示一个固定的元素集 – 在你的情况下是 – 将出现在XML中。 XmlSerializer支持选择元素,如选择元素绑定支持中所述 :

如果各个选项元素的类型及其名称不同,则Xsd.exe仅将XmlElementAttribute属性应用于公共成员。 如果它们仅按名称不同,则Xsd.exe另外应用XmlChoiceIdentifierAttribute ,并添加额外的逻辑以进行选择。

因此,您可以使用以下选项反序列化XML:

  1. 使用[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; } } 
  2. 如果要使用相同的Parameter类型对元素进行反序列化,则必须引入辅助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数组将具有与ParametersElementName数组相同数量的条目,其中的enum值将指示实际遇到的每个参数的XML元素名称。

  3. 作为选项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

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

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