2012-03-29 66 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 2012-03-29 18:14:12

+0

我不認爲XSD.exe支持生成沒有名稱空間屬性的類。 – 2012-03-29 18:34:14

回答

-2

那麼,如果你不能或不想改變代碼,那麼你必須xslt轉換你的xml以在需要的地方添加一些命名空間。這將有助於解串器反序列化文檔。

問候。

+0

我無法更改反序列化代碼嗎?或者更改傳入的xml以注入命名空間?我怎麼能這樣做 – 2012-03-29 18:21:57

+0

我不這麼認爲你可以避免已經寫入屬性類的名稱空間聲明。但您可以使用XSLT更改包含的xml。它可能需要對XSLT進行一些研究,因爲它是一種標記語言,用於設置xml.http://support.microsoft.com/kb/307322/en-us/或http://stackoverflow.com/questions/144713/add- a-namespace-to-elements-using-xslt – 2012-03-30 05:01:01

+0

這個答案是不正確的。 xslt是不需要的。 @Amine - 你可以做你想做的。看到我的答案。 http://stackoverflow.com/a/10020010/48082 – Cheeso 2012-04-04 22:23:51

5

有沒有需要修改這個問題而無需修改類?

是的。

.NET有一個名爲XmlAttributeOverrides的類,它是專門爲此目的而設計的。 您可以在運行時覆蓋代碼中存在的屬性。

以下修改的Deserialize實用程序方法將使用您提供的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序列化屬性。你的情況沒有必要。

More information.

PS:[Serializable]屬性你裝飾你的類,則不需要。這是一個常見的錯誤,將其應用於將被XML序列化和反序列化的類。但它是無關的,因此是錯誤的。

+0

這是一個interresting,有了這段代碼,我設法覆蓋了我的XML命名空間,也就是說,我的模式有一個名稱空間,但由於某種原因,我必須讀取的XML文件具有不同的供應商名稱空間。 但是,我可以從文件中讀取命名空間,然後在我的反序列化中覆蓋它,並從文件中按元素反序列化元素。 但是..很多運行時代碼正在進行: 'test.vshost.exe'(CLR v4.0.30319:test.vshost.exe):Loaded'Microsoft.GeneratedCode'。 而且速度很慢..有沒有其他方法可以做到這一點? – neslekkiM 2015-06-09 13:51:50