LINQ to XML 比較DOM

此文章描述 LINQ to XML 和目前主流 XML 程式設計 API (W3C 文件物件模型 (DOM)) 之間的一些主要差異。

建構 XML 樹狀結構的新方式

在 W3C DOM 中,您可以從下往上建置 XML 樹狀;也就是說,您可以建立文件、建立項目,然後將項目加入到文件中。

例如,下列範例使用一種典型方式,使用 Microsoft 的 DOM 實作 XmlDocument 來建立 XML 樹狀結構。

XmlDocument doc = new XmlDocument();
XmlElement name = doc.CreateElement("Name");
name.InnerText = "Patrick Hines";
XmlElement phone1 = doc.CreateElement("Phone");
phone1.SetAttribute("Type", "Home");
phone1.InnerText = "206-555-0144";
XmlElement phone2 = doc.CreateElement("Phone");
phone2.SetAttribute("Type", "Work");
phone2.InnerText = "425-555-0145";
XmlElement street1 = doc.CreateElement("Street1");
street1.InnerText = "123 Main St";
XmlElement city = doc.CreateElement("City");
city.InnerText = "Mercer Island";
XmlElement state = doc.CreateElement("State");
state.InnerText = "WA";
XmlElement postal = doc.CreateElement("Postal");
postal.InnerText = "68042";
XmlElement address = doc.CreateElement("Address");
address.AppendChild(street1);
address.AppendChild(city);
address.AppendChild(state);
address.AppendChild(postal);
XmlElement contact = doc.CreateElement("Contact");
contact.AppendChild(name);
contact.AppendChild(phone1);
contact.AppendChild(phone2);
contact.AppendChild(address);
XmlElement contacts = doc.CreateElement("Contacts");
contacts.AppendChild(contact);
doc.AppendChild(contacts);
Dim doc As XmlDocument = New XmlDocument()
Dim name As XmlElement = doc.CreateElement("Name")
name.InnerText = "Patrick Hines"
Dim phone1 As XmlElement = doc.CreateElement("Phone")
phone1.SetAttribute("Type", "Home")
phone1.InnerText = "206-555-0144"
Dim phone2 As XmlElement = doc.CreateElement("Phone")
phone2.SetAttribute("Type", "Work")
phone2.InnerText = "425-555-0145"
Dim street1 As XmlElement = doc.CreateElement("Street1")
street1.InnerText = "123 Main St"
Dim city As XmlElement = doc.CreateElement("City")
city.InnerText = "Mercer Island"
Dim state As XmlElement = doc.CreateElement("State")
state.InnerText = "WA"
Dim postal As XmlElement = doc.CreateElement("Postal")
postal.InnerText = "68042"
Dim address As XmlElement = doc.CreateElement("Address")
address.AppendChild(street1)
address.AppendChild(city)
address.AppendChild(state)
address.AppendChild(postal)
Dim contact As XmlElement = doc.CreateElement("Contact")
contact.AppendChild(name)
contact.AppendChild(phone1)
contact.AppendChild(phone2)
contact.AppendChild(address)
Dim contacts As XmlElement = doc.CreateElement("Contacts")
contacts.AppendChild(contact)
doc.AppendChild(contacts)
Console.WriteLine(doc.OuterXml)

這種程式碼撰寫風格會隱藏 XML 樹狀結構的結構。 LINQ to XML 也支援替代方法 (功能性建構),其更能顯示結構。 此方法可以使用 XElementXAttribute 建構函式來完成。 在 Visual Basic 中,也可以使用 XML 常值來完成。 此範例示範如何使用功能性建構來建構相同的 XML 樹狀結構:

XElement contacts =
    new XElement("Contacts",
        new XElement("Contact",
            new XElement("Name", "Patrick Hines"),
            new XElement("Phone", "206-555-0144",
                new XAttribute("Type", "Home")),
            new XElement("phone", "425-555-0145",
                new XAttribute("Type", "Work")),
            new XElement("Address",
                new XElement("Street1", "123 Main St"),
                new XElement("City", "Mercer Island"),
                new XElement("State", "WA"),
                new XElement("Postal", "68042")
            )
        )
    );
Dim contacts = _
    <Contacts>
        <Contact>
            <Name>Patrick Hines</Name>
            <Phone Type="Home">206-555-0144</Phone>
            <Phone Type="Work">425-555-0145</Phone>
            <Address>
                <Street1>123 Main St</Street1>
                <City>Mercer Island</City>
                <State>WA</State>
                <Postal>68042</Postal>
            </Address>
        </Contact>
    </Contacts>

請注意,將要建構 XML 樹狀結構的程式碼縮排可顯示基礎 XML 的結構。 Visual Basic 版本會使用 XML 常值。

如需詳細資訊,請參閱 XML 樹狀結構

直接使用 XML 元素

當您使用 XML 進行程式設計時,您的主要焦點通常是 XML 項目,也可能是屬性。 在 LINQ to XML 中,您可以直接使用 XML 元素和屬性。 例如,您可以執行下列動作:

  • 完全不使用文件物件來建立 XML 項目。 當您必須使用 XML 樹狀結構的片段時,這可以簡化程式設計的方式。
  • 從 XML 檔案直接載入 T:System.Xml.Linq.XElement 物件。
  • T:System.Xml.Linq.XElement 物件序列化為檔案或資料流。

將這個 XML 項目或屬性與 W3C DOM 相比較,後者中的 XML 文件會當做 XML 樹狀結構的邏輯容器使用。 在 DOM 中,XML 節點 (包括項目和屬性) 必須在 XML 文件的內容中建立。 此處為要在 DOM 中建立名稱元素的程式碼片段:

XmlDocument doc = new XmlDocument();
XmlElement name = doc.CreateElement("Name");
name.InnerText = "Patrick Hines";
doc.AppendChild(name);
Dim doc As XmlDocument = New XmlDocument()
Dim name As XmlElement = doc.CreateElement("Name")
name.InnerText = "Patrick Hines"
doc.AppendChild(name)

如果您要跨多個文件使用同一個項目,您必須匯入跨這些文件的節點。 LINQ to XML 可避免這層複雜度。

使用 LINQ to XML 時,您僅能在想要於文件根層級上加入註解或處理指示時,才能使用 XDocument 類別。

簡化的名稱和命名空間處理方式

名稱、命名空間和命名空間前置詞的處理通常是 XML 程式設計的複雜部分。 LINQ to XML 不必處理命名空間前置詞,因而可簡化名稱和命名空間。 您也可以控制命名空間前置詞。 但是,如果您決定不要明確地控制命名空間前置詞,則 LINQ to XML 將在序列化期間指派命名空間前置詞 (如有必要),或使用預設的命名空間進行序列化 (如非必要)。 如果使用預設的命名空間,在產生的文件中將不會有任何命名空間前置詞。 如需詳細資訊,請參閱命名空間概觀

另一個 DOM 問題是,DOM 不會讓您變更節點的名稱。 而是必須建立新的節點,並將所有子節點複製到該節點中,因此會失去原始的節點識別。 LINQ to XML 會讓您在節點上設定 XName 屬性,以避免此問題。

載入 XML 的靜態方法支援

LINQ to XML 可讓您使用靜態方法 (而非執行個體方法) 來載入 XML。 這會簡化載入和剖析的程序。 如需詳細資訊,請參閱如何從檔案載入 XML

移除對 DTD 建構的支援

LINQ to XML 透過移除對實體和實體參考的支援,進一步簡化 XML 程式設計。 實體的管理很複雜,而且不常使用。 移除這些支援會增進效能並簡化程式設計介面。 填入 LINQ to XML 樹狀結構時,系統會展開所有 DTD 實體。

對片段的支援

LINQ to XML 不提供 XmlDocumentFragment 類別的對等項目。 但是,在許多情況下,XmlDocumentFragment 概念可透過查詢結果來處理,該查詢的類型為 XNodeIEnumerable<T>XElementIEnumerable<T>

支援 XPathNavigator

LINQ to XML 透過 System.Xml.XPath 命名空間中的擴充方法,提供對 XPathNavigator 的支援。 如需詳細資訊,請參閱System.Xml.XPath.Extensions

支援空白字元與縮排

LINQ to XML 處理空白字元,會比 DOM 更容易。

常見的案例為讀取縮排的 XML、建立沒有任何空白字元文字節點 (也就是不保留空白字元) 的記憶體內部 XML 樹狀結構、對 XML 執行某些作業,然後儲存具有縮排的 XML。 當您序列化具有格式的 XML 時,只會保留 XML 樹狀結構中的有效空白字元。 這是 LINQ to XML 的預設行為。

其他常見案例為讀取與修改已經過刻意縮排的 XML。 您可能不想用任何方式變更這個縮排。 在 LINQ to XML 中,您可以透過下列方式來這樣做:

  • 載入或剖析 XML 時保留空白字元。
  • 將 XML 序列化時停用格式設定。

LINQ to XML 會將空白字元儲存為 XText 節點,而不是像 DOM 那樣具有專用的 Whitespace 節點類型。

支援註釋

LINQ to XML 元素支援一組可延伸的註釋。 這在追蹤項目的其他資訊 (例如,結構描述資訊)、項目是否繫結至 UI 的相關資訊,或任何種類的應用程式專屬資訊時,相當實用。 如需詳細資訊,請參閱 LINQ to XML 註釋

支援結構描述資訊

LINQ to XML 透過 System.Xml.Schema 命名空間中的擴充方法來提供對 XSD 驗證的支援。 您可以驗證 XML 樹狀是以 XSD 編譯。 您可以利用 Post-Schema-Validation Infoset (PSVI) 填入 XML 樹狀。 如需詳細資訊,請參閱如何使用 XSD 進行驗證Extensions

另請參閱