非泛型ArrayList序列化输出ArrayOfAnyType,如何生成目标XML结构?
问题描述
序列化非泛型ArrayList时遇到XML结构不符合预期的问题,必须使用非泛型ArrayList,添加[XmlArray("LineDetails")]后代码可运行,但输出的XML嵌套了多余的anyType节点,无法生成目标结构。XML层级要求为Document > Header > LineCollection > LineDetails,其中LineDetails是动态数量的节点。
相关代码
[XmlType(TypeName = "LineCollection")] public class LineCollection { public String LineCount{ get; set; } // [XmlElement(ElementName = "LineDetails")] [XmlArray("LineDetails")] public ArrayList LineDetails{ get; set; } } public class LineDetails: ArrayList { public String LineNum{ get; set; } public String ItemId{ get; set; } public String ItemName{ get; set; } //... only strings } public class Utf8StringWriter : StringWriter { public override Encoding Encoding => new UTF8Encoding(false); } public string Serialize() { // var xmlserializer = new XmlSerializer(this.GetType()); var xmlserializer = new XmlSerializer(this.GetType(), new Type[] { typeof(LineDetails) }); var Utf8StringWriter = new Utf8StringWriter(); var xns = new XmlSerializerNamespaces(); xns.Add(string.Empty, string.Empty); using (var writer = XmlWriter.Create(Utf8StringWriter)) { xmlserializer.Serialize(writer, this, xns); return Utf8StringWriter.ToString(); } }
当前错误输出
<LineColletion> <LineDetails> <anyType xmlns:p5="http://www.w3.org/2001/XMLSchema-instance" p5:type="LineDetails"> <LineNum>1</LineNum> <ItemId>Item_2321</ItemId> <ItemName>TheItemName</ItemName> </anyType> <anyType xmlns:p5="http://www.w3.org/2001/XMLSchema-instance" p5:type="LineDetails"> <LineNum>2</LineNum> <ItemId>Item_2321</ItemId> <ItemName>TheItemName</ItemName> </anyType> </LineDetails> </LineColletion>
期望输出
<LineColletion> <LineDetails> <LineNum>1</LineNum> <ItemId>Item_2321</ItemId> <ItemName>TheItemName</ItemName> </LineDetails> <LineDetails> <LineNum>2</LineNum> <ItemId>Item_232100000</ItemId> <ItemName>TheItemName0</ItemName> </LineDetails> <LineDetails> <LineNum>3</LineNum> <ItemId>Item_23217777</ItemId> <ItemName>TheItemName7</ItemName> </LineDetails> </LineColletion>
解决方法
核心问题有两个:
LineDetails类不应继承ArrayList:它只是单个行数据的实体类,不需要继承集合类型,否则序列化时会被识别为集合而非普通对象。LineCollection中的LineDetails属性需用[XmlElement]替代[XmlArray]:[XmlArray]会生成包裹数组的父节点,而我们需要多个LineDetails节点直接作为LineCollection的子节点。
修改后的代码如下:
[XmlType(TypeName = "LineCollection")] public class LineCollection { public String LineCount { get; set; } // 使用XmlElement标记,指定每个集合元素的节点名称 [XmlElement(ElementName = "LineDetails")] public ArrayList LineDetails { get; set; } } // 移除ArrayList继承,改为普通实体类 public class LineDetails { public String LineNum { get; set; } public String ItemId { get; set; } public String ItemName { get; set; } //... 其他字符串字段 } // 以下代码保持不变 public class Utf8StringWriter : StringWriter { public override Encoding Encoding => new UTF8Encoding(false); } public string Serialize() { var xmlserializer = new XmlSerializer(this.GetType(), new Type[] { typeof(LineDetails) }); var utf8StringWriter = new Utf8StringWriter(); var xns = new XmlSerializerNamespaces(); xns.Add(string.Empty, string.Empty); using (var writer = XmlWriter.Create(utf8StringWriter)) { xmlserializer.Serialize(writer, this, xns); return utf8StringWriter.ToString(); } }
修改说明:
- 去掉
LineDetails的ArrayList继承后,XmlSerializer会将其识别为普通可序列化对象,不再生成anyType节点。 [XmlElement("LineDetails")]告知XmlSerializer:ArrayList中的每个元素都序列化为<LineDetails>节点,直接作为LineCollection的子节点,避免了不必要的嵌套。
内容的提问来源于stack exchange,提问作者Tweene
相关产品推荐
相关产品推荐

