不修改C# XSD类,为XML序列化添加前缀及xsi:schemaLocation
解决方案:不修改XSD类添加xsi:schemaLocation属性
你需要在不改动自动生成的XSD类的前提下,给XML根元素追加xsi:schemaLocation属性,这里有两种可靠的实现方式:
方法1:序列化后修改XML文档
这种方法先按原逻辑完成序列化,再通过XML文档操作给根元素添加目标属性,逻辑简单易维护:
public static string XmlNamespaceWithSchemaLocation<T>(T entity) where T : class { XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; settings.OmitXmlDeclaration = true; using (StringWriter sw = new StringWriter()) using (XmlWriter writer = XmlWriter.Create(sw, settings)) { XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("agrlib", "http://services.agresso.com/schema/ABWSchemaLib/2011/11/14"); ns.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance"); XmlSerializer xser = new XmlSerializer(typeof(T)); xser.Serialize(writer, entity, ns); // 加载序列化结果并添加schemaLocation属性 var doc = XDocument.Parse(sw.ToString()); var rootElement = doc.Root; if (rootElement != null) { // 注意要使用xsi的命名空间来创建属性 var xsiNamespace = XNamespace.Get("http://www.w3.org/2001/XMLSchema-instance"); rootElement.Add(new XAttribute(xsiNamespace + "schemaLocation", "http://services.agresso.com/schema/ABWInvoice/2011/11/14")); } return doc.ToString(); } }
方法2:手动写入根元素,序列化内部内容
这种方法直接控制XmlWriter生成根元素(包含所有命名空间和schemaLocation),再序列化实体的内部节点,性能更优(避免XML解析开销):
public static string XmlNamespaceWithSchemaLocation<T>(T entity) where T : class { XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; settings.OmitXmlDeclaration = true; using (StringWriter sw = new StringWriter()) using (XmlWriter writer = XmlWriter.Create(sw, settings)) { // 定义所有需要的命名空间常量 const string DefaultNamespace = "http://services.agresso.com/schema/ABWInvoice/2011/11/14"; const string AgrlibNamespace = "http://services.agresso.com/schema/ABWSchemaLib/2011/11/14"; const string XsiNamespace = "http://www.w3.org/2001/XMLSchema-instance"; // 手动写出根元素,包含所有命名空间和schemaLocation属性 writer.WriteStartElement("ABWInvoice", DefaultNamespace); writer.WriteAttributeString("xmlns", "agrlib", null, AgrlibNamespace); writer.WriteAttributeString("xmlns", "xsi", null, XsiNamespace); writer.WriteAttributeString("schemaLocation", XsiNamespace, "http://services.agresso.com/schema/ABWInvoice/2011/11/14"); // 序列化实体的内部内容(跳过根元素) XmlSerializer serializer = new XmlSerializer(typeof(T), DefaultNamespace); XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("", DefaultNamespace); // 绑定默认命名空间,避免多余声明 ns.Add("agrlib", AgrlibNamespace); serializer.Serialize(writer, entity, ns); // 闭合根元素 writer.WriteEndElement(); writer.Flush(); return sw.ToString(); } }
关键说明
两种方法都不需要修改自动生成的XSD类:
- 方法1通过后处理XML文档实现属性追加,逻辑直观,适合小体量XML场景
- 方法2通过手动控制根元素生成,直接序列化内部节点,性能更优,适合大型XML场景
内容的提问来源于stack exchange,提问作者BOR15K
相关产品推荐
相关产品推荐

