程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> LINQ學習筆記:導航和查詢X-DOM

LINQ學習筆記:導航和查詢X-DOM

編輯:關於.NET

導航/查詢X-DOM

就像你可能期望的那樣, XNode和XContainer類定義了方法和屬性來測量X-DOM樹. 與常規的DOM不同的是, 這些函數並不會返回實現了IList<T>的集合, 而是返回了一個單一值或者一個實現了IEnumerable<T>的序列. 基於這個你可以執行一個LINQ查詢或者使用foreach來做枚舉. 這同時也允許你使用熟悉的LINQ查詢語法來執行簡單的導航任務或者高級查詢.

在X-DOM中, 元素和屬性名都是大小寫敏感的, 這與XML是一致的.

FirstNode, LastNode與Nodes

FirstNode與LastNode允許你直接訪問第一個或者最後一個子節點; Nodes返回所有的子節點並形成一個序列. 這三個方法只用於直系的後代節點.

檢索元素

Elements方法返回類型為XElement的子節點. 例如:

   1: var bench = new XElement ("bench",
   2:               new XElement ("toolbox",
   3:                 new XElement ("handtool", "Hammer"),
   4:                 new XElement ("handtool", "RASP")
   5:               ),
   6:               new XElement ("toolbox",
   7:                 new XElement ("handtool", "Saw"),
   8:                 new XElement ("powertool", "Nailgun")
   9:               ),
  10:               new XComment ("Careful with the nailgun")
  11:             );
  12:
  13: foreach (XElement e in bench.Elements( ))
  14:   Console.WriteLine (e.Name + "=" + e.Value);
  15:
  16: // 結果: toolbox=HammerRASP
  17:            toolbox=SawNailgun

以下的LINQ查詢用於查詢包含nail gun的toolbox:

   1: IEnumerable<string> query =
   2:   from toolbox in bench.Elements( )
   3:   where toolbox.Elements( ).Any
   4:     (tool => tool.Value == "Nailgun")
   5:   select toolbox.Value;
   6:
   7: RESULT: { "SawNailgun" }

Elements等價於Nodes上面的LINQ查詢, 我們之前的查詢也可以被寫為:

   1: from toolbox in bench.Nodes().OfType<XElement>()
   2: where ...

接下來的例子使用一個SelectMany查詢檢索hand tools:

   1: IEnumerable<string> query =
   2:   from toolbox in bench.Elements( )
   3:   from tool in toolbox.Elements( )
   4:   where tool.Name == "handtool"
   5:   select tool.Value;
   6:
   7: RESULT: { "Hammer", "RASP", "Saw" }

Elements也可以只返回給定名稱的元素, 例如:

   1: int x = bench.Elements ("toolbox").Count();      // 2

這等價於:

   1: int x = bench.Elements()
   2:              .Where (e => e.Name == "toolbox")
   3:              .Count();                                                  // 2
   4:

Elements還定義了一個擴展方法接受IEnumerable<XContainer>參數. 更精確的說, 它接受了此種類型的參數:

   1: IEnumerable<T> where T : XContainer

這讓其可以和元素序列一起工作, 使用這個方法我們可以重寫查找hand tools的查詢:

   1: from tool in bench.Elements ("toolbox")
   2:                   .Elements ("handtool")
   3: select tool.Value.ToUpper( );

第一個Elements綁定到XContainer上, 第二個則綁定到擴展方法上.

讀取一個單一的元素

方法Element(單數)返回匹配給定名稱的第一個元素. Element對於簡單的導航是非常有用的, 例如:

   1: var settings = XElement.Load ("databaseSettings.XML");
   2:
   3: string cx = settings.Element ("database")
   4:                     .Element ("connectString")
   5:                     .Value;

Element的作用相當於調用Elements然後再應用LINQ的FirstOrDefault並給定一個名稱作為匹配斷言. 如果沒有任何元素匹配到, 則Element返回null.

如果元素xyz不存在, 那麼Element(”xyz”).Value將會拋出一個NullReferenceException異常. 如果你傾向於使用null代替異常, 可以將XElement轉換成string而不是調用它的Value屬性, 如下:

   1: string xyz =
   2:   (string) settings.Element("xyz");

XElement定義了一個顯示的string轉換正式為了這個目的.

遞歸功能

XContainer同時也定義了Descendants和DescendantNodes方法, 它們遞歸地返回子元素或者子節點.Descendant接受一個可選的元素名, 會到我們之前的例子, 我們可以使用Descendants去查找所有的hand tools:

   1: Console.WriteLine
   2:   (bench.Descendants ("handtool").Count( ));   // 3

不管是父節點還是葉節點都包含在整體橫切中. 以下的查詢取得所有包含單詞”careful”, 存在於X-DOM任何地方的注釋節點:

   1: IEnumerable<string> query =
   2:   from c in bench.DescendantNodes( ).OfType<XComment>( )
   3:   where c.Value.Contains ("careful")
   4:   orderby c.Value
   5:   select c.Value;

查詢父節點

所有的XNodes都有一個Parent屬性和AncestorXX的方法用於父節點導航. 一個父親節點永遠是一個XElement.

如果x是一個XElement, 以下代碼打印true:

   1: foreach (XNode child in x.Nodes( ))
   2:   Console.WriteLine (child.Parent == x);

如果x是一個XDocument的話, XDocument有點獨特, 它永遠不能作為任何節點的父親節點. 為了訪問XDocument,應該使用Document屬性, 這只爭對X-DOM樹上的任意對象可以工作.

Ancestors返回一個序列其第一個元素是Parent, 下一個元素則是Parent.Parent, 依次類推直到根元素.

你還可以使用LINQ查詢AncestorsAndSelf().Last()來取得輸入序列的根元素. 另外一種方法是調用Document.Root, 但只有當XDocument呈現的時候才能工作.

對等節點導航

使用PreviousNode和NextNode(FirstNode / LastNode),我們可以使用一個linked list橫貫所有的節點. 這並不是巧合, 在內部, Nodes實際上就是存儲在一個linked list.

屬性導航

XAttributes定義了PreviousAttribute和NextAttribute, Parent也是一樣.

Attributes方法接受了一個名稱並返回包含0或1個元素的序列; 在XML中, 一個元素不能包含重復的屬性名.

待續!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved