|
Linq To Xml學(xué)習(xí) - 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>
內(nèi)存中 XML 樹(shù)修改與函數(shù)構(gòu)造
就地修改 XML 樹(shù)是更改 XML 文檔形狀的傳統(tǒng)方法。 典型的應(yīng)用程序?qū)⑽臋n加載到數(shù)據(jù)存儲(chǔ)區(qū)(如 DOM 或 LINQ to XML);使用編程接口插入節(jié)點(diǎn)、刪除節(jié)點(diǎn)或更改節(jié)點(diǎn)的內(nèi)容;然后將 XML 保存到文件或通過(guò)網(wǎng)絡(luò)傳輸。
LINQ to XML 允許使用另一種可在許多方案中使用的方法:函數(shù)構(gòu)造。 函數(shù)構(gòu)造將修改數(shù)據(jù)視為轉(zhuǎn)換問(wèn)題,而不是數(shù)據(jù)存儲(chǔ)區(qū)的具體操作。 如果您采用某種數(shù)據(jù)表示形式并有效地將其從一種形式轉(zhuǎn)換為另一種形式,其結(jié)果等效于您采用一個(gè)數(shù)據(jù)存儲(chǔ)區(qū)并對(duì)其以某種方式進(jìn)行操作以采用另一種形狀。 函數(shù)構(gòu)造方法的關(guān)鍵是將查詢的結(jié)果傳遞給 XDocument 和 XElement 構(gòu)造函數(shù)。
此示例假設(shè)您想修改下面的簡(jiǎn)單 XML 文檔,使屬性變?yōu)樵亍?本節(jié)首先介紹傳統(tǒng)的就地修改方法。 然后顯示函數(shù)構(gòu)造方法。XML文件:
xml version="1.0" encoding="utf-8" ?><Root Data1="123" Data2="456"> <Child1>ContentChild1>Root>
您可以編寫(xiě)一些過(guò)程代碼以便從屬性創(chuàng)建元素,然后刪除屬性,如下所示:
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);
輸出結(jié)果為:
<Root> <Child1>ContentChild1> <Data1>123Data1> <Data2>456Data2>Root>
函數(shù)構(gòu)造方法
相比之下,函數(shù)方法包含用于形成新樹(shù)的代碼、從源樹(shù)中選擇元素和屬性并在將其添加到新樹(shù)中時(shí)進(jìn)行相應(yīng)的轉(zhuǎn)換。 函數(shù)方法如下所示:
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);
在本例中,函數(shù)示例一點(diǎn)也不比第一個(gè)示例簡(jiǎn)短,而且一點(diǎn)也不比第一個(gè)示例簡(jiǎn)單。 但如果要對(duì)一個(gè) XML 樹(shù)進(jìn)行很多更改,則非函數(shù)方法將變得非常復(fù)雜,而且會(huì)顯得很笨拙。 相比之下,使用函數(shù)方法時(shí),您只需形成所需的 XML,嵌入適當(dāng)?shù)牟樵兒捅磉_(dá)式以提取需要的內(nèi)容。 函數(shù)方法生成的代碼更易于維護(hù)。
請(qǐng)注意,在本例中,函數(shù)方法的執(zhí)行效果可能沒(méi)有樹(shù)操作方法好。 主要問(wèn)題是函數(shù)方法創(chuàng)建了更多短生存期的對(duì)象。 但是,如果使用函數(shù)方法能夠提高程序員的效率,則折中也是一種有效的方式。
這是一個(gè)很簡(jiǎn)單的示例,但它顯示了這兩種方法之間基本原理上的差異。 對(duì)于轉(zhuǎn)換較大的 XML 文檔,函數(shù)方法可以產(chǎn)生更高的效率增益。
向 XML 樹(shù)中添加元素、屬性和節(jié)點(diǎn)
下面的方法將子內(nèi)容添加到 XElement 或 XDocument 中:
方法 說(shuō)明
Add 在 XContainer 的子內(nèi)容的末尾添加內(nèi)容。
AddFirst 在 XContainer 的子內(nèi)容的開(kāi)頭添加內(nèi)容。
下面的方法將內(nèi)容添加為 XNode 的同級(jí)節(jié)點(diǎn)。 向其中添加同級(jí)內(nèi)容的最常見(jiàn)的節(jié)點(diǎn)是 XElement,不過(guò)你也可以將有效的同級(jí)內(nèi)容添加到其他類(lèi)型的節(jié)點(diǎn),例如 XText 或 XComment。
方法 說(shuō)明
AddAfterSelf 在 XNode 后面添加內(nèi)容。
AddBeforeSelf 在 XNode 前面添加內(nèi)容。
示例:
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);
輸出結(jié)果:
<Root> <Child1>1Child1> <Child2>2Child2> <Child3>3Child3> <Child4>4Child4> <Child5>5Child5> <NewChild>new contentNewChild> <Element4>4Element4> <Element5>5Element5>Root>
修改 XML 樹(shù)中的元素、屬性和節(jié)點(diǎn)
下表匯總了修改元素、元素的子元素或元素屬性 (Attribute) 時(shí)可以使用的方法和屬性 (Property)。
下面的方法修改 XElement。
方法 | 說(shuō)明 |
---|---|
XElement..::.Parse | 用已分析的 XML 替換元素。 |
XElement..::.RemoveAll | 移除元素的所有內(nèi)容(子節(jié)點(diǎn)和屬性)。 |
XElement..::.RemoveAttributes | 移除元素的屬性。 |
XElement..::.ReplaceAll | 替換元素的所有內(nèi)容(子節(jié)點(diǎn)和屬性)。 |
XElement..::.ReplaceAttributes | 替換元素的屬性。 |
XElement..::.SetAttributeValue | 設(shè)置屬性的值。 如果該屬性不存在,則創(chuàng)建該屬性。 如果值設(shè)置為 null,則移除該屬性。 |
XElement..::.SetElementValue | 設(shè)置子元素的值。 如果該元素不存在,則創(chuàng)建該元素。 如果值設(shè)置為 null,則移除該元素。 |
XElement..::.Value | 用指定的文本替換元素的內(nèi)容(子節(jié)點(diǎn))。 |
XElement..::.SetValue | 設(shè)置元素的值。 |
XElement.SetElementValue 方法
此方法旨在簡(jiǎn)化將名稱(chēng)/值對(duì)列表用作子元素集時(shí)的維護(hù)。維護(hù)列表時(shí),需要添加對(duì)、修改對(duì)或刪除對(duì)。如果調(diào)用此方法將不存在的名稱(chēng)作為子元素傳遞,則此方法會(huì)為您創(chuàng)建一個(gè)子元素。如果您調(diào)用此方法來(lái)傳遞一個(gè)現(xiàn)有子元素的名稱(chēng),則此方法會(huì)將此子元素的值更改為指定的值。如果您為 value 傳遞了 nullNothingnullptrnull 引用(在 Visual Basic 中為 Nothing),則此方法會(huì)移除子元素。
// Create an element with no contentXElement 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);
輸出結(jié)果:
<Root> <Ele1>1Ele1> <Ele2>2Ele2> <Ele3>3Ele3>Root><Root> <Ele1>1Ele1> <Ele2>22Ele2> <Ele3>3Ele3>Root><Root> <Ele1>1Ele1> <Ele2>22Ele2>Root>
XElement.SetAttributeValue 方法
此方法旨在簡(jiǎn)化將名稱(chēng)/值對(duì)列表用作屬性集時(shí)的維護(hù)。維護(hù)列表時(shí),需要添加對(duì)、修改對(duì)或刪除對(duì)。如果調(diào)用此方法將不存在的名稱(chēng)作為屬性傳遞,則此方法會(huì)為您創(chuàng)建一個(gè)屬性。如果調(diào)用此方法來(lái)傳遞現(xiàn)有屬性的名稱(chēng),則此方法將會(huì)屬性的值修改為指定的值。如果您為 value 傳遞了 nullNothingnullptrnull 引用(在 Visual Basic 中為 Nothing),則此方法會(huì)移除該屬性。
此方法將引發(fā) Changed 和 Changing 事件。
將值分配給具有指定名稱(chēng)的屬性。如果不存在具有指定名稱(chēng)的屬性,則添加新屬性。如果值為 nullNothingnullptrnull 引用(在 Visual Basic 中為 Nothing),則刪除具有指定名稱(chēng)的屬性(如果存在)。
// 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);
輸出結(jié)果為:
<Root Att1="1" Att2="2" Att3="3" /><Root Att1="1" Att2="22" Att3="3" /><Root Att1="1" Att2="22" />
XNode.ReplaceWith 方法
使用指定的內(nèi)容替換此節(jié)點(diǎn)。
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);
輸出結(jié)果:
<Root> <Child1>child1 contentChild1> <Child2>child2 contentChild2> <NewChild>new contentNewChild> <Child4>child4 contentChild4> <Child5>child5 contentChild5>Root>
從 XML 樹(shù)中移除元素、屬性和節(jié)點(diǎn)
可以修改 XML 樹(shù),移除元素、屬性和其他類(lèi)型的節(jié)點(diǎn)。
從 XML 文檔中移除單個(gè)元素或單個(gè)屬性的操作非常簡(jiǎn)單。 但是,若要移除多個(gè)元素或?qū)傩缘募希瑒t應(yīng)首先將一個(gè)集合具體化為一個(gè)列表,然后從該列表中刪除相應(yīng)元素或?qū)傩浴?最好的方法是使用 Remove 擴(kuò)展方法,該方法可以實(shí)現(xiàn)此操作。
這么做的主要原因在于,從 XML 樹(shù)檢索的大多數(shù)集合都是用延遲執(zhí)行生成的。 如果不首先將集合具體化為列表,或者不使用擴(kuò)展方法,則可能會(huì)遇到某類(lèi) Bug。
示例:
此示例演示三種移除元素的方法。 第一種,移除單個(gè)元素。 第二種,檢索元素的集合,使用 Enumerable.ToList<(Of <(TSource>)>) 運(yùn)算符將它們具體化,然后移除集合。 最后一種,檢索元素的集合,使用 Remove 擴(kuò)展方法移除元素。
XElement root = XElement.Parse(@" ");root.Element("Child1").Element("GrandChild1").Remove();root.Element("Child2").Elements().ToList().Remove();root.Element("Child3").Elements().Remove();Console.WriteLine(root);
輸出結(jié)果為:
<Root> <Child1> <GrandChild2 /> <GrandChild3 /> Child1> <Child2 /> <Child3 />Root>
it知識(shí)庫(kù):Linq To Xml學(xué)習(xí) - 3.查詢、更新、刪除,轉(zhuǎn)載需保留來(lái)源!
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。