使用DataContractSerializer序列化没有名称空间的对象

如何从使用DataContractSerializer序列化的对象的XML表示中删除XML名称空间?

该对象需要被序列化为非常简单的输出XML。

  • 最新最好的 – 使用.Net 4 beta 2
  • 该对象将永远不需要反序列化。
  • XML不应该有任何xmlns:… namespace refs
  • 任何exception和ISubObject的子types都需要被支持。
  • 改变原始的对象将是非常困难的。

目的:

[Serializable] class MyObj { string str; Exception ex; ISubObject subobj; } 

需要序列化成:

 <xml> <str>...</str> <ex i:nil="true" /> <subobj i:type="Abc"> <AbcProp1>...</AbcProp1> <AbcProp2>...</AbcProp2> </subobj> </xml> 

我用这个代码:

 private static string ObjectToXmlString(object obj) { if (obj == null) throw new ArgumentNullException("obj"); var serializer = new DataContractSerializer( obj.GetType(), null, Int32.MaxValue, false, false, null, new AllowAllContractResolver()); var sb = new StringBuilder(); using (var xw = XmlWriter.Create(sb, new XmlWriterSettings { OmitXmlDeclaration = true, NamespaceHandling = NamespaceHandling.OmitDuplicates, Indent = true })) { serializer.WriteObject(xw, obj); xw.Flush(); return sb.ToString(); } } 

从这篇文章我采用了一个DataContractResolver,以便不必声明子types:

 public class AllowAllContractResolver : DataContractResolver { public override bool TryResolveType(Type dataContractType, Type declaredType, DataContractResolver knownTypeResolver, out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace) { if (!knownTypeResolver.TryResolveType(dataContractType, declaredType, null, out typeName, out typeNamespace)) { var dictionary = new XmlDictionary(); typeName = dictionary.Add(dataContractType.FullName); typeNamespace = dictionary.Add(dataContractType.Assembly.FullName); } return true; } public override Type ResolveName(string typeName, string typeNamespace, Type declaredType, DataContractResolver knownTypeResolver) { return knownTypeResolver.ResolveName(typeName, typeNamespace, declaredType, null) ?? Type.GetType(typeName + ", " + typeNamespace); } } 

您需要标记要序列化的类:

 [DataContract(Namespace="")] 

在这种情况下,数据协定序列化程序不会为您的序列化对象使用任何名称空间。

渣子

如果你已经绕过了默认的行为(就像我现在所做的那样),那么你可以创build一个绕过写命名空间的自定义XmlWriter。

 using System.IO; using System.Xml; public class MyXmlTextWriter : XmlTextWriter { public MyXmlTextWriter(Stream stream) : base(stream, null) { } public override void WriteStartElement(string prefix, string localName, string ns) { base.WriteStartElement(null, localName, ""); } } 

然后在你的作家消费者,如下所示:

 var xmlDoc = new XmlDocument(); DataContractSerializer serializer = new DataContractSerializer(obj.GetType()); using (var ms = new MemoryStream()) { using (var writer = new MyXmlTextWriter(ms)) { serializer.WriteObject(writer, obj); writer.Flush(); ms.Seek(0L, SeekOrigin.Begin); xmlDoc.Load(ms); } } 

而输出将会有名字空间的声明,但是不会有这样的用法:

 <TestObject xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <Items xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays"> <string>Item1</string> <string>Item2</string> </Items> </TestObject>