2009-12-05 50 views
41

如何從使用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); 
    } 
} 

回答

45

你必須標記你想用序列化類:

[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

11

如果你有你的心臟上繞過默認行爲(我目前做的)設置,您可以創建繞過寫的命名空間的自定義的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

相關問題