LINQ to XML元素概括
在向大家詳細(xì)介紹LINQ to XML之前,首先讓大家了解下LINQ to XML元素,然后全面介紹LINQ to XML。
對(duì)于LINQ to XML元素的更新操作,關(guān)鍵就是在于查詢上面,如何有效并準(zhǔn)確的查詢到目標(biāo)元素是一個(gè)比較有挑戰(zhàn)性的問(wèn)題,這就像SQL語(yǔ)句一樣對(duì)于同一個(gè)查詢不同的寫(xiě)法和關(guān)系連接效率就不一樣,這個(gè)讀者需要自己多加練習(xí)。在上面的代碼段中,我們?nèi)ゲ檎宜袑傩詾镻artNumber=872-AA的元素并將其更新為Hello。那么如果想操作元素值,只需將修改查詢條件為:
- var partNos = from item in xelem.Descendants("ProductName")
- where item.Value == "Lawnmower"
XML文檔的元素名稱更新相比較于值更新要麻煩許多。由于XML文檔結(jié)構(gòu)是一個(gè)類樹(shù)形結(jié)構(gòu),學(xué)過(guò)數(shù)據(jù)結(jié)構(gòu)的讀者知道要更新一個(gè)樹(shù)節(jié)點(diǎn)的指針,最少需要三個(gè)步驟:
A. 查找目標(biāo)樹(shù)節(jié)點(diǎn)的父節(jié)點(diǎn)
B. 將先前的節(jié)點(diǎn)的孩子轉(zhuǎn)移到新節(jié)點(diǎn)
C. 將父節(jié)點(diǎn)的子節(jié)點(diǎn)替換(如果需要還要用算法重新排序樹(shù))。
所以我們也需要用同樣的邏輯來(lái)處理XML節(jié)點(diǎn)的更新。那么相比較DOM文檔對(duì)象和LINQ to XML元素名稱更新操作,LINQ to XML的步驟要簡(jiǎn)單許多。
- XElement xel = XElement.Load(@"example.xml");
- var itemNos = from item in xel.Descendants("Item")
- select item;
- int n = itemNos.Count();
- for (int i=0; i<n; i++)
- {
- // 新創(chuàng)建節(jié)點(diǎn)
- XElement nEl = new XElement("Element");
- // 轉(zhuǎn)移孩子節(jié)點(diǎn)
- nEl.Add(itemNos.ElementAt(0).Elements());
- // 替換
- itemNos.ElementAt(0).ReplaceWith(nEl);
- }
- Console.Write(xel);
上面的代碼是將所有名稱為Item的元素替換成名稱為Element。細(xì)心的讀者可以看到我在for循環(huán)中獲取itemNos的孩子都使用0這個(gè)索引值,為什么呢?這是因?yàn)樵诿杜e器中如果前面的對(duì)象消失那么索引位置就會(huì)下移,那么當(dāng)我們替換一個(gè)元素后,下一個(gè)元素的索引自動(dòng)變?yōu)?,所以我們只要循環(huán)指定次數(shù)就可以遍歷所有元素來(lái)。這也是為什么不用foreach的原因。那么我們進(jìn)一步的出思考XML名稱替換這個(gè)問(wèn)題。我們會(huì)發(fā)現(xiàn)LINQ to XML的XElement類提供了4個(gè)方法用來(lái)支持該功能:ReplaceAll, ReplaceAttributes, ReplaceNodes和ReplaceWith。這四個(gè)方法除了ReplaceWith是操作本元素以為,其他的都是操作元素的孩子或是屬性內(nèi)容。這里提供的好處是如果我們想遍歷替換操作,就不必去重復(fù)的查詢目標(biāo)元素。
最后,我們討論一下如何利用LINQ to XML來(lái)刪除一個(gè)元素。對(duì)于類樹(shù)形結(jié)構(gòu)的數(shù)據(jù)來(lái)說(shuō),刪除一個(gè)元素意味著兩種情況:一、刪除本節(jié)點(diǎn)和其所有子節(jié)點(diǎn);二、只刪除本節(jié)點(diǎn)。而在刪除節(jié)點(diǎn)之前,我們需要先定位到目標(biāo)節(jié)點(diǎn),所以要先進(jìn)行查詢操作:
- XElement xelem = XElement.Load(@"example.xml");
- var partNos = from item in xelem.Descendants("Item")
- where item.Attributes("PartNumber").Single().Value == "872-AA"
- select item;
- partNos.Remove();
- Console.Write(xelem);
【編輯推薦】