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

问题描述:

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

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

  • 最新&最大 - 使用.NET 4.0 Beta 2的
  • 对象将永远不需要反序列化。
  • XML不应该有任何xmlns:... namespace refs
  • 需要支持Exception和ISubObject的任何子类型。
  • 改变原始物体将会非常困难。

对象:

[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(); 
    } 
} 

this article我收养了一个DataContractResolver所以没有亚型有将被宣布为:

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="")] 

在这种情况下,数据合同序列化器将不使用任何命名空间为您的序列化对象。

马克

+0

一些子对象不在我的控制之下,我无法改变它们。是否可以在不改变对象的情况下做到这一点? – Yurik 2009-12-05 10:36:16

+0

不,对不起 - 你不能移除现有的命名空间 - 你必须能够在对象本身上指定命名空间。 – 2009-12-05 11:17:25

+1

那不可能 - 所有的系统类型呢? MS不能期望所有类型都是可修改的,必须有其他的一些方法:( – Yurik 2009-12-05 13:04:09

如果你有你的心脏上绕过默认行为(我目前做的)设置,您可以创建绕过写的命名空间的自定义的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> 
+0

XmlTextWriter给我一个问题,通过构造函数传递设置与XmlWriter比较 – Kelmen 2015-10-16 10:56:54

+0

@Kelmen怎么样? – leat 2015-10-18 07:22:52

+1

您是否不想重写'WriteStartAttribute'以摆脱声明? – 2016-01-18 17:26:15