要彻底移除XmlSerializer生成的xmlns:xsi和xmlns:xsd声明,需使用XmlSerializerNamespaces并调用Add("", "")覆盖默认命名空间映射,同时确保所有Xml特性未设置Namespace属性。
在使用 XmlSerializer 序列化对象为 XML 时,.NET 默认会自动添加 xmlns:xsi 和 xmlns:xsd 等命名空间声明,即使你没显式定义任何命名空间。这些声明对某些系统(如轻量级 API、遗留系统或严格校验的 XML Schema)来说是冗余甚至不兼容的。要彻底移除它们,关键不是“过滤”输出,而是**从序列化源头控制命名空间的注入行为**——XmlSerializerNamespaces 就是为此设计的。
XmlSerializerNamespaces 本身不“移除”已有命名空间,而是**覆盖**序列化器默认使用的命名空间映射。它的核心用法是传入一个包含空前缀映射的实例:
XmlSerializerNamespaces 实例.Add("", "") —— 第一个空字符串表示“默认命名空间前缀”,第二个空字符串表示“不绑定到任何 URI”XmlSerializer.Serialize() 的重载方法这样,序列化器就不会再自动添加 xsi 和 xsd 声明,
因为你的命名空间表已显式接管了默认行为。
在较新版本中,更直接的方式是使用 XmlWriterSettings 配合 XmlSerializer,尤其当你要完全跳过类型信息序列化时:
XmlWriterSettings.OmitXmlDeclaration = false(按需)XmlWriterSettings.NamespaceHandling = NamespaceHandling.OmitDuplicates(辅助去重)XmlSerializer.Serialize(XmlWriter, object, XmlSerializerNamespaces) 并传入 new XmlSerializerNamespaces(new[] { new XmlQualifiedName("", "") })
注意:XmlSerializer 不支持像 XmlWriterSettings 那样全局禁用 xsi/xsd,所以必须配合 XmlSerializerNamespaces 显式覆盖。
即使用了 XmlSerializerNamespaces,如果类成员上写了类似 [XmlElement(Namespace = "http://example.com")] 或 [XmlRoot(Namespace = "urn:myapp")],序列化器仍会生成对应命名空间前缀和声明。要真正“无命名空间”,需确保:
[Xml*] 特性中 Namespace 属性未设置,或显式设为 ""
[XmlRoot],检查其 Namespace 是否为空字符串序列化后不要只看字符串是否含 xmlns:,而应检查实际 XML 结构:
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type 或 xsi:nil 属性(除非你主动写入)xmlns="" 是允许的,表示“此元素及其子元素属于无命名空间”,不是冗余项)可将结果加载进 XDocument 并检查 Root.Name.Namespace 是否为 XNamespace.None 来确认。