階層構造のXMLから楽々と情報を取得する、LINQのクエリ構文の続き。
昨日のエントリについて、MVP for LINQたる@neueccさんからいろいろ教えてもらい、メソッド構文でも、もっと単純にできることがわかりました。
今回も、対象は次のようなXMLです。
<rsp stat=""ok"">
<root>
<parent id=""1"">
<child id=""101"">
<item id=""10101"" />
<item id=""10102"" />
</child>
<child id=""102"">
<item id=""10201"" />
</child>
</parent>
<parent id=""2"">
<child id=""201"">
<item id=""20101"" />
</child>
</parent>
</root>
</rsp>
1.XElement.Descendantsメソッドを使う方法
XContainer.Descendants メソッド (XName) (System.Xml.Linq)
このドキュメントまたは要素の子孫要素のフィルター処理されたコレクションをドキュメント順に返します。 一致する XName がある要素のみがコレクションに含められます。
を使い、item要素を列挙し、parent、child要素はXObject.Parent プロパティ (System.Xml.Linq)を通して取得する方法です。
var q = XElement.Parse(rsp).Descendants("item")
.Select(item => new
{
Parent = item.Parent.Parent,
Child = item.Parent,
Item = item
});
すっきりはしますが、item.Parent.Parentのあたりはちょいと分かりづらいですね。
2.SelectManyの中でSelectを使う方法
昨日の例ではSelectManyの中でListに詰め替えることで、無理やりフラットにしていましたが、単純にSelectメソッドを使うだけでよかったみたいです。
var q = XElement.Parse(rsp).Element("root")
.Elements("parent")
.Select(parent => new { Parent = parent, Childs = parent.Elements("child") })
.SelectMany(xs => xs.Childs.Select(child => new { Parent = xs.Parent, Child = child, Items = child.Elements("item") }))
.SelectMany(ys => ys.Items.Select(item => new { Parent = ys.Parent, Child = ys.Child, Item = item }));
確認してませんが、クエリ式はこのパターンのようなコードになるような気がします。
※ILSpyで前回のクエリ式方式の方のアセンブリを見てみましたが、クエリ式のまま復元されてて確認できず・・・
というわけで
やり方によって、メソッド構文でもある程度シンプルにすることは可能でした。LINQは奥深いですね。