Linq To Xml學習 - 3.查詢、更新、刪除
文章最後有該示例的XML文檔。
查找具有特定屬性的元素
XElement root = XElement.Load ("PurchaseOrder.xml");
IEnumerable address =
from el in root.Elements("Address")
where (string)el.Attribute("Type") == "Billing"
select el;
foreach (XElement el in address)
Console.WriteLine(el);
輸出為:
<Address Type="Billing">
<Name>Tai YeeName>
<Street>8 Oak AvenueStreet>
<City>Old TownCity>
<State>PAState>
<Zip>95819Zip>
<Country>USACountry>
Address>
內存中 XML 樹修改與函數構造
就地修改 XML 樹是更改 XML 文檔形狀的傳統方法。 典型的應用程序將文檔 加載到數據存儲區(如 DOM 或 LINQ to XML);使用編程接口插入節點、刪除 節點或更改節點的內容;然後將 XML 保存到文件或通過網絡傳輸。
LINQ to XML 允許使用另一種可在許多方案中使用的方法:函數構造。 函數 構造將修改數據視為轉換問題,而不是數據存儲區的具體操作。 如果您采用某 種數據表示形式並有效地將其從一種形式轉換為另一種形式,其結果等效於您采 用一個數據存儲區並對其以某種方式進行操作以采用另一種形狀。 函數構造方 法的關鍵是將查詢的結果傳遞給 XDocument 和 XElement 構造函數。
此示例假設您想修改下面的簡單 XML 文檔,使屬性變為元素。 本節首先介 紹傳統的就地修改方法。 然後顯示函數構造方法。XML文件:
xml version="1.0" encoding="utf-8" ? >
<Root Data1="123" Data2="456">
<Child1>ContentChild1>
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);
輸出結果為:
<Root>
<Child1>ContentChild1>
<Data1>123Data1>
<Data2>456Data2>
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);
在本例中,函數示例一點也不比第一個示例簡短,而且一點也不比第一個示 例簡單。 但如果要對一個 XML 樹進行很多更改,則非函數方法將變得非常復雜 ,而且會顯得很笨拙。 相比之下,使用函數方法時,您只需形成所需的 XML, 嵌入適當的查詢和表達式以提取需要的內容。 函數方法生成的代碼更易於維護 。
請注意,在本例中,函數方法的執行效果可能沒有樹操作方法好。 主要問題 是函數方法創建了更多短生存期的對象。 但是,如果使用函數方法能夠提高程 序員的效率,則折中也是一種有效的方式。
這是一個很簡單的示例,但它顯示了這兩種方法之間基本原理上的差異。 對 於轉換較大的 XML 文檔,函數方法可以產生更高的效率增益。
向 XML 樹中添加元素、屬性和節點
下面的方法將子內容添加到 XElement 或 XDocument 中:
方法 說明
Add 在 XContainer 的子內容的末尾添加內容。
AddFirst 在 XContainer 的子內容的開頭添加內容。
下面的方法將內容添加為 XNode 的同級節點。 向其中添加同級內容的最常 見的節點是 XElement,不過你也可以將有效的同級內容添加到其他類型的節點 ,例如 XText 或 XComment。
方法 說明
AddAfterSelf 在 XNode 後面添加內容。
AddBeforeSelf 在 XNode 前面添加內容。
示例:
XElement srcTree = new XElement("Root",
new XElement("Element1", 1),
new XElement("Element2", 2),
new XElement("Element3", 3),
new XElement("Element4", 4),
new XElement("Element5", 5)
);
XElement xmlTree = new XElement("Root",
new XElement("Child1", 1),
new XElement("Child2", 2),
new XElement("Child3", 3),
new XElement("Child4", 4),
new XElement("Child5", 5)
);
xmlTree.Add(new XElement("NewChild", "new content"));
xmlTree.Add(
from el in srcTree.Elements()
where (int)el > 3
select el
);
// Even though Child9 does not exist in srcTree, the following statement will not
// throw an exception, and nothing will be added to xmlTree.
xmlTree.Add(srcTree.Element("Child9"));
Console.WriteLine(xmlTree);
輸出結果:
<Root>
<Child1>1Child1>
<Child2>2Child2>
<Child3>3Child3>
<Child4>4Child4>
<Child5>5Child5>
<NewChild>new contentNewChild>
<Element4>4Element4>
<Element5>5Element5>
Root>
修改 XML 樹中的元素、屬性和節點
下表匯總了修改元素、元素的子元素或元素屬性 (Attribute) 時可以使用的 方法和屬性 (Property)。
下面的方法修改 XElement。
方法 說明 XElement..::.Parse 用已分析的 XML 替換元素。 XElement..::.RemoveAll 移除元素的所有內容(子節點和屬性)。 XElement..::.RemoveAttributes 移除元素的屬性。 XElement..::.ReplaceAll 替換元素的所有內容(子節點和屬性)。 XElement..::.ReplaceAttributes 替換元素的屬性。 XElement..::.SetAttributeValue 設置屬性的值。 如果該屬性不存在,則創建該屬性。 如果值 設置為 null,則移除該屬性。 XElement..::.SetElementValue 設置子元素的值。 如果該元素不存在,則創建該元素。 如果 值設置為 null,則移除該元素。 XElement..::.Value 用指定的文本替換元素的內容(子節點)。 XElement..::.SetValue 設置元素的值。
下面的方法修改 XAttribute。
方法 說明 XAttribute..::.Value 設置屬性的值。 XAttribute..::.SetValue 設置屬性的值。
下面的方法修改 XNode(包括 XElement 或 XDocument)。
方法 說明 XNode..::.ReplaceWith 用新內容替換節點。
下面的方法修改 XContainer(XElement 或 XDocument)。
方法 說明 XContainer..::.ReplaceNodes 用新內容替換子節點。
XElement.SetElementValue 方法
此方法旨在簡化將名稱/值對列表用作子元素集時的維護。維護列表時,需要 添加對、修改對或刪除對。如果調用此方法將不存在的名稱作為子元素傳遞,則 此方法會為您創建一個子元素。如果您調用此方法來傳遞一個現有子元素的名稱 ,則此方法會將此子元素的值更改為指定的值。如果您為 value 傳遞了 nullNothingnullptrnull 引用(在 Visual Basic 中為 Nothing),則此方法 會移除子元素。
// Create an element with no content
XElement root = new XElement("Root");
// Add some name/value pairs.
root.SetElementValue("Ele1", 1);
root.SetElementValue("Ele2", 2);
root.SetElementValue("Ele3", 3);
Console.WriteLine(root);
// Modify one of the name/value pairs.
root.SetElementValue("Ele2", 22);
Console.WriteLine(root);
// Remove one of the name/value pairs.
root.SetElementValue("Ele3", null);
Console.WriteLine(root);
輸出結果:
<Root>
<Ele1>1Ele1>
<Ele2>2Ele2>
<Ele3>3Ele3>
Root>
<Root>
<Ele1>1Ele1>
<Ele2>22Ele2>
<Ele3>3Ele3>
Root>
<Root>
<Ele1>1Ele1>
<Ele2>22Ele2>
Root>
XElement.SetAttributeValue 方法
此方法旨在簡化將名稱/值對列表用作屬性集時的維護。維護列表時,需要添 加對、修改對或刪除對。如果調用此方法將不存在的名稱作為屬性傳遞,則此方 法會為您創建一個屬性。如果調用此方法來傳遞現有屬性的名稱,則此方法將會 屬性的值修改為指定的值。如果您為 value 傳遞了 nullNothingnullptrnull 引用(在 Visual Basic 中為 Nothing),則此方法會移除該屬性。
此方法將引發 Changed 和 Changing 事件。
將值分配給具有指定名稱的屬性。如果不存在具有指定名稱的屬性,則添加 新屬性。如果值為 nullNothingnullptrnull 引用(在 Visual Basic 中為 Nothing),則刪除具有指定名稱的屬性(如果存在)。
// Create an element with no content.
XElement root = new XElement("Root");
// Add some name/value pairs.
root.SetAttributeValue("Att1", 1);
root.SetAttributeValue("Att2", 2);
root.SetAttributeValue("Att3", 3);
Console.WriteLine(root);
// Modify one of the name/value pairs.
root.SetAttributeValue("Att2", 22);
Console.WriteLine(root);
// Remove one of the name/value pairs.
root.SetAttributeValue("Att3", null);
Console.WriteLine(root);
輸出結果為:
<Root Att1="1" Att2="2" Att3="3" />
<Root Att1="1" Att2="22" Att3="3" />
<Root Att1="1" Att2="
XNode.ReplaceWith 方法
使用指定的內容替換此節點。
XElement xmlTree = new XElement("Root",
new XElement("Child1", "child1 content"),
new XElement("Child2", "child2 content"),
new XElement("Child3", "child3 content"),
new XElement("Child4", "child4 content"),
new XElement("Child5", "child5 content")
);
XElement child3 = xmlTree.Element("Child3");
child3.ReplaceWith(
new XElement("NewChild", "new content")
);
Console.WriteLine(xmlTree);
輸出結果:
<Root>
<Child1>child1 contentChild1>
<Child2>child2 contentChild2>
<NewChild>new contentNewChild>
<Child4>child4 contentChild4>
<Child5>child5 contentChild5>
Root>
從 XML 樹中移除元素、屬性和節點
可以修改 XML 樹,移除元素、屬性和其他類型的節點。
從 XML 文檔中移除單個元素或單個屬性的操作非常簡單。 但是,若要移除 多個元素或屬性的集合,則應首先將一個集合具體化為一個列表,然後從該列表 中刪除相應元素或屬性。 最好的方法是使用 Remove 擴展方法,該方法可以實 現此操作。
這麼做的主要原因在於,從 XML 樹檢索的大多數集合都是用延遲執行生成的 。 如果不首先將集合具體化為列表,或者不使用擴展方法,則可能會遇到某類 Bug。
示例:
此示例演示三種移除元素的方法。 第一種,移除單個元素。 第二種,檢索 元素的集合,使用 Enumerable.ToList<(Of <(TSource>)>) 運算 符將它們具體化,然後移除集合。 最後一種,檢索元素的集合,使用 Remove 擴展方法移除元素。
XElement root = XElement.Parse(@"
");
root.Element("Child1").Element ("GrandChild1").Remove();
root.Element("Child2").Elements().ToList().Remove();
root.Element("Child3").Elements().Remove();
Console.WriteLine(root);
輸出結果為:
<Root>
<Child1>
<GrandChild2 />
<GrandChild3 />
Child1>
<Child2 />
<Child3 />
Root>