2010-07-27 81 views
1

我正在開發一個系統,通過Exchange Web服務從電子郵件中提取XML附件,並通過我創建的自定義DAL對象將它們輸入到數據庫中。解析XML文件-options?

我已經設法提取XML附件並將其準備好作爲流...他們的問題是如何解析此流並填充DAL對象。

我可以創建一個XMLTextReader並遍歷每個元素。除此之外,我沒有看到任何問題,我懷疑有一種很滑的方式。閱讀器似乎將開始標籤,標籤的內容和結束標籤視爲不同的元素(使用reader.NodeType)。我預計我的價值被認爲是一個元素而不是三個。就像我說的,我可以解決這個問題,但我相信肯定有更好的方法。

我遇到了使用XML序列化器(對我來說是全新的)的想法,但快速查看錶明這些不能處理ArrayLists和List(我正在使用List)。

再一次,我是LINQ的新手,但也提到了LINQ到XML,但我看過的例子看起來相當複雜 - 儘管我只是缺乏熟悉感。

基本上,我不想要一個封閉的系統,但我不想使用任何複雜的技術與學習曲線,只是因爲它'很酷'。

將此XML/Stream轉換爲我的DAL對象的最簡單和最有效的方法是什麼?

XML示例:

<?xml version="1.0" encoding="UTF-8"?> 
<enquiry> 
    <enquiryno>100001</enquiryno> 
    <companyname>myco</companyname> 
    <typeofbusiness>dunno</typeofbusiness> 
    <companyregno>ABC123</companyregno> 
    <postcode>12345</postcode> 
    <contactemail>[email protected]</contactemail> 
    <firstname>My</firstname> 
    <lastname>Name</lastname> 
    <vehicles> 
     <vehicle> 
      <vehiclereg>54321</vehiclereg> 
      <vehicletype>Car</vehicletype> 
      <vehiclemake>Ford</vehiclemake> 
      <cabtype>n/a</cabtype> 
      <powerbhp>130</powerbhp> 
      <registrationdate>01/01/2003</registrationdate> 
     </vehicle> 
    </vehicles> 
</enquiry> 

更新1: 我試圖反序列化的基礎上,格雷厄姆的例子。我認爲我已經設置了序列化的DAL,包括爲每個屬性指定[XmlElement("whatever")]。我已經嘗試使用反序列化如下:

SalesEnquiry enquiry = null; 
XmlSerializer serializer = new XmlSerializer(typeof(SalesEnquiry)); 
enquiry = (SalesEnquiry)serializer.Deserialize(stream); 

但是,我得到一個異常:「There is an error in XML document (2, 2)」。設置InnerException指出{"<enquiry xmlns=''> was not expected."}

結論(更新):

我以前的問題是一個事實,即XML文件(查詢)中的元素=類(SalesEnquiry)這個名字!而不是該類的[XmlElement]屬性,我們需要改爲[XmlRoot]屬性。爲了完整起見,如果您希望在序列化過程中忽略班級中的某個屬性,請使用[XmlIgnore]屬性。

我已成功序列化了我的對象,並且現在已成功接收傳入的XML並將其解序列化爲SalesEnquiry對象。

這種方法比手動解析XML要容易得多。好吧,學習曲線陡峭,但是值得。

謝謝!

+1

XML附件是否符合特定模式?它總是一樣的模式?您是否將XML「分解」爲特定的表格佈局,或將整個文檔存儲爲BLOB? – lesscode 2010-07-27 11:51:41

+0

@Wayne:不,沒有正式的模式,一些元素是可選的,將會丟失而不是空白。數據存儲在數據庫中的一對錶中。 – CJM 2010-07-27 13:46:49

+0

我已根據您的更新更新了我的答案。 – 2010-07-27 14:44:18

回答

6

如果您的XML使用模式(即您總是會知道顯示的元素以及它們在樹中的顯示位置),您可以使用XmlSerializer來創建對象。您只需在您的類上使用一些屬性來告訴序列化程序它們對應的XML元素或屬性。然後,只需加載XML,使用要創建的.NET對象的類型創建一個新的XmlSerializer,然後調用Deserialize方法。

例如,你有一個這樣的類:

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

    [XmlElement("PersonAge")] 
    public int Age { get; set; } 

    [XmlArrayItem("Child")] 
    public List<string> Children { get; set; } 
} 

輸入這樣的XML(保存在文件中的這個例子):

<?xml version="1.0"?> 
<Person> 
    <PersonName>Bob</PersonName> 
    <PersonAge>35</PersonAge> 
    <Children> 
    <Child>Chris</Child> 
    <Child>Alice</Child> 
    </Children> 
</Person> 

然後創建一個Person例如像這樣的:

Person person = null; 
XmlSerializer serializer = new XmlSerializer(typeof(Person)); 
using (FileStream fs = new FileStream(GetFileName(), FileMode.Open)) 
{ 
    person = (Person)serializer.Deserialize(fs); 
} 

更新: 根據你最近的更新,我猜想你要麼指定一個XmlRoot屬性作爲你的根元素。 SalesEnquiry)或XmlSerializer可能有點困惑,因爲您在XML中引用了一個空的名稱空間(xmlns=''看起來不正確)。

+0

一旦我得到這個工作(見上文),這應該是非常方便,謝謝。 – CJM 2010-07-27 14:30:55

+0

我試着爲該類指定一個XmlElement屬性,但它不允許它。此外,我嘗試添加一個名稱空間到查詢元素,並在同一點發生同樣的錯誤。我很難過。 – CJM 2010-07-27 15:13:53

+0

@CJM,對不起,我的錯誤:它不是您在課堂上需要的'XmlElement',而是'XmlRoot'。我已經更新了我的答案。 – 2010-07-28 08:33:52

2

XmlSerializer確實支持數組&列表...只要包含的類型是可序列化的。

1

我發現Xsd2Code對這種事情非常有幫助:http://xsd2code.codeplex.com/

基本上,所有你需要做的是寫一個XSD文件(XML模式文件),並指定一些命令行開關。 Xsd2Code會自動生成一個C#類文件,其中包含所有類和屬性以及處理序列化所需的所有內容。這不是一個完美的解決方案,因爲它不支持XSD的所有方面,但是如果你的XML文件是相對簡單的元素和屬性集合,它應該是一個很好的捷徑。

Codeplex上還有另外一個類似的項目叫做Linq to XSD(http://linqtoxsd.codeplex.com/),它被設計用於強制執行整個XSD規範,但上次我檢查時,它不再被支持,也沒有準備好黃金時段。不過,我認爲這值得一提。

+0

謝謝丹 - 可能早些時候有用,但無論出於何種原因,我創建了DAL,然後鏈接回XML。如果這個應用程序是它的東西,它可能會讓這個過程更加快捷。另一方面,這是一個有價值的學習練習,因爲它是...... – CJM 2010-07-27 21:39:06