在 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:如果您也可以添加文档类型,则为奖励点。
谢谢。
您可以像这样删除命名空间:
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_GROUP
在 Com.Foo.Request
命名空间中。如果不表示对基础数据的中断性更改,则无法完全删除命名空间 - 即某处的某人将获得异常(由于获取了它没有预料到的数据 - 特别是根命名空间中的REQUEST_GROUP
)。在 C# 术语中,这是 System.String
和 My.Custom.String
之间的区别 - 当然,它们都被称为 String
,但这只是它们的本地名称。
如果要删除命名空间的所有跟踪,则实用的选择是从[XmlRoot(...)]
和[XmlType(...)]
(以及示例中未显示的任何其他位置)中编辑掉Namespace=...
条目。
如果类型不受控制,您也可以在运行时使用 XmlAttributeOverrides
执行此操作 - 但需要注意:如果使用XmlAttributeOverrides
创建XmlSerializer
,则必须缓存并重用它 - 否则您的AppDomain
将泄漏(在此模式下,它会根据序列化程序动态创建程序集,并且无法卸载程序集)。