LINQ to XMLを使ってXMLのデータにアクセスする

文:Tony Patton(Special to TecRepublic) 編集校正:石橋啓一郎
2008-01-31 08:00:00
  • このエントリーをはてなブックマークに追加

 私はすでに.NET Language-Integrated Query(LINQ)の基本(英語)について説明し、LINQからバックエンドのSQLサーバを利用するための情報(英語)を提供した。この記事では、LINQ技術の持つもっとも刺激的な側面の1つである、XMLの処理に焦点を当てる。LINQ to XMLによるXMLの処理は、その他の面倒なアプローチに比べれば遙かにきれいなアプローチとなる。

LINQ to XMLの基本

 LINQ to XMLは.NET 3.5で提供されている組み込みのLINQデータプロバイダだ。これはSystem.Xml.Linq名前空間で提供される。LINQ to XMLを使うと、XMLベースのデータの作成と読み書きが可能になる。XMLのデータソースはファイルでも、メモリ上のXMLでも、HTTPなどのプロトコル経由でアクセスする遠隔リソースでもよい。

 System.Xml.Linq名前空間のXDocumentクラスには、XMLデータの処理を単純化するさまざまなメソッドやプロパティがある。次のリストは、それらのメソッドやプロパティの例だ。

  • Add:XML文書に要素を加える。
  • AddFirst:XML文書の一番上に新しい要素を加える。
  • Ancestors:要素の先祖にアクセスする。
  • Descendants: 特定の要素の子孫にアクセスする。
  • Element:XML文書の中にある個別の要素にアクセスする。
  • FirstNode:要素の最初の子ノードを返す。
  • IsAfter:ドキュメント順に基づいて、現在のノードを指定したノードの後に表示するかどうかを判定する。
  • IsBefore:ドキュメント順に基づいて、現在のノードを指定したノードの前に表示するかどうかを判定する。
  • LastNode:要素の最後の子ノードを返す。
  • NextNode:現在のノードの次の兄弟ノードを返す。
  • PreviousNode:現在のノードの前の兄弟ノードを返す。
  • RemoveNodes:文書あるいは要素の子ノードを削除する。
  • Root:その文書のXMLツリーのルート要素を得る。
  • Save:XDocumentオブジェクトをシリアル化し、ファイル、TextWriterオブジェクト、あるいはXmlWriterオブジェクトにする。
  • WriteTo:XML文書をXmlWriterオブジェクトに書き込む。

 これらのメソッドとプロパティは、LINQ to XMLによる処理の氷山の一角に過ぎない。System.Xml.Linq名前空間には、XMLのあらゆる側面に対するクラスとそれ以上のものが含まれており、例えばXComment、XDeclaration、XElement、XName、XNamespace、XElemen、XObjectなどがある。MSDNでは、System.Xml.Linq名前空間に関するより多くの情報が提供されている。

 LINQ to XMLは、System.Xml名前空間の中のXmlReaderとXmlWriterを使うといった他のアプローチに比べずっと単純だ。どれだけ簡単に使えるかを示すには、例を見てもらうのがいいだろう。

実例

 次の例のXMLでは、sitesと呼ばれるルートノードでXML文書を定義している。このルートノードは、siteと呼ばれるnameとurlを持つノードを1つ以上持つ。site要素には、technicalと呼ばれる属性がある。




TechRepublic
techrepublic.com.com


News
www.news.com


CNET
www.cnet.com


GameSpot
www.gamespot.com


 XML文書のデータを読み込み、nameとurlの要素に保持されている値を表示する。次のC#のコードはローカルファイルからXMLをXDocumentオブジェクトに読み込むものだ。表示する項目を選択するには、from節の中でXDocumentのDecendantsプロパティが使われる。ここでは基本的に、XML文書のすべてのsite要素に対してクエリーを行っている。最後に、foreachブロックを使ったループの中で、select文でロードされたすべてのsite要素に対し処理が行われ、Consoleオブジェクトを通じて表示が行われる。

XDocument xmlDoc = XDocument.Load(@"c:sites.xml");
var q = from c in xmlDoc.Descendants("site")
select (string)c.Element("name") + " -- " +(string)c.Element("url");
foreach (string name in q) {
Console.WriteLine("Site: " + name);
}

 次の例では、この概念を推し進め、where節を使ったデータをフィルタリングを行っている。このコードの断片では、technical属性がtrueの値を持つsite要素だけを選択し、表示するものだ。このwhere節ではAttributeプロパティを使って適切な値を持っているかどうかをチェックしている。

XDocument xmlDoc = XDocument.Load(@"c:sites.xml");
var q = from c in xmlDoc.Descendants("site")
where c.Attribute("technical").Value == "true"
select (string)c.Element("name") + " ==>" + (string)c.Element("url");
foreach (string name in q) {
Console.WriteLine("Site: " + name);
}

 LINQでは実行中に匿名型を定義することができる。これを説明するために、例をもう少し拡張してみよう。次のコードの断片では、nameとurlという2つのプロパティを持つ匿名型を実行中に定義している。これは、select節のnewというキーワードで作られ、プロパティはnew命令の波括弧で囲われた部分で定義されている。foreachブロックからこの新しいタイプがアクセスされ、それぞれのプロパティを使って値の表示が行われる。

XDocument xmlDoc = XDocument.Load(@"c:sites.xml");
var q = from c in xmlDoc.Descendants("site")
where c.Attribute("technical").Value == "true"
select new {
name = c.Element("name").Value,
url = c.Element("url").Value
};
foreach (var obj in q) {
Console.WriteLine ("Site: " + obj.name + " -- " + obj.url);
}
  • 新着記事
  • 特集
  • ブログ