Xml反序列化-将两个元素合并为一个ListT.目的 [英] Xml Deserialization - Merging two elements into a single List<T> object
问题描述
我有一个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 anXmlChoiceIdentifierAttribute
in addition, and adds extra logic for making the choice.
因此,您具有以下用于反序列化XML的选项:
Thus, you have the following options to deserialize your XML:
Subclass your
Parameter
class and specify different types for each element name, using[XmlElementAttribute(String, Type)]
. The specificParameter
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; }
}
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屋!