使用XmlElement特性为何破坏XML序列化?如何实现预期输出?
XML序列化时XmlElement特性导致集合容器节点消失的问题
我需要参照示例文件生成XML,发现部分节点采用camelCase而非约定的PascalCase。希望代码模型保持规范命名,但序列化时遵循已有格式。尝试使用XmlElement特性后出现异常行为:
未添加特性时的正常输出
<?xml version="1.0" encoding="utf-16"?> <Model> <Elements> <Element Name="Hello," /> <Element Name="World!" /> </Elements> </Model>
添加XmlElement特性后的异常输出
<?xml version="1.0" encoding="utf-16"?> <Model> <brokenConvention Name="Hello," /> <brokenConvention Name="World!" /> </Model>
模型代码
public class Model { //[XmlElement("brokenConvention")] // 取消注释后出现异常行为 public Element[] Elements { get; set; } } public class Element { [XmlAttribute] public string Name { get; set; } }
序列化代码
using System; using System.Threading.Tasks; using System.Xml.Serialization; using System.IO; using System.Xml; using System.Text; using System.Collections; using System.Collections.Generic; public class Program { public static void Main() { var model = new Model { Elements = new Element[] { new Element { Name = "Hello," }, new Element { Name = "World!" } } }; var xmlSerializer = new XmlSerializer(typeof(Model)); using var writer = new StringWriter(); using var xmlWriter = new XmlTextWriter(writer) { Formatting = Formatting.Indented }; xmlSerializer.Serialize(xmlWriter, model, new XmlSerializerNamespaces(new [] { XmlQualifiedName.Empty })); Console.WriteLine(writer.ToString()); } }
原因解析
在集合属性上标记[XmlElement]特性时,XmlSerializer会将该集合视为无容器节点的扁平集合——直接把每个集合元素作为父节点(Model)的子节点输出,同时用特性指定的名称替换默认元素名。这就是Elements容器节点消失、直接输出brokenConvention节点的核心原因。
默认情况下,XmlSerializer会为集合属性生成一个容器节点(比如这里的Elements),再在容器内生成每个集合元素的节点(默认用元素类型名Element)。而[XmlElement]特性会覆盖这个默认逻辑,告诉序列化器不需要容器节点,直接输出元素。
正确实现方式
要保留Elements容器节点,同时修改容器内元素的名称为brokenConvention,需要配合使用[XmlArray]和[XmlArrayItem]特性:
修改后的Model类代码:
public class Model { [XmlArray("Elements")] // 指定集合容器节点的名称 [XmlArrayItem("brokenConvention")] // 指定容器内每个元素的节点名称 public Element[] Elements { get; set; } }
序列化后的预期XML输出:
<?xml version="1.0" encoding="utf-16"?> <Model> <Elements> <brokenConvention Name="Hello," /> <brokenConvention Name="World!" /> </Elements> </Model>
特性说明
[XmlArray]:用于定义集合的外层容器节点名称,这里显式指定为"Elements"(默认就是属性名,也可以省略,显式声明更清晰)。[XmlArrayItem]:用于定义容器内每个元素的节点名称,这里替换为需要的camelCase命名"brokenConvention"。
内容的提问来源于stack exchange,提问作者eriyg
相关产品推荐
相关产品推荐

