如何用C#实现符合特定XML格式的读写(含XmlOverride)
用XmlSerializer重写XML根节点与移除数组层级的正确实现
我明白你要的是直接让XML输出符合预期结构——要么从类生成时去掉数组的包裹节点,要么直接序列化数组时自定义根节点名称。之前用XmlOverride没成功可能是没找对正确的配置方式,下面给你两种靠谱的实现方案:
方案一:用特性修饰类实现静态配置(适合固定结构的场景)
如果你的XML结构是固定的,直接在类上用XmlRoot和XmlElement特性就能搞定,不用复杂的Override:
修改TestXml类的定义,给根节点指定自定义名称,同时把数组字段标记为直接生成元素,而非带包裹节点:
[XmlRoot("SOME_OVERRIDDEN_NAME")] public class TestXml { // 用XmlElement代替默认的XmlArray,这样就不会生成<testXmlArray>包裹节点 [XmlElement("TestXmlElement")] public TestXmlElement[] testXmlArray = new TestXmlElement[] { new TestXmlElement(), new TestXmlElement() }; public TestXml() { } } public class TestXmlElement { [XmlAttribute] public string Name = "default"; [XmlAttribute] public ulong Value = 1; public TestXmlElement() { } }
序列化TestXml实例时,输出就会变成你要的样子:
<?xml version="1.0"?> <SOME_OVERRIDDEN_NAME> <TestXmlElement Name="default" Value="1" /> <TestXmlElement Name="default" Value="1" /> </SOME_OVERRIDDEN_NAME>
方案二:用XmlAttributeOverrides动态配置(适合需要动态修改结构的场景)
如果需要动态调整根节点名称或者数组的序列化方式(比如不同场景用不同根节点),就需要正确配置XmlAttributeOverrides。之前没成功可能是没给数组字段正确设置XmlElementAttributes,或者没处理根节点的Override:
场景1:动态修改TestXml类的序列化结构(去掉数组包裹+自定义根节点)
static void SerializeTestXmlWithOverride() { TestXml tx = new TestXml(); StreamWriter sw = new StreamWriter(@"g:\test_class_override.xml"); // 创建Override对象 XmlAttributeOverrides overrides = new XmlAttributeOverrides(); // 1. 重写TestXml的根节点名称 XmlAttributes rootAttrs = new XmlAttributes(); rootAttrs.XmlRoot = new XmlRootAttribute("SOME_OVERRIDDEN_NAME"); overrides.Add(typeof(TestXml), rootAttrs); // 2. 重写testXmlArray字段,让它直接生成元素,不带包裹节点 XmlAttributes arrayAttrs = new XmlAttributes(); // 添加XmlElementAttribute,指定元素名称 arrayAttrs.XmlElements.Add(new XmlElementAttribute("TestXmlElement")); overrides.Add(typeof(TestXml), "testXmlArray", arrayAttrs); // 用带override的XmlSerializer序列化 XmlSerializer x = new XmlSerializer(typeof(TestXml), overrides); x.Serialize(sw.BaseStream, tx); sw.Close(); }
场景2:动态修改数组的根节点名称(序列化TestXmlElement[]时自定义根)
static void SerializeArrayWithOverride() { TestXmlElement[] txa = new TestXmlElement[] { new TestXmlElement(), new TestXmlElement() }; StreamWriter sw = new StreamWriter(@"g:\test_array_override.xml"); // 序列化数组时,要给数组类型指定XmlRoot XmlAttributeOverrides overrides = new XmlAttributeOverrides(); XmlAttributes arrayRootAttrs = new XmlAttributes(); arrayRootAttrs.XmlRoot = new XmlRootAttribute("SOME_OVERRIDDEN_NAME"); // 注意:数组的类型是TestXmlElement[],所以要传入typeof(TestXmlElement[]) overrides.Add(typeof(TestXmlElement[]), arrayRootAttrs); XmlSerializer x = new XmlSerializer(typeof(TestXmlElement[]), overrides); x.Serialize(sw.BaseStream, txa); sw.Close(); }
运行这两个方法后,输出的XML就完全符合你的预期了。
关键注意点
- 用
XmlAttributeOverrides时,一定要确保类型和成员名称匹配,比如给数组字段添加Override时,成员名称要和类里的字段名完全一致(这里是testXmlArray) - 序列化数组时,Override的是数组的类型(
TestXmlElement[]),而不是元素类型 - 如果用特性的方式,
XmlElement特性会让数组直接生成子元素,而默认的XmlArray会生成包裹节点,这是去掉<testXmlArray>的核心
内容的提问来源于stack exchange,提问作者morteza
相关产品推荐
相关产品推荐

