我有一个
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 anXmlChoiceIdentifierAttribute
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显示每个选项.