LINQ to XMLでのナビゲーション系のプロパティについて.
過去の内容は以下から見れます。よろしければご参照くださいませ。
今回は子孫要素を取得するDescendantsメソッドと先祖要素を取得するAncestorsメソッドです。
2つとも、個人的にはLINQ to XMLの中で最もよく利用するメソッドの一つです。
Descendantsメソッドは、XContainerクラスに所属するメソッドです。
Ancestorsメソッドは、XNodeクラスに所属するメソッドです。
どちらも、引数無しとXNameを受け取るオーバーロードを持っています。
引数無しの方は、自分を起点として子孫または先祖の要素を取得します。
引数有りの方は、自分を起点とした子孫または先祖の中に指定したXNameを持つ要素を探してくれます。
注意点として
- Descendantsメソッドの方は、ネストした子孫要素のデータも取得できる。
- Ancestorsメソッドの方は、自分よりも上に存在する兄弟要素は取得できない。あくまで先祖の要素が取得対象となる。
- Ancestorsメソッドで返されるコレクションは、ドキュメントの逆順になっている。
というのがあります。
以下、サンプルです。
namespace Gsf.Samples { using System; using System.Collections.Generic; using System.Linq; using System.Xml.Linq; #region LinqSamples-76 /// <summary> /// LINQ to XMLのサンプルです. /// </summary> /// <remarks> /// ナビゲーション(Descendants, Ancestorsメソッド)のサンプルです. /// </remarks> public class LinqSamples76 : IExecutable { public void Execute() { // // Descendants(XName) // 現在の要素を起点として子孫要素を取得する. // 子孫の範囲は、直下だけでなく、ネストした子孫階層のデータも // 取得できる. Linq To XMLでよく利用するメソッドの一つ. // var root = BuildSampleXml(); var elem = root.Descendants(); Console.WriteLine("Count={0}", elem.Count()); Console.WriteLine("====================================="); // "Customer"という名前の子孫要素を取得 elem = root.Descendants("Customer"); Console.WriteLine("Count={0}", elem.Count()); Console.WriteLine("First item:"); Console.WriteLine(elem.First()); Console.WriteLine("====================================="); // 属性付きで絞り込み elem = root.Descendants("Customer").Where(x => x.Attribute("CustomerID").Value == "HUNGC"); Console.WriteLine("Count={0}", elem.Count()); Console.WriteLine("First item:"); Console.WriteLine(elem.First()); Console.WriteLine("====================================="); // クエリ式で利用 elem = from node in root.Descendants("Customer") let attr = node.Attribute("CustomerID").Value where attr.StartsWith("L") from child in node.Descendants("Region") where child.Value == "CA" select node; Console.WriteLine("Count={0}", elem.Count()); Console.WriteLine("First item:"); Console.WriteLine(elem.First()); Console.WriteLine("====================================="); // 直接2階層下の要素名を指定 elem = from node in root.Descendants("Region") where node.Value == "CA" select node; Console.WriteLine("Count={0}", elem.Count()); Console.WriteLine("First item:"); Console.WriteLine(elem.First()); Console.WriteLine("====================================="); // // Ancestors(XName) // 現在の要素の先祖要素を取得する. // 兄弟要素は取得できない(件数が0件となる) // あくまで自分の先祖となる要素を指定する. // root = BuildSampleXml(); var startingPoint = root.Descendants("Region").Where(x => x.Value == "CA").First(); var ancestors = startingPoint.Ancestors(); Console.WriteLine("Count={0}", ancestors.Count()); Console.WriteLine("First item:"); Console.WriteLine(ancestors.First()); Console.WriteLine("====================================="); // ContactNameは、現在の要素(Region)の先祖(FullAddress)ではないため指定しても取得できない ancestors = startingPoint.Ancestors("ContactName"); Console.WriteLine("Count={0}", ancestors.Count()); if (ancestors.Any()) { Console.WriteLine("First item:"); Console.WriteLine(ancestors.First()); } Console.WriteLine("====================================="); // FullAddress要素の兄弟要素となるContactNameは取得できない startingPoint = root.Descendants("FullAddress").First(); ancestors = startingPoint.Ancestors("ContactName"); Console.WriteLine("Count={0}", ancestors.Count()); if (ancestors.Any()) { Console.WriteLine("First item:"); Console.WriteLine(ancestors.First()); } Console.WriteLine("====================================="); // FullAddress要素の先祖であるCustomer要素は取得できる. startingPoint = root.Descendants("FullAddress").First(); ancestors = startingPoint.Ancestors("Customer"); Console.WriteLine("Count={0}", ancestors.Count()); if (ancestors.Any()) { Console.WriteLine("First item:"); Console.WriteLine(ancestors.First()); } Console.WriteLine("====================================="); } XElement BuildSampleXml() { // // サンプルXMLファイル // see: http://msdn.microsoft.com/ja-jp/library/vstudio/bb387025.aspx // return XElement.Load(@"xml/CustomersOrders.xml"); } } #endregion }
実行すると以下のようになります。
Count=356 ===================================== Count=4 First item:===================================== Count=1 First item: Great Lakes Food Market Howard Snyder Marketing Manager (503) 555-7555 2732 Baker Blvd. Eugene OR 97403 USA ===================================== Count=1 First item: Hungry Coyote Import Store Yoshi Latimer Sales Representative (503) 555-6874 (503) 555-2376 City Center Plaza 516 Main St. Elgin OR 97827 USA ===================================== Count=1 First item: Let's Stop N Shop Jaime Yorres Owner (415) 555-5938 87 Polk St. Suite 5 San Francisco CA 94117 USA CA ===================================== Count=4 First item:87 Polk St. Suite 5 ===================================== Count=0 ===================================== Count=0 ===================================== Count=1 First item:San Francisco CA 94117 USA ===================================== Great Lakes Food Market Howard Snyder Marketing Manager (503) 555-7555 2732 Baker Blvd. Eugene OR 97403 USA
以下、参考リソースです.
- XElement.Descendants メソッド
- XElement.Ancestors メソッド
================================
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ
サンプルコードは、以下の場所で公開しています。
- いろいろ備忘録日記サンプルソース置き場