2009-12-05 28 views
41

DataContractSerializerを使用してシリアル化されたオブジェクトのXML表現からXML名前空間を削除するにはどうすればよいですか?DataContractSerializerを使用した名前空間のないオブジェクトのシリアル化

このオブジェクトは、非常に単純な出力XMLにシリアライズする必要があります。最大

  • 最新& - ネット4のベータ2
  • オブジェクトを使用して直列化復元する必要はありません。
  • xmlns:... namespace refs
  • ExceptionおよびISubObjectのサブタイプをサポートする必要があります。
  • 元のオブジェクトを変更することは非常に困難です。

オブジェクト:

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

のにシリアライズする必要があります:何のサブタイプが持たないように、私はDataContractResolverを採用this articleから

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

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

私はこのコードを使用宣言する:

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

+0

いいえ、申し訳ありません - 既存の名前空間を削除することはできません。オブジェクト自体に名前空間を指定する必要があります。 –

+1

これはできません - すべてのシステムタイプはどうですか? MSはすべてのタイプが変更可能であるとは期待できませんが、別の方法が必要です:( – Yurik

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

XmlWriterと比較してコンストラクタを介して設定を渡すのに問題が発生するXmlTextWriter – Kelmen

+0

@Kelmen How So? – leat

+1

宣言を取り除くために 'WriteStartAttribute'をオーバーライドしたくないのですか? –

関連する問題