記憶體中 XML 樹狀修改與功能建構 (LINQ to XML)

就地修改 XML 樹狀結構是變更 XML 文件組織結構的傳統方式。 一般應用程式會將文件載入資料存放區 (例如 DOM 或 LINQ to XML);使用程式設計介面插入節點、刪除節點或變更節點的內容;然後將 XML 儲存到檔案或透過網路傳輸。

LINQ to XML 可啟用在許多案例中有用的其他方法:功能建構。 功能結構會將修改資料視為轉換的問題,而不是資料存放區的詳細管理。 如果您可以表示資料,並將其有效地從一個表單轉換到另一個表單,結果會與您取得一個資料存放區,然後以相同的方式管理該資料存放區取得其他組織結構相同。 功能結構方法的關鍵在於將查詢結果傳遞到 XDocumentXElement 建構函式。

在許多情況下,您可以用管理資料存放區的少數時間撰寫轉換程式碼,而且產生的程式碼更穩定也更容易維護。 在這些情況下,即使轉換方法可能會耗用更大的處理能力,但仍是較有效的修改資料方式。 如果開發人員熟悉功能性做法,許多情況下產生的程式碼會更容易理解,而且很容易找出用來修改樹狀結構每個部分的程式碼。

您就地修改 XML 樹狀結構的做法,對於許多 DOM 程式設計人員而言更為熟悉,而使用功能性做法撰寫的程式碼,對於還不了解該做法的開發人員而言似乎較為陌生。 如果您必須針對大型 XML 樹狀結構進行小小的修改,您就地修改樹狀結構的方法在大部分的情況下,將會需要較少的 CPU 時間。

本文提供這兩種做法的範例。 假設您想要修改下列簡單的 XML 文件,讓屬性變成元素:

<?xml version="1.0" encoding="utf-8" ?>
<Root Data1="123" Data2="456">
  <Child1>Content</Child1>
</Root>

下列第一個範例使用傳統的就地修改做法,第二個範例使用功能建構做法。

範例:使用傳統就地做法將屬性轉換成元素

您可以撰寫特定的程序性程式碼以便從屬性建立項目,然後刪除該屬性,如下所示:

XElement root = XElement.Load("Data.xml");
foreach (XAttribute att in root.Attributes()) {
    root.Add(new XElement(att.Name, (string)att));
}
root.Attributes().Remove();
Console.WriteLine(root);
Dim root As XElement = XElement.Load("Data.xml")
For Each att As XAttribute In root.Attributes()
    root.Add(New XElement(att.Name, att.Value))
Next
root.Attributes().Remove()
Console.WriteLine(root)

這個範例會產生下列輸出:

<Root>
  <Child1>Content</Child1>
  <Data1>123</Data1>
  <Data2>456</Data2>
</Root>

範例:使用功能建構做法將屬性轉換成元素

相較之下,功能性做法包含形成新樹狀結構的程式碼,會從來源樹狀結構挑選出元素和屬性,然後在新增到新的樹狀結構時適當地加以轉換。

XElement root = XElement.Load("Data.xml");
XElement newTree = new XElement("Root",
    root.Element("Child1"),
    from att in root.Attributes()
    select new XElement(att.Name, (string)att)
);
Console.WriteLine(newTree);
Dim root As XElement = XElement.Load("Data.xml")
Dim newTree As XElement = _
    <Root>
        <%= root.<Child1> %>
        <%= From att In root.Attributes() _
            Select New XElement(att.Name, att.Value) %>
    </Root>
Console.WriteLine(newTree)

這個範例會與第一個範例輸出相同的 XML。 但是請注意,您實際上可以用功能性方法查看所產生的新 XML 結構。 您可以查看 Root 項目的建立、從來源樹狀結構提取 Child1 項目的程式碼,以及將屬性從來源樹狀結構轉換到新樹狀結構中的項目之程式碼。

在此案例中,功能性範例既沒有比第一個範例簡短,也沒有比較簡單。 不過,如果您有對 XML 樹狀結構進行很多變更,程序性做法會變得相當複雜,而且反應有些遲鈍。 相反地,使用功能性方法時,您仍然可以在適當地內嵌查詢和運算式,只形成所需的 XML,以便在所需的內容中提取。 功能性方法會產生容易維護的程式碼。

請注意,在這個情況下,功能性方法可能不會實際與樹狀結構管理方法一起執行。 主要的問題在於功能性做法會建立更多短期存在的物件。 不過,如果使用功能性方法能讓程式設計人員的產能更大,進行取捨是有效的方法。

這是非常簡單的範例,但是它有助於顯示兩種方法間的觀點差異。 功能性方法在轉換大型 XML 文件時,會產生較大的產能。