2014-01-20 27 views
1

我正在重構一些解析預先存在的XML文件(其中我沒有創建並且無法控制設計)的代碼。目前,我將XML讀入XDocument並執行各種linq查詢來提取數據。我想要做的是使用XML 反序列化來爲我工作。反序列化嚴重設計的XML

我想這樣做是因爲代碼的其他部分使用了XML反序列化(並且我想使代碼在操作中保持一致),並且更好地記錄了此XML文件的結構。

但深埋7層內部的XML是如下數據:

<objects> 
    <object name="Fred"> 
    <type> 
     <BOOL/> 
    </type> 
    </object> 
    <object name="Barney"> 
    <type> 
     <WORD/> 
    </type> 
    </object> 
    <object name="Wilma"> 
    <type> 
     <derived name="Special1"/> 
    </type> 
    </object> 
    <object name="Betty"> 
    <type> 
     <array> 
     <dimension upper="3" lower="0"/> 
     <INT/> 
     </array> 
    </type> 
    </object> 
    <object name="Dino"> 
    <type> 
     <array> 
     <dimension upper="3" lower="0"/> 
     <derived name="Special2"/> 
     </array> 
    </type> 
    </object> 
</objects> 

直到此時我已經能夠逃脫定義簡單類的XML模式。

但隨着object數據Type元素的值被表達爲子元素(而不是一個屬性),選擇那些是有嚴格規定的類型(EG BOOLWORD)。在用戶定義類型的情況下,使用不同的子元素,最終的類型名稱在該子元素的name屬性中定義(EG Special1Special2)。 (另請注意,我不/不能有標準類型的完整列表。)

(請注意,儘管該XML設計很糟糕,這是不畸形

然後,事情當對象是一個數組並且該類型被包裝在一個array元素中時,會變得更加混亂。

最終我想要的type(既包括標準和用戶定義的)和array dimensions作爲object類(以及指示時遇到derived類型)的屬性。

我不知道如何構建一個可以從這個XML反序列化的類,但是我懷疑我需要深入研究一下這個類的一些自定義XML處理(或者可能是XSLT轉換?)。

+2

手動序列化似乎更優化,然後嘗試重新設計一些東西,以便能夠使用'XmlSerializer'。因爲你可能不得不用屬性來調整它,或者改變類型本身(動態創建它?)。那麼爲什麼不手工手工閱讀/保存? – Sinatr

+0

@Sinatr我不是在追求你的意思,所以你可以擴展你的評論? –

+0

XML是否在文檔的頂部有一個XML模式(XSD或DTD)?您需要在一天結束時提供一個XSD,以自動從複雜對象序列化/反序列化。 –

回答

1

爲什麼to use XML deserialization to do all that work for me

你已經手動完成了,你爲什麼要做額外的工作?額外的工作將是:許多班級,通過attributes有很多替換(例如<type>)。

或者,繼續我的例子,如果你想here


Here是反序列化,你可以看到,這是完全一樣的。

只是爲了方便起見,我會在這裏郵編:

using System; 
using System.IO; 
using System.Text; 
using System.Xml; 
using System.Xml.Serialization; 

public class Program 
{ 
    [Serializable] 
    [XmlRoot("Objects")] 
    public class MyXml 
    { 
     [XmlElement("Object")] 
     public MyObject[] MyObjects; 
    } 


    [Serializable] 
    [XmlRoot("Object")] 
    public class MyObject 
    { 
     [XmlAttribute("name")] 
     public string MyName; 
     [XmlElement("Type")] 
     public object MyType; 
    } 

    public static void Main() 
    { 
     var data = new MyXml(); 
     data.MyObjects = new MyObject[] {new MyObject() { MyName = "Fred"}, new MyObject()}; 
     using (var stream = new MemoryStream()) 
     { 
      var space = new XmlSerializerNamespaces(); 
      space.Add("", ""); 
      var serializer = new XmlSerializer(data.GetType()); 
      serializer.Serialize(stream, data, space); 
      var text = Encoding.Default.GetString(stream.ToArray()); 
      foreach(var line in text.Split(System.Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries)) 
      Console.WriteLine(line); 

      stream.Seek(0, SeekOrigin.Begin); 
      var test = serializer.Deserialize(stream) as MyXml; 
      Console.WriteLine("\nTest: " + test.MyObjects[0].MyName); 

     } 
    } 
} 
+0

我想要使用XML反序列化來部分地幫助自我記錄XML文件,並且部分地使代碼庫與其他使用相同方法的部分在不同的XML文件上保持一致。我已經知道如何做直接的XML序列化,並且我的示例'object'在大約22個類的層次結構中已經有7層深。但從我看到你的例子似乎並沒有解決我的問題,如何DE序列化'類型' –

+0

請參閱編輯....... – Sinatr

+0

這並不能解決我的問題,如何統一提取指定爲''''' –

0

因爲它已經說了,我沒有看到任何其他替代其他比手動處理它,因爲你已經在做。

如果您(可能也不是XML擁有者)不知道XML將如何使用(從架構角度而言),您認爲爲什麼有些技術可以自動理解?

所以,我認爲你的手工操作是正確的。

+0

因爲我是一個XML序列化的相對新手,所以我希望能發現一種我忽略的技術。例如一個鉤子,可以手動處理這個愚蠢的事情,而不必手動處理整個文件。 –

+0

問題是,如果你的設計不好(說:你的XML沒有經過DTD或模式的優雅處理),你總會發現你無法克服的麻煩。我建議你嘗試與XML的所有者交談以構建一個模式,還有一些工具可以基於XML構建模式。通過構建一個模式,你將能夠優雅地反序列化它,但是,當你將一個字符串(其類型在字符串中定義)轉換爲一個真正的類型時,仍然需要將這些東西解析爲Bool或dword 。然後你需要手動做事情。 –

+0

關於從xml自動生成模式(XSD文件)的工具,您可以檢查Altova XMLSpy。不過,這是一種付費工具。我相信你會找到任何開源工具,或類似的東西在網絡上。 –