在 XML 序列化期间删除命名空间

本文关键字:删除 命名空间 XML 序列化 | 更新日期: 2023-09-27 17:56:38

给定此通用序列化代码:

public virtual string Serialize(System.Text.Encoding encoding)
{
 System.IO.StreamReader streamReader = null;
 System.IO.MemoryStream memoryStream = null;
 memoryStream = new System.IO.MemoryStream();
 System.Xml.XmlWriterSettings xmlWriterSettings = new System.Xml.XmlWriterSettings();
 xmlWriterSettings.Encoding = encoding;
 System.Xml.XmlWriter xmlWriter = XmlWriter.Create(memoryStream, xmlWriterSettings);
 Serializer.Serialize(xmlWriter, this);
 memoryStream.Seek(0, System.IO.SeekOrigin.Begin);
 streamReader = new System.IO.StreamReader(memoryStream);
 return streamReader.ReadToEnd();
}

和这个对象(来自xsd2code):

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.225")]
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "Com.Foo.Request")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "Com.Foo.Request", IsNullable = false)]
public partial class REQUEST_GROUP
{
 [EditorBrowsable(EditorBrowsableState.Never)]
 private List<REQUESTING_PARTY> rEQUESTING_PARTYField;
 [EditorBrowsable(EditorBrowsableState.Never)]
 private RECEIVING_PARTY rECEIVING_PARTYField;
 [EditorBrowsable(EditorBrowsableState.Never)]
 private SUBMITTING_PARTY sUBMITTING_PARTYField;
 [EditorBrowsable(EditorBrowsableState.Never)]
 private REQUEST rEQUESTField;
 [EditorBrowsable(EditorBrowsableState.Never)]
 private string iDField;
 public REQUEST_GROUP()
 {
  this.rEQUESTField = new REQUEST();
  this.sUBMITTING_PARTYField = new SUBMITTING_PARTY();
  this.rECEIVING_PARTYField = new RECEIVING_PARTY();
  this.rEQUESTING_PARTYField = new List<REQUESTING_PARTY>();
  this.IDField = "2.1";
 }
}

使用 utf-8 编码的序列化输出:

<?xml version="1.0" encoding="utf-8"?> <REQUEST_GROUP xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" ID="2.1" xmlns="Com.Foo.Request"> <RECEIVING_PARTY /> <SUBMITTING_PARTY /> <REQUEST LoginAccountIdentifier="xxx" LoginAccountPassword="yyy" _RecordIdentifier="" _JobIdentifier=""> <REQUESTDATA> <PROPERTY_INFORMATION_REQUEST _SpecialInstructionsDescription="" _ActionType="Submit"> <_DATA_PRODUCT _ShortSubjectReport="Y" /> <_PROPERTY_CRITERIA _City="Sunshine City" _StreetAddress2="" _StreetAddress="123 Main Street" _State="CA" _PostalCode="12345"> <PARSED_STREET_ADDRESS /> </_PROPERTY_CRITERIA> <_SEARCH_CRITERIA /> <_RESPONSE_CRITERIA /> </PROPERTY_INFORMATION_REQUEST> </REQUESTDATA> </REQUEST> </REQUEST_GROUP>

编辑问题 1:如何以这种方式修饰类,或操作序列化程序以在处理过程中删除REQUEST_GROUP节点中的所有命名空间,而不是使用 xslt 或正则表达式进行后处理。

问题2:如果您也可以添加文档类型,则为奖励点。

谢谢。

在 XML 序列化期间删除命名空间

您可以像这样删除命名空间:

XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add(string.Empty, string.Empty);
ns.Add(string.Empty, "Com.Foo.Request");
Serializer.Serialize(xmlWriter, this, ns);

至于添加 doctype,我知道可以创建自定义XmlWriter并使用调用 WriteDocType 的方法覆盖WriteStartDocument,但我有点希望其他人知道比这更简单的方法。

编辑:顺便说一下,我强烈建议使用using

using(System.Xml.XmlWriter xmlWriter = XmlWriter.Create(etc.))
{
  // use it here.
}

它通过在块结束时调用 Dispose 方法来自动处理流的整理。

如果您只想删除命名空间别名,那么如前所示,您可以使用 XmlSerializerNamespaces 强制XmlSerializer显式使用命名空间(即 xmlns="blah" ),而不是声明别名并改用别名。

但是,无论您如何处理别名,该元素的基本名称都会REQUEST_GROUPCom.Foo.Request 命名空间中。如果不表示对基础数据的中断性更改,则无法完全删除命名空间 - 即某处的某人将获得异常(由于获取了它没有预料到的数据 - 特别是根命名空间中的REQUEST_GROUP)。在 C# 术语中,这是 System.StringMy.Custom.String 之间的区别 - 当然,它们都被称为 String ,但这只是它们的本地名称。

如果要删除命名空间的所有跟踪,则实用的选择是从[XmlRoot(...)][XmlType(...)](以及示例中未显示的任何其他位置)中编辑掉Namespace=...条目。

如果类型不受控制,您也可以在运行时使用 XmlAttributeOverrides 执行此操作 - 但需要注意:如果使用XmlAttributeOverrides创建XmlSerializer,则必须缓存并重用它 - 否则您的AppDomain将泄漏(在此模式下,它会根据序列化程序动态创建程序集,并且无法卸载程序集)。