程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> .NET實例教程 >> LINQ及XML實戰

LINQ及XML實戰

編輯:.NET實例教程

基礎知識
1. LINQ的讀法:(1)lin k (2)lin q
2. LINQ的關鍵詞:from, select, in, where, group by, order by …
3. LINQ的注意點:必須以select或者是group by 結束。
4. LINQ的語義:
from 臨時變量 in 集合對象或數據庫對象
where 條件表達式
[order by條件]
select 臨時變量中被查詢的值
[group by 條件]

    LINQ的查詢返回值的類型是臨時變量的類型,可能是一個對象也可能是一個集合。並且LINQ的查詢表達式是在最近一次創建對象時才被編譯的。LINQ的查詢一般跟var關鍵字一起聯用 (什麼是var?匿名對象) 。以下的兩個查詢表達式是一樣的效果:

var q = from name in methods 
where (name.Name.Length > 15)
select name;

IEnumerable<MethodInfo> p = from name in methods
where (name.Name.Length > 15)
select name;

   所以這樣的我們就可以對LINQ的查詢表達式進行嵌套查詢:


var q = from t in 
(from name in methods
where (!name.IsVirtual)
select name)
where (t.Name.Length > 15)
select t.Name;

   5. LINQ的全稱:Language-Integrated Query
   6. LINQ的分類:LINQ to Object, LINQ to XML, LINQ to SQL, LINQ to ADO.Net

   對於LINQ to SQL方面的文章網路上已經有很多了,我將不再討論這方面的內容。下面我主要討論的是LINQ to XML方面的內容,順便提一下LINQ to Object。 

LINQ to Object

MethodInfo[] methods = typeof(string).GetMethods(); 
var q = from t in methods
where (t.Name.Length > 15)
select t;

   LINQ to Object主要是基於.Net框架裡的Lambda表達式來實現的,因此上面的代碼運行結果等同於下面的代碼:

MethodInfo[] methods = typeof(string).GetMethods(); 
var q = methods
.Where((method) => method.Name.Length > 15)
.Select((name) => name.Name);


LINQ to XML

XElement xelem = XElement.Load(@"example.XML"); 
// 查詢節點名為Item,並返回它們的PartNumber屬性值的集合
IEnumerable<string> partNos = from item in xelem.Descendants("Item")
Select (string)item.Attribute("PartNumber");
foreach (string str in partNos)
Console.WriteLine(str);

   在.Net3.5中,框架對XML的操作進行了擴展,這個擴展就是LINQ to XML。在名稱空間System.Xml.LINQ下。從以上的代碼我們可以看到增加了一個新的XElement對象。我們通過XElement.Load方法來裝載XML文檔,而不是傳統的DOM模式XMLDocument.Load。

   相比較於W3C的DOM文檔結構來說,LINQ to XML為我們提供了一種更方便的創建一個XML文檔的方式。

XElement contacts = 
new XElement("Contacts",
new XElement("Name", "Ice Lee"),
new XElement("Phone", "010-876546",
new XAttribute("Type", "Home")),
new XElement("Phone", "425-23456",
new XAttribute("Type", "Work")),
new XElement("Address",文章整理:學網 http://www.xue5.com (本站) [1] [2] [3] [4] [5] [6]


new XElement("Street", "ZhiXinCun"),
new XElement("City", "Beijin")
)
);
輸出結果:
<? XML version="1.0" encoding="utf-8"?>
<Contacts>
<Name>Ice Lee</Name>
<Phone Type="Home">010-876546</Phone>
<Phone Type="Work">425-23456</Phone>
<Address>
<Street>ZhiXinCun</Street>
<City>Beijing</City>
</Address>
</Contacts>

    LINQ to XML提供了為豐富並且簡潔的類來實現對XML的操作。相對於種類繁多的DOM模型的XML類庫而言,LINQ的類使我們的學習曲線變得平滑並且還能達到相同的效果。LINQ to XML解決了DOM模型中的幾個比較不方便的問題,如修改節點名字的問題;同時也拋棄了一些看起來很強大但是很不常用的東西,如實體和實體引用。這樣使得LINQ to XML的操作速度更快並且更方便。以下的幾個例子將展示給大家LINQ to XML如何完成節點名稱修改,增加和刪除的效果。
首先,我們看一下添加一個節點到XML中是這麼樣實現的:
XElement xelem = XElement.Load(@"example.XML");
XElement newXelem = new XElement("NewNode", "This is new node");
xelem.Add(newXelem);


相當的簡單,只要先生成一個XElement對象然後把它Add到當前節點對象就可以了。進一步我們仔細查看一下XElement可以添加節點的方法。可以看到一共有Add, AddAfterSelf, AddAnnotation, AddBeforeSelf, AddFirst這五個方法。在默認情況下,Add的操作是將新節點作為被插入節點的最後一個孩子節點插入的,而AddFirst正好相反。AddAfterSelf和AddBeforeSelf則是將節點作為兄弟節點插入的,這裡要注意的是調用這兩個方法的時候不能以根節點作為被插入節點,因為XML文檔規定只能有一個根節點。最後,我們來看一下AddAnnotation這個方法。AddAnnotation是為一個節點添加一個相關的評注的類對象。這個類對象可以用戶自己定義,所以通過這個方法我們可以擴展XML文檔對象的功能,例如根據節點來獲取類對象的功能。下面是一段引用自msdn的代碼:


public cla歡迎光臨學網,點擊這裡查看更多文章教程 [1] [2] [3] [4] [5] [6]

ss MyAnnotation
{
private string tag;
public string Tag { get { return tag; } set { tag = value; } }
public MyAnnotation(string tag)
{
this.tag = tag;
}
}
… …
MyAnnotation ma = new MyAnnotation("T1");
XElement root = new XElement("Root", "content");
root.AddAnnotation(ma);
MyAnnotation ma2 = (MyAnnotation)root.Annotation<MyAnnotation>();

    接下來我們再看一下如何利用LINQ to XML來更新XML的信息。對XML文檔進行更新主要包括兩個方面,一個方面是對元素屬性和值得更新;另一方面是對元素名稱的更新。在一般情況下,我們通常只對元素的屬性和值進行更新,代碼如下:


XElement xelem = XElement.Load(@"example.XML"); 
var partNos = from item in xelem.Descendants("Item")
where item.Attribute("PartNumber").Value == "872-AA"
select item;

foreach (XElement node in partNos)
{
node.Value = "Hello";
Console.WriteLine(node.Value);
}


對於XML元素的更新操作,關鍵就是在於查詢上面,如何有效並准確的查詢到目標元素是一個比較有挑戰性的問題,這就像SQL語句一樣對於同一個查詢不同的寫法和關系連接效率就不一樣,這個讀者需要自己多加練習。在上面的代碼段中,我們去查找所有屬性為PartNumber=872-AA的元素並將其更新為Hello。那麼如果想操作元素值,只需將修改查詢條件為:

var partNos = from item in xelem.Descendants("ProductName") 
where item.Value == "Lawnmower"


   XML文檔的元素名稱更新相比較於值更新要麻煩許多。由於XML文檔結構是一個類樹形結構,學過數據結構的讀者知道要更新一個樹節點的指針,最少需要三個步驟 :
   A. 查找目標樹節點的父節點
   B. 將先前的節點的孩子轉移到新節點
   C. 將父節點的子節點替換(如果需要還要用算法重新排序樹)。
   所以我們也需要用同樣的邏輯來處理XML節點的更新。那麼相比較DOM文檔對象和LINQ to XML對元素名稱更新操作,LINQ to XML的步驟要簡單許多。文章整理:學網 http://www.xue5.com (本站) [1] [2] [3] [4] [5] [6]



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++)
{
// 新創建節點
XElement nEl = new XElement("Element");
// 轉移孩子節點
nEl.Add(itemNos.ElementAt(0).Elements());
// 替換
itemNos.ElementAt(0).ReplaceWith(nEl);
}
Console.Write(xel);

   上面的代碼是將所有名稱為Item的元素替換成名稱為Element。細心的讀者可以看到我在for循環中獲取itemNos的孩子都使用0這個索引值,為什麼呢?這是因為在枚舉器中如果前面的對象消失那麼索引位置就會下移,那麼當我們替換一個元素後,下一個元素的索引自動變為0,所以我們只要循環指定次數就可以遍歷所有元素來。這也是為什麼不用foreach的原因。那麼我們進一步的出思考XML名稱替換這個問題。我們會發現LINQ to XML的XElement類提供了4個方法用來支持該功能:ReplaceAll, ReplaceAttributes, ReplaceNodes和ReplaceWith。這四個方法除了ReplaceWith是操作本元素以為,其他的都是操作元素的孩子或是屬性內容。這裡提供的好處是如果我們想遍歷替換操作,就不必去重復的查詢目標元素。

   最後,我們討論一下如何利用LINQ to XML來刪除一個元素。對於類樹形結構的數據來說,刪除一個元素意味著兩種情況:一、刪除本節點和其所有子節點;二、只刪除本節點。而在刪除節點之前,我們需要先定位到目標節點,所以要先進行查詢操作:

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);


對刪除操作,LINQ to XML也一樣提供了五個方法來操作:Remove, RemoveAll, RemoveAnnotations, RemoveAttributes, RemoveNodes。這五個方法跟添加和更新操作一樣都是為了方便操作元素內容而存在的。 

總結
 
   從上面的示例代碼中,我們可以看到其實使用LINQ to XML來操作XML對象是很方便的。而最主要,也是最重要的問題是你如何找到這個要操作的元素,也就是查詢操作才是靈魂。LINQ的查詢操作通常和匿名對象關鍵字var一起使用。歡迎光臨學網,點擊這裡查看更多文章教程 [1] [2] [3] [4] [5] [6]

匿名對象無疑是為LINQ而存在的,就像我們最前面的實例一樣當查詢返回的是集合對象或是新對象的時候,你需要先定義返回集合的類型,這很困難也很麻煩。這裡再提一下LINQ的語法:

/ 返回一個關於Item的集合,該集合的變量名為item. 
from item in xelem.Descendants("Item")
// 將上面的集合返回出去
select item;

   對於所有的LINQ語句,總是從上層傳遞結果到下層去處理。所以當我們在考慮查詢語句的時候,也要注意每一句的返回值。

   本文的實例工程可以從以下網址獲取:
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved