.Net(VB、C#)でLinq to XMLを利用してXMLを操作する
XMLドキュメントを簡単かつ効率的に作成・参照・更新できるようにするLinq to XMLを利用してXMLファイルを操作する。
using句の指定(C#の場合)
| 1 | using System.Xml.Linq; | 
using句でLinq to XMLの名前空間を呼出しておく。
尚、Visual Studioのソリューションエクスプローラで参照設定を確認し、System.XML.Linqの参照設定がない場合には追加する。
単純なXMLの表示
簡単なXMLのデータを作成し、コンソールに表示する。
| 1 2 | Dim x = New XElement("Name", "Jyunpei Ryuzouji") Console.WriteLine(x) | 
| 1 2 | var x = new XElement("Name", "Jyunpei Ryuzouji"); Console.WriteLine(x); | 
Nameという1種類の要素を持つXMLデータを作成し、コンソールに表示している。
Linq to XMLにおいて、XElementクラスがXML要素を表すクラスになる。
尚、Linq to XMLの各クラスは先頭に”X”がつく。
| 1 | <Name>Jyunpei Ryuzouji</Name> | 
XML要素に属性を追加して表示
XML要素に属性(Attribute)を追加する。
| 1 2 | Dim x = New XElement("Name", New XAttribute("ID", 99999), "Jyunpei Ryuzouji") Console.WriteLine(x) | 
| 1 2 | var x = new XElement("Name", new XAttribute("ID", 99999), "Jyunpei Ryuzouji"); Console.WriteLine(x); | 
XElementクラスのコンストラクタの中でXAttributeクラスを初期化し、IDという属性とその値として”99999″を追加する。
| 1 | <Name ID="99999">Tadahiro Ishisaka</Name> | 
Name要素にID属性が追加され、その値が”99999″となっている。
XElementクラスのAddメソッドを使用して属性を追加
XElementクラスのAddメソッドを使用して、XML要素に属性(Attribute)を追加する。
| 1 2 3 | Dim x = New XElement("Name", "Jyunpei Ryuzouji") x.Add(New XAttribute("ID", 99999)) Console.WriteLine(x) | 
| 1 2 3 | var x = new XElement("Name", "Jyunpei Ryuzouji"); x.Add(new XAttribute("ID", 99999)); Console.WriteLine(x); | 
| 1 | <Name ID="99999">Tadahiro Ishisaka</Name> | 
XML文書を作成する
Linq to XMLでXML文書(XML Document)を表すクラスはXDocumentクラスになる。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 'XML文書の作成 Dim Users = New XDocument( _     New XDeclaration("1.0", "utf-8", "yes"), _     New XElement( _         "Users", _         New XElement( _             "User", _             New XAttribute("ID", 99999), _             New XElement("Name", "Jyunpei Ryuzouji"), _             New XElement("Address", "Shizuoka") _         ), _         New XElement( _             "User", _             New XAttribute("ID", 88888), _             New XElement("Name", "Rituko Inoue"), _             New XElement("Address", "Fukuoka") _         ) _     ) _ ) '出力 Console.WriteLine(Users.Declaration) Console.WriteLine(Users) | 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | //XML文書の作成 var Users = new XDocument(    new XDeclaration("1.0", "utf-8", "yes"),    new XElement(         "Users",         new XElement(             "User",             new XAttribute("ID", 99999),             new XElement("Name", "Jyunpei Ryuzouji"),             new XElement("Address", "Shizuoka")         ),         new XElement(             "User",             new XAttribute("ID", 88888),             new XElement("Name", "Rituko Inoue"),             new XElement("Address", "Fukuoka")         )    ) ); //出力 Console.WriteLine(Users.Declaration); Console.WriteLine(Users); | 
上記はXDocumentクラスのコンストラクタですべてを記述している。
この程度であれば問題ないが、これ以上大きなXML文書を扱うには視認性が悪い。
尚、途中に出てくるXDeclarationクラスはXML宣言のクラス。
| 1 2 3 4 5 6 7 8 9 10 11 | <?xml version="1.0" encoding="utf-8" standalone="yes"?> <Users>     <User ID="99999">         <Name>Jyunpei Ryuzouji</Name>         <Address>Shizuoka</Address>     </User>     <User ID="88888">         <Name>Rituko Inoue</Name>         <Address>Fukuoka</Address>     </User> </Users> | 
XML文書を作成する(ノードごとに記述)
コードの視認性を良くする為にノードごとにXML要素を追加する。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 'XML文書の作成 Dim Users = New XDocument(New XDeclaration("1.0", "utf-8", "yes")) Users.Add(New XComment("ユーザリスト")) 'XMLコメントの追加 Users.Add(New XElement("Users")) 'Root Elementの作成 '1ノード目の追加 Dim temp = New XElement("User") temp.Add(New XAttribute("ID", 99999)) temp.Add(New XElement("Name", "Jyunpei Ryuzouji")) temp.Add(New XElement("Address", "Shizuoka")) Users.Root.Add(temp) '2ノード目の追加 temp = New XElement("User") temp.Add(New XAttribute("ID", 88888)) temp.Add(New XElement("Name", "Rituko Inoue")) temp.Add(New XElement("Address", "Fukuoka")) Users.Root.Add(temp) '3ノード目の追加 temp = New XElement("User") temp.Add(New XAttribute("ID", 77777)) temp.Add(New XElement("Name", "Airi Komiyama")) temp.Add(New XElement("Address", "Tokyo")) Users.Root.Add(temp) '出力 Console.WriteLine(Users.Declaration) Console.WriteLine(Users) | 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | //XML文書の作成 var Users = new XDocument(new XDeclaration("1.0", "utf-8", "yes")); Users.Add(new XComment("ユーザリスト")); //XMLコメントの追加 Users.Add(new XElement("Users")); //Root Elementの作成 //1ノード目の追加 var temp = new XElement("User"); temp.Add(new XAttribute("ID", 99999)); temp.Add(new XElement("Name", "Jyunpei Ryuzouji")); temp.Add(new XElement("Address", "Shizuoka")); Users.Root.Add(temp); //2ノード目の追加 temp = new XElement("User"); temp.Add(new XAttribute("ID", 88888)); temp.Add(new XElement("Name", "Rituko Inoue")); temp.Add(new XElement("Address", "Fukuoka")); Users.Root.Add(temp); //3ノード目の追加 temp = new XElement("User"); temp.Add(new XAttribute("ID", 77777)); temp.Add(new XElement("Name", "Airi Komiyama")); temp.Add(new XElement("Address", "Tokyo")); Users.Root.Add(temp); //出力 Console.WriteLine(Users.Declaration); Console.WriteLine(Users); | 
XML宣言を表すXDeclarationクラスのインスタンスはXDocumentクラスのコンストラクタの引数に渡す必要がある。
後からXDocumentクラスのAddメソッドで追加することは出来ない。(実行時エラーとなる)
また、XCommentクラスを使用するとXMLコメントを追加することが出来る。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <?xml version="1.0" encoding="utf-8" standalone="yes"?> <!--ユーザリスト--> <Users>     <User ID="99999">         <Name>Jyunpei Ryuzouji</Name>         <Address>Shizuoka</Address>     </User>     <User ID="88888">         <Name>Rituko Inoue</Name>         <Address>Fukuoka</Address>     </User>     <User ID="77777">         <Name>Airi Komiyama</Name>         <Address>Tokyo</Address>     </User> </Users> | 
XML文書の保存
XML文書を保存するにはXDocumentクラスのSaveメソッドを使用する。
| 1 2 | 'XML文書の保存 Users.Save(System.AppDomain.CurrentDomain.BaseDirectory + "Users.xml") | 
| 1 2 | //XML文書の保存 Users.Save(System.AppDomain.CurrentDomain.BaseDirectory + "Users.xml"); | 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <?xml version="1.0" encoding="utf-8" standalone="yes"?> <!--ユーザリスト--> <Users>     <User ID="99999">         <Name>Jyunpei Ryuzouji</Name>         <Address>Shizuoka</Address>     </User>     <User ID="88888">         <Name>Rituko Inoue</Name>         <Address>Fukuoka</Address>     </User>     <User ID="77777">         <Name>Airi Komiyama</Name>         <Address>Tokyo</Address>     </User> </Users> | 
上記の他にXMLWriterに渡して非同期で出力する方法、TextWriterに渡して同じく非同期で出力する方法、出力時に空白を削除する/しないのオプションがある。
XMLファイルの読込み
XMLファイルからデータを読込むには、XDocumentクラスのLoadメソッドを使用する。
| 1 2 3 4 5 | 'XML文書の読込み Console.WriteLine("XMLファイルを読込む") Dim ReadedUsers = XDocument.Load(System.AppDomain.CurrentDomain.BaseDirectory + "Users.xml") Console.WriteLine(ReadedUsers.Declaration) Console.WriteLine(ReadedUsers) | 
| 1 2 3 4 5 | //XML文書の読込み Console.WriteLine("XMLファイルを読込む"); var ReadedUsers = XDocument.Load(System.AppDomain.CurrentDomain.BaseDirectory + "Users.xml"); Console.WriteLine(ReadedUsers.Declaration); Console.WriteLine(ReadedUsers); | 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <?xml version="1.0" encoding="utf-8" standalone="yes"?> <!--ユーザリスト--> <Users>     <User ID="99999">         <Name>Jyunpei Ryuzouji</Name>         <Address>Shizuoka</Address>     </User>     <User ID="88888">         <Name>Rituko Inoue</Name>         <Address>Fukuoka</Address>     </User>     <User ID="77777">         <Name>Airi Komiyama</Name>         <Address>Tokyo</Address>     </User> </Users> | 
LoadメソッドもSaveメソッドと同様にオーバーロードされたメソッドがあり、URI指定によるXMLファイルの読込みやXMLReader、TextReaderからの読込みがサポートされている。
クエリ式を使用したLINQの記述
Linq to XMLなので勿論、LINQによるXML要素の取得が可能。
LINQの基本的なクエリ式は、以下の通り。
| 1 2 | from [範囲変数] in [データソース] select [範囲変数] | 
クエリ式はまず、from句から始める必要がある。
次に最低でもselect句で範囲変数を指定し、最終的に式が返すソースシーケンスの内容を確定する。
from句
 from [範囲変数] in [データソース]
from句ではクエリもしくはサブクエリの対象となるデータソースとソースシーケンス内の各要素を表すローカルの範囲変数を指定する。
尚、ソースシーケンスとはデータソースの中でクエリ式内での各操作の対象となる連続したデータのこと。
LINQのデータソースにはIEnumerable<T>インターフェイスあるいはIEnumerableとその派生インターフェイスを実装したオブジェクトだけを指定することができる。
通常の配列やArrayList、ADO.NETのデータセットはIEnumerableインターフェイスを持つ為、LINQの対象とすることができる。
selsct句
 select [式]
selsct句はクエリ式が実行されたときに生成される値の型を指定する。
クエリ式の結果はselect句の前の式の評価およびselect句の式の評価によって生成される。
select句の一番単純な例は式に範囲変数を指定し、ソースシーケンスをそのまま式の値とする方法。
where句
 whewe [条件式]
where句を利用することで、ソースシーケンスのデータに対して何らかのフィルタリング条件を付けて必要なデータだけを取得することが出来る。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 'XML文書の読込み Console.WriteLine("XMLファイルを読込む") Dim ReadedUsers = XDocument.Load(System.AppDomain.CurrentDomain.BaseDirectory + "Users.xml") Console.WriteLine(ReadedUsers.Declaration) Console.WriteLine(ReadedUsers) 'クエリ式の発行 Console.WriteLine("クエリ式を発行して値を取得") Dim query = _     From x In ReadedUsers.Descendants("User") _     Where x.Attribute("ID").Value = "88888" _     Select x '出力 For Each i In query     Console.WriteLine(i.Attribute("ID").Value + " : " + i.Element("Name").Value + " : " + i.Element("Address").Value) Next | 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | //XML文書の読込み Console.WriteLine("XMLファイルを読込む"); var ReadedUsers = XDocument.Load(System.AppDomain.CurrentDomain.BaseDirectory + "Users.xml"); Console.WriteLine(ReadedUsers.Declaration); Console.WriteLine(ReadedUsers); //クエリ式の発行 Console.WriteLine("クエリ式を発行して値を取得"); var query =     from x in ReadedUsers.Descendants("User")     where x.Attribute("ID").Value == "88888"     select x; //出力 foreach (var i in query) {     Console.WriteLine(i.Attribute("ID").Value + " : " + i.Element("Name").Value + " : " + i.Element("Address").Value); } | 
通常、特定の要素を検索対象とするには正確に木構造を辿る形で指定していく必要がある。
しかし、Linq to XMLではDescendantsで要素名を指定すれば木構造を辿らずダイレクトに指定する事が出来る。
上記は、ID属性が”88888″のユーザ情報をコンソールに表示している。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | XMLファイルを読込む <?xml version="1.0" encoding="utf-8" standalone="yes"?> <!--ユーザリスト--> <Users>     <User ID="99999">         <Name>Jyunpei Ryuzouji</Name>         <Address>Shizuoka</Address>     </User>     <User ID="88888">         <Name>Rituko Inoue</Name>         <Address>Fukuoka</Address>     </User>     <User ID="77777">         <Name>Airi Komiyama</Name>         <Address>Tokyo</Address>     </User> </Users> クエリ式を発行して値を取得 88888 : Rituko Inoue : Fukuoka | 
メソッドベースでのLINQの記述
メソッドベースでもLINQの記述が可能。
| 1 2 3 4 5 6 7 8 9 10 11 | 'XML文書の読込み Console.WriteLine("XMLファイルを読込む") Dim ReadedUsers = XDocument.Load(System.AppDomain.CurrentDomain.BaseDirectory + "Users.xml") Console.WriteLine(ReadedUsers.Declaration) Console.WriteLine(ReadedUsers) 'メソッドベース(ラムダ式)でLINQを記述 Console.WriteLine("メソッドベース(ラムダ式)で値を取得") Dim lambda = ReadedUsers.Descendants("User").Where(Function(x) x.Attribute("ID").Value = "99999") For Each i In lambda     Console.WriteLine(i.Attribute("ID").Value + " : " + i.Element("Name").Value + " : " + i.Element("Address").Value) Next | 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | //XML文書の読込み Console.WriteLine("XMLファイルを読込む"); var ReadedUsers = XDocument.Load(System.AppDomain.CurrentDomain.BaseDirectory + "Users.xml"); Console.WriteLine(ReadedUsers.Declaration); Console.WriteLine(ReadedUsers); //メソッドベース(ラムダ式)でLINQを記述 Console.WriteLine("メソッドベース(ラムダ式)で値を取得"); var lambda = ReadedUsers.Descendants("User").Where(x => x.Attribute("ID").Value == "99999"); //出力 foreach (var i in lambda) {     Console.WriteLine(i.Attribute("ID").Value + " : " + i.Element("Name").Value + " : " + i.Element("Address").Value); } | 
上記は、ID属性が”99999″のユーザ情報をコンソールに表示している。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | XMLファイルを読込む <?xml version="1.0" encoding="utf-8" standalone="yes"?> <!--ユーザリスト--> <Users>     <User ID="99999">         <Name>Jyunpei Ryuzouji</Name>         <Address>Shizuoka</Address>     </User>     <User ID="88888">         <Name>Rituko Inoue</Name>         <Address>Fukuoka</Address>     </User>     <User ID="77777">         <Name>Airi Komiyama</Name>         <Address>Tokyo</Address>     </User> </Users> メソッドベース(ラムダ式)で値を取得 99999 : Jyunpei Ryuzouji : Shizuoka | 
