2015-10-15 135 views
2

我有XML序列化的類屬性名稱反序列化XML元素屬性

[Serializable] 
public class Item 
{ 
    [XmlElement("name")] 
    public string Name { get; set; } 
} 

,我希望它能夠反序列化XML文件,我有兩種方式:

<item> 
    <name>Name</name> 
</item> 

<item> 
    <name value="Name" /> 
</item> 

的首部作品不錯,但我應該怎麼做才能夠反序列化塞科nd也與同一班?

+0

IMO這是不可能的。您將不得不完成輸入XML文件的格式。但這是一個有趣的問題。 – niksofteng

回答

0

我找到了另一種方式來解決我的問題,只使用一個類,也許有人會覺得這有用

[Serializable] 
public class Item 
{ 
    [XmlElement("name")] 
    public NameElement NameElement { get; set; } 
} 

public class NameElement 
{ 
    [XmlAttribute("value")] 
    public string Value { get; set; } 

    [XmlText] 
    public string Text { get; set; } 

    [XmlIgnore] 
    public string Name 
    { 
     get { return String.IsNullOrEmpty(this.Value) ? this.Text : this.Value; } 
     set { this.Value = value; } 
    } 
} 

也許這不是超優雅,但它在這兩種情況下,並使用同班。

2

XML序列化屬性都工作,序列化和反序列化。如果我們假設有可能使用來自兩個不同的XML結構的反序列化實例Item屬性,那麼如何系列化應該努力 - 它應該序列化實例名元素值,或屬性?還是對兩者?這就是爲什麼你不能將兩個不同的xml結構反序列化爲單個類。使用兩個不同的類或手動反序列化它,而不使用XML序列化屬性。

+0

對,我想可能xml元素的內部文本以某種方式被轉換爲值屬性。我正在使用外部api,並根據請求獲取具有不同約定名稱元素的項目:/ – Brazol

+1

然後,對您而言,最好的解決方案是爲不同的約定創建另一個「Item2」類(當然,您應該使用更好的名稱您的請求類型之間的差異)。如果發送不同類型的請求,則反序列化對'Item2'的響應。您可以使'Item'和'Item2'實現相同的界面。因此,您的代碼的其他部分可以在不知道您傳遞的確切類型的情況下使用它。 –

0

既然你已經提到,XML數據是從外部來源的,所以很明顯你沒有超過對照。

因此,你可以按照任何如下的選項:

  1. 創建每個XML數據結構不同的類,因爲據我所知是沒有辦法控制XML反序列化使用XmlSerializer
  2. 您可以在使用XDocument自行讀取XML,克服這種限制。

如果第二個想法去,我已經創建了小控制檯應用程序來證明。

的代碼主片是如下:

MemoryStream xmlStream = new MemoryStream(Encoding.UTF8.GetBytes(xmlData)); 
XDocument doc = XDocument.Load(xmlStream); 

var records = from record in doc.Descendants("item").Descendants() 
       select new Item(!record.IsEmpty ? record.Value : record.Attribute("value").Value); 

在這裏,我使用讀取和LinqToXml檢查該元素不是空的元件,即,Value是不是空白的,然後使用Value否則讀元素的值爲Attribute

控制檯應用程序(完整代碼):

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Text; 
using System.Xml.Linq; 
using System.Xml.Serialization; 

namespace Console.TestApp 
{ 
    class Program 
    { 
     static string xmltypeFirst = @"<item> 
    <name>John</name> 
</item>"; 

     static string xmltypeSecond = @"<item> 
    <name value='Smith' /> 
</item>"; 

     static void Main(string[] args) 
     { 
      var data = xmltypeFirst; 
      var result = Deserialize(data).ToList(); 
      Console.WriteLine("Name: " + result[0].Name); 

      data = xmltypeSecond; 
      result = Deserialize(data).ToList(); 
      Console.WriteLine("Name: " + result[0].Name); 

      Console.WriteLine("Press any to key to exit.."); 
      Console.ReadLine(); 
     } 

     private static IEnumerable<Item> Deserialize(string xmlData) 
     { 
      MemoryStream xmlStream = new MemoryStream(Encoding.UTF8.GetBytes(xmlData)); 
      XDocument doc = XDocument.Load(xmlStream); 

      var records = from record in doc.Descendants("item").Descendants() 
          select new Item(!record.IsEmpty ? record.Value : record.Attribute("value").Value); 
      return records; 
     } 
    } 

    [Serializable] 
    public class Item 
    { 
     public Item(string name) 
     { 
      this.Name = name; 
     } 

     [XmlElement("name")] 
     public string Name { get; set; } 
    } 
} 

注意:要運行這個,你需要在你的項目中添加引用System.Xml.Linq.dll

參考:here

+0

不錯的想法,但我的例子只是爲了說明問題,而XML的方式更復雜,所以使用XmlDocument反序列化比使用Serializable類更多的工作。 – Brazol