You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:24:56