« IPMI | メイン | 書評 : UNIX magazine 最終号 »

2009年06月22日

Linq to XML 入門 その4 結合(JOIN)

しばらく間が開いてしまいすいませんです。前回は基本的なクエリーまで説明したので、今回からはもう少し複雑なクエリー式の説明をします。

今回はJOINを説明します。

JOIN(結合)はLinqにおいてもリレーショナルデータベースの結合と同じく一定の条件の下データ同士を関連付けます。

結合(Join)の概念がちょっとわかりにくいという方はSQLの入門書で結合(Join)について勉強してみるといいと思います。このJOINあたりからが実際にはLinqの非常に強力な使用方法になっていきます。リレーショナルデータベースのデータでもないものを簡単な書式でJoinできるというのは実はすごいことなのです。

説明に当たっては、どこかにあるかもしれないレストランを想定し、メニューのカテゴリが記述されたcategory.xmlとメニューのアイテムが記述されたmenu.xmlを使用します。アプリケーションとしてはこれら二つのXMLデータを結合(JOIN)して、メニューのリストを作ります。

各XMLデータは以下の通りで、ここからダウンロードすることもできます。

menu.xml

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <menu>
   3:   <item MenuId="1" CategoryId="1">
   4:     <name>コーラ</name>
   5:     <price>250</price>
   6:   </item>
   7:   <item MenuId="2" CategoryId="1">
   8:     <name>アイスコーヒー</name>
   9:     <price>250</price>
  10:   </item>
  11:   <item MenuId="3" CategoryId="1">
  12:     <name>ブレンドコーヒー</name>
  13:     <price>250</price>
  14:   </item>
  15:   <item MenuId="4" CategoryId="1">
  16:     <name>生ビール</name>
  17:     <price>400</price>
  18:   </item>
  19:   <item MenuId="5" CategoryId="2">
  20:     <name>フレンチフライ</name>
  21:     <price>400</price>
  22:   </item>
  23:   <item MenuId="6" CategoryId="2">
  24:     <name>湯で海老</name>
  25:     <price>800</price>
  26:   </item>
  27:   <item MenuId="7" CategoryId="2">
  28:     <name>チーズ盛り合わせ</name>
  29:     <price>1350</price>
  30:   </item>
  31:   <item MenuId="8" CategoryId="2">
  32:     <name>オニオングラタンスープ</name>
  33:     <price>1050</price>
  34:   </item>
  35:   <item MenuId="9" CategoryId="2">
  36:     <name>シェフのお任せミニサラダ</name>
  37:     <price>870</price>
  38:   </item>
  39:   <item MenuId="9" CategoryId="2">
  40:     <name>シェフのお任せスープ</name>
  41:     <price>870</price>
  42:   </item>
  43:   <item MenuId="10" CategoryId="3">
  44:     <name>御殿場高原で育った子羊のロースト</name>
  45:     <price>1800</price>
  46:   </item>
  47:   <item MenuId="11" CategoryId="3">
  48:     <name>あしたか牛のフィレ肉を使ったビーフシチュー</name>
  49:     <price>2500</price>
  50:   </item>
  51:   <item MenuId="12" CategoryId="3">
  52:     <name>沼津港スズキのグリル</name>
  53:     <price>2300</price>
  54:   </item>
  55:   <item MenuId="12" CategoryId="3">
  56:     <name>焼津マグロのカルパッチョ</name>
  57:     <price>2300</price>
  58:   </item>
  59:   <item MenuId="13" CategoryId="3">
  60:     <name>あしたか牛のサーロインステーキ</name>
  61:     <price>3200</price>
  62:   </item>
  63:   <item MenuId="14" CategoryId="4">
  64:     <name>韮山苺を使ったショートケーキ</name>
  65:     <price>650</price>
  66:   </item>
  67:   <item MenuId="15" CategoryId="4">
  68:     <name>西浦みかんのババロワ</name>
  69:     <price>550</price>
  70:   </item>
  71:   <item MenuId="15" CategoryId="4">
  72:     <name>朝霧高原の牛乳から作ったティラミス</name>
  73:     <price>550</price>
  74:   </item>
  75: </menu>

category.xml

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <Categories>
   3:   <Category id ="1">
   4:     <CategoryName>飲料</CategoryName>
   5:   </Category>
   6:   <Category id ="2">
   7:     <CategoryName>前菜</CategoryName>
   8:   </Category>
   9:   <Category id ="3">
  10:     <CategoryName>主菜</CategoryName>
  11:   </Category>
  12:   <Category id ="4">
  13:     <CategoryName>デザート</CategoryName>
  14:   </Category>
  15: </Categories> 

それではアプリケーションのコードです。

   1: XDocument menu = XDocument.Load(@"..\..\menu.xml");
   2: XDocument category = XDocument.Load(@"..\..\category.xml");
   3:  
   4: var menuList = from m in menu.Descendants("item")
   5:                join c in category.Descendants("Category")
   6:                on
   7:                 (string)m.Attribute("CategoryId")
   8:                equals
   9:                 (string)c.Attribute("id")
  10:                select new {
  11:                    MenuId = (string)m.Attribute("MenuId"),
  12:                    MenuName = (string)m.Element("name"),
  13:                    CategoryName = (string)c.Element("CategoryName"),
  14:                    Price = (int)m.Element("price")
  15:                };
  16: 
  17: foreach (var m in menuList) {
  18:     Console.WriteLine("お料理\t\t{0}", m.MenuName);
  19:     Console.WriteLine("お料理の種類\t{0}", m.CategoryName);
  20:     Console.WriteLine("お値段\t\t{0}", m.Price.ToString());
  21: }
  22:  
  23: Console.ReadLine();

1,2行目でXML文書を読み込みます。

5行目から今回新しく説明するポイントです。

5行目のjoin句で、4行目のfrom句でmenu.xmlから取り出したxmlのエレメントに結合するcategory.xmlのエレメントを指定します。

6行目からon句から始まり9行目までが結合条件で、この場合にはmenu.xml側が持つCategoryIdアトリビュートの値とcategory.xmlがもつidアトリビュートの一致をもって結合するようにしています。アトリビュート同士の値が同値であることの確認には"="(オペレータ)ではなくequals句を使う必要があります。正確には

from <左辺XML>

join <右辺XML>

on <左辺条件> equals <右辺条件>

となります。

今回示した例は内部結合(Inner Join)と呼ばれる結合方法です。左辺側(今回であればmenu.xml)と右辺側(Categoryxml)の両方で条件が一致したデータのみが結果として返されます。これ以外にLinqでは右辺のデータと一致するものが無くても左辺のデータをすべて返す左外部結合(Outer Join)もサポートしています。左外部結合に関しては以下のMSDNドキュメントを参考にしてください。

http://msdn.microsoft.com/ja-jp/library/bb311040.aspx

それではまた次回!

これまでの記事:

参考図書:

Essential LINQ (Microsoft .NET Development Series)
Essential LINQ (Microsoft .NET Development Series) Charlie Calvert

Addison-Wesley Professional 2009-03-22
売り上げランキング : 109833


Amazonで詳しく見る
by G-Tools
プログラミングMicrosoft LINQ (マイクロソフト公式解説書 Microsoft Visual Studi)
プログラミングMicrosoft LINQ (マイクロソフト公式解説書 Microsoft Visual Studi) 小高 太郎 (株)オーパス・ワン

日経BPソフトプレス 2009-05-25
売り上げランキング : 43591


Amazonで詳しく見る
by G-Tools

トラックバック

このエントリーのトラックバックURL:
http://www.isisaka.com/blog/mt-tb.cgi/3209

このリストは、次のエントリーを参照しています: Linq to XML 入門 その4 結合(JOIN):

» Linq to XML 入門その1 (XML文書の作り方) from OPC Diary
準備 これから数回に分けてLinq to XMLの基礎的な使い方についてまとめ... [続きを読む]

コメント

 

コメントしてください




保存しますか?


                 あわせて読みたい
クリエイティブ・コモンズ・ライセンス
このブログは、次のライセンスで保護されています。 クリエイティブ・コモンズ・ライセンス.