2012-03-29 14 views
2

この質問は以前に聞かれましたが、答えがうまくいきません:XMLに名前空間がない場合、XmlRoot名前空間で装飾されたクラスを逆シリアル化する方法はありますか?

XMLをデシリアライズしようとすると本当に問題が発生しています。私は似たような投稿をたくさん読んだが、これを解決することはできない。ここで

私がデシリアライズしようとしているXML

<register-account success="false"> 
    <user-name>xxxxx</user-name> 
    <password>fghgh</password> 
    <email>[email protected]</email> 
</register-account> 

クラスです:

[Serializable, XmlRoot(ElementName = "register-account", Namespace = "MyNamespace")] 
[XmlType("register-account")] 
public class RegisterAccountResponse 
{ 
    [XmlAttribute("success")] 
    public bool Success { get; set; } 

    /// <summary> 
    /// Gets or sets the Tennant email address 
    /// </summary> 
    [XmlElement("email")] 
    public string Email { get; set; } 

    /// <summary> 
    /// Gets or sets the tennant password 
    /// </summary> 
    [XmlElement("password")] 
    public string Password { get; set; } 

    /// <summary> 
    /// Gets or sets the Tennant username 
    /// </summary> 
    [XmlElement("user-name")] 
    public string Username { get; set; } 
} 

デシリアライズ方法

public static T Deserialize<T>(string data) where T : class 
{ 

    var ser = new XmlSerializer(typeof(T)); 

    using (var sr = new StringReader(data)) 
    { 
     return (T)ser.Deserialize(sr); 
    } 
} 

デシリアライズメソッド呼び出し

var data = Helper.Deserialize<RegisterAccountResponse>(xml); 

例外:

XMLドキュメント(1、2)に誤りがあります。 ---> System.InvalidOperationException:期待されていませんでした。 Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderData.Read5_data()

内部例外で、次のように:

質問への答えは、クラスから名前空間を削除することでした
<register-account xmlns=''> was not expected. 

(削除Namespace = "MyNamespace")。ただし、クラスはxsd.exeを使用して自動生成される非常に大きなライブラリの一部です。私は、生成されたクラスの中で何も変更したくありません。クラスを変更することなくこの問題を解決するにはまだ離れていますか?

+0

それがXML全体であるとすると、表示したXMLには名前空間(xmlns宣言なし)がありません。したがって、クラスのシリアライゼーションパラメータから削除することは意味があります。そうでない場合は、XSDを介してクラスを再生成し、ネームスペースなしでクラスを生成させます。 – Reddog

+0

XSD.exeがクラスと一緒にクラスを生成することをサポートしているとは思いません。 –

答えて

-2

もしあなたがコードを変更できない、または変更したくなければ、xsltを使ってxmlを変換して必要な場所にいくつかの名前空間を追加する必要があります。デシリアライザがドキュメントをデシリアライズするのに役立ちます。

よろしくお願いいたします。

+0

デシリアライズコードを変更できませんか?または入力XMLを変更して名前空間を挿入しますか?どのように私はそれについて行うことができます –

+0

私はクラスの属性として記述されている名前空間の宣言を避けることができるようには思わない。ただし、XSLTを使用してxmlを変更することはできます。 xml.http://support.microsoft.com/kb/307322/en-us/またはhttp://stackoverflow.com/questions/144713/add-japan.htmlをスタイル付けするためのマークアップ言語であるため、XSLTのいくつかの調査が必要な場合があります。 a-namespace-to-elements-using-xslt –

+0

この回答は間違っています。 xsltが必要なのは当てはまりません。 @Amine - あなたはあなたが望むことをすることができます。私の答えを見てください。 http://stackoverflow.com/a/10020010/48082 – Cheeso

5

この問題を解決するには、クラスを変更する必要はありませんか?

はい。

.NETには、この目的のために設計されたXmlAttributeOverridesというクラスがあります。 実行時にコードに存在する属性を上書きできます。

次の変更されたデシリアライズユーティリティメソッドは、指定したXMLを使用して、指定したクラスのインスタンスを正しく変更しなくても、そのインスタンスを正しくデシリアライズします。 XSLTもありません。

public static T DeserializeWithNoRootNamespace<T>(string data) 
     where T : class 
    { 

     /* Each overridden field, property, or type requires 
      an XmlAttributes object. We are overriding the serialization 
      of the XmlRoot on the type, so we need one XmlAttributes collection. */ 
     var attrs = new XmlAttributes(); 

     /* Create an XmlRootAttribute to override the XmlRoot in-line attr. 
      The override will use no namespace. */ 
     var root = new XmlRootAttribute("register-account"); 

     // set the XmlRoot on the XmlAttributes collection. 
     attrs.XmlRoot= root; 

     // Create the XmlAttributeOverrides object. 
     var o = new XmlAttributeOverrides(); 

     /* Map the attributes collection to the thing being 
      overriden (the class). */ 
     o.Add(typeof(T), attrs); 

     // create the serializer, specifying the overrides to use 
     var ser = new XmlSerializer(typeof(T), o); 

     using (var sr = new StringReader(data)) 
     { 
      return (T)ser.Deserialize(sr); 
     } 
    } 

上記のコードは、XmlRoot属性をオーバーライドします。 XmlAttributeOverridesは、クラスの任意の部分のxml-serialization属性をデシリアライズするのに十分な一般的なものです。それはあなたの場合には必要ではありませんでした。

More information.

PS:[Serializable]はあなたのクラスを飾るしている属性は、必要とされていません。 XML直列化と逆シリアル化されるクラスに適用するのはよくあるエラーです。しかしそれは外的であり、したがって間違っています。

+0

このコードでは、このコードを使用して、xmlの名前空間をオーバーライドすることができました。つまり、スキーマに名前空間が1つありますが、何らかの理由でxmlファイルを読み込む必要があります。 しかし、これで私はファイルから名前空間を読み込み、それをデシリアライズでオーバーライドし、ファイルから要素ごとに逆シリアル化することができました。 しかし、ランタイムコード生成の多くは進行中です: 'test.vshost.exe'(CLR v4.0.30319:test.vshost.exe): 'Microsoft.GeneratedCode'が読み込まれました。 それは地獄のように遅いです。これを行うには他の方法がありますか? – neslekkiM