XmlSerializer - 序列化没有父元素的列表元素
本文关键字:元素 列表元素 序列化 XmlSerializer | 更新日期: 2023-09-27 18:33:11
我知道他的问题也已经被问过并回答了,但我有一种不同的情况,该解决方案不起作用。我有一个 Web 方法响应 xsd,我需要对其进行序列化/反序列化。下面是该 xsd 中存在问题的片段。
<xs:choice minOccurs="0">
<xs:element name="Type1" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="string1"/>
<xs:element type="xs:string" name="string2"/>
<xs:element type="xs:boolean" name="boolean1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Type2">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:float" name="float1"/>
<xs:element type="xs:float" name="float2"/>
<xs:element type="xs:float" name="float3"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
我已经定义了这个选择元素,如下所示:
public class Type1
{
[XmlElement(IsNullable = true)]
public string string1 { get; set; }
[XmlElement(IsNullable = true)]
public string string2 { get; set; }
public bool boolean1 { get; set; }
}
public class Type2
{
public float float1 { get; set; }
public float float { get; set; }
public float float3 { get; set; }
}
[XmlElement("Type1", typeof(List<Type1>), IsNullable = true)]
[XmlElement("Type2", typeof(Type2), IsNullable = true)]
public object Type { get; set; }
问题是当我需要序列化 Type1 元素列表时。我明白这个:
<Type1>
<Type1>
<string1>6185</string1>
<string2>VW</string2>
<boolean1>true</boolean1>
</Type1>
<Type1>
<string1>6186</string1>
<string2>AUDI</string2>
<boolean1>true</boolean1>
</Type1>
<Type1>
<string1>6187</string1>
<string2>OPEL</string2>
<boolean1>true</boolean1>
</Type1>
</Type1>
当我根据 XSD 需要得到这个时:
<Type1>
<string1>6185</string1>
<string2>VW</string2>
<boolean1>true</boolean1>
</Type1>
<Type1>
<string1>6186</string1>
<string2>AUDI</string2>
<boolean1>true</boolean1>
</Type1>
<Type1>
<string1>6187</string1>
<string2>OPEL</string2>
<boolean1>true</boolean1>
</Type1>
所以我的问题是,如何摆脱封装所有 Type1 列表元素的父元素"Type1"?
谢谢!
为了生成所需的 XML,您可能需要稍微更改数据模型。
XmlSerializer
支持单个多态元素或多态元素的集合。 在这两种情况下,它都会查看每个元素的名称,以确定反序列化时的实际类型。 在您的情况下,您希望拥有一种类型的集合或另一种类型的单一实例。 您已经通过指定XmlSerializer
有效地将集合视为类型 List<Type1>
的单一实例来实现此设计 - 这将需要列表的外部容器元素。
由于您不希望这样做,因此可以改为指定 Type
属性是每种类型的多态元素的集合:
[XmlElement("Type1", typeof(Type1), IsNullable = true)]
[XmlElement("Type2", typeof(Type2), IsNullable = true)]
public List<object> Type
如果要保留当前数据模型,可以创建一个代理属性,将Type
打包到数组中,验证数组是否包含第一种类型的集合或第二种类型的单一实例:
[XmlRoot("Root")]
public class RootObject
{
[XmlElement("Type1", typeof(Type1), IsNullable = true)]
[XmlElement("Type2", typeof(Type2), IsNullable = true)]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)]
public object [] TypeArray
{
get
{
if (Type == null)
return null;
var collection = Type as IEnumerable;
if (collection != null)
return collection.Cast<object>().ToArray();
else
return new[] { Type };
}
set
{
if (value == null)
{
Type = null;
return;
}
var type1 = value.OfType<Type1>().ToList();
var type2 = value.Where(t => t == null || t is Type2).Cast<Type2>().ToList();
if (type2.Count == 1 && type1.Count == 0)
Type = type2[0];
else if (type1.Count == value.Length)
Type = type1;
else
throw new InvalidOperationException("invalid value");
}
}
[XmlIgnore]
public object Type { get; set; }
}
原型小提琴。