DBに保存されているデータをXML形式で受け取り、
LINQ to XMLの技術を用いて、そのXMLを簡単に解析するためのコードです。
(DB → XML → 解析)
手軽さから、DBはSQLiteを使いました。
なので、nugetでSQLiteのパッケージを導入します。
DBに格納するテスト用のデータは、大阪環状線の駅情報です。
「駅データ.jp」で公開している駅情報をそのままDBに保存して使わせて頂きました。
- DBからデータ取得
- 取得したデータをXMLに変更
- そのXMLを解析
1.DBからデータを取得
DBは以下の様な構造です。(stationテーブル)
station_name | lon | lat |
---|---|---|
天王寺 | 135.514124 | 34.647243 |
新今宮 | 135.501076 | 34.650149 |
... | ... | ... |
寺田町 | 135.523437 | 34.647957 |
以下のようなクラスを作成しました。
public class SQLiteIF
{
/// <summary>
/// 駅情報一覧をXML形式で取得
/// </summary>
/// <param name="dbFilePath">.dbファイルのフルパス</param>
static public string GetStations( string dbFilePath )
{
// 取得したレコードをListで保持します。
// 取得したデータはすべてstring型とする。
List<Dictionary<string, string>> stationRecords = new List<Dictionary<string, string>>();
// DBに接続して、クエリを実行する。
using ( var sqliteConn = new SQLiteConnection( "Data Source=" + dbFilePath ) )
{
sqliteConn.Open();
using ( SQLiteCommand command = sqliteConn.CreateCommand() )
{
// クエリ実行
command.CommandText = "SELECT * from station";
using ( SQLiteDataReader reader = command.ExecuteReader() )
{
// 一行一行読み込んでいく
while ( reader.Read() )
{
// Listに追加
Dictionary<string, string> record = new Dictionary<string, string>() {
{ "stationName", reader["station_name"].ToString() },
{ "longitude", reader["lon"].ToString() },
{ "latitude", reader["lat"].ToString()}
};
stationRecords.Add( record );
}
}
}
sqliteConn.Close();
}
// ルート部分のエレメントオブジェクト作成
XElement rootElement = new XElement( "records" );
// ルートに対して子のエレメントを追加していく
foreach ( var record in stationRecords )
{
XElement el = new XElement( "record",
from keyValue in record
select new XElement( keyValue.Key, keyValue.Value )
);
rootElement.Add( el );
}
return rootElement.ToString();
}
}
取得したレコード情報は、一時的に全てDictionaryに格納しています。
Dictionary<string, string> record = new Dictionary<string, string>() {
{ "stationName", reader["station_name"].ToString() },
{ "longitude", reader["lon"].ToString() },
{ "latitude", reader["lat"].ToString()}
};
上記DictionaryをListにAddして、複数のレコード情報を保持しました。
2.取得したデータをXMLに変換
LINQ to XMLを使えば、簡単にXML形式の文字列が作成出来ます。
// ルート部分のエレメントオブジェクト作成
XElement rootElement = new XElement( "records" );
// ルートに対して子のエレメントを追加していく
foreach ( var record in stationRecords )
{
XElement el = new XElement( "record",
from keyValue in record
select new XElement( keyValue.Key, keyValue.Value )
);
rootElement.Add( el );
}
return rootElement.ToString();
LINQのクエリを使うと、簡単にXElementオブジェクトの作成が行えます。
もしかしたら、foreachしなくても一発でXElementオブジェクトが作成出来るかもしれません。
偉い人教えてください……。
XElementオブジェクトさえ出来てしまえば、
後は、ToString()を行うだけでXMLのストリームが作成出来ます。
<records>
<record>
<stationName>天王寺</stationName>
<longitude>135.514124</longitude>
<latitude>34.647243</latitude>
</record>
<record>
<stationName>新今宮</stationName>
<longitude>135.501076</longitude>
<latitude>34.650149</latitude>
</record>
……
<record>
<stationName>寺田町</stationName>
<longitude>135.523437</longitude>
<latitude>34.647957</latitude>
</record>
</records>
ちなみにXElementを使うには、以下のusing宣言が必要です。
using System.Xml.Linq;
3.そのXMLを解析
DictionaryからXMLを作成するためにXElementを使用しましたが、
解析する場合もXElementを使用します。
class Program
{
static void Main( string[] args )
{
// XMLストリームを取得
string xmlStream = SQLiteIF.GetStations( ".dbファイルのフルパスを指定" );
// XMLストリームからXElementオブジェクトを作成する場合は、
// LoadではなくParseを使うこと。
XElement stationsElement = XElement.Parse( xmlStream );
// <record>要素のコレクションを取得
IEnumerable<XElement> stations = stationsElement.Elements( "record" );
// <record>に属している要素から、必要な情報を取得する
foreach ( var stationElement in stations )
{
Console.WriteLine( string.Format( "駅名: {0}", stationElement.Element( "stationName" ).Value ) );
Console.WriteLine( string.Format( "緯度: {0}", stationElement.Element( "latitude" ).Value ) );
Console.WriteLine( string.Format( "経度: {0}", stationElement.Element( "longitude" ).Value ) );
Console.WriteLine();
}
}
}
■ 実行結果
駅名: 天王寺
緯度: 34.647243
経度: 135.514124駅名: 新今宮
緯度: 34.650149
経度: 135.501076……
駅名: 寺田町
緯度: 34.647957
経度: 135.523437
関連サイト
- 駅データ.jp
http://www.ekidata.jp/ - LINQ to XML を使用してディクショナリを操作する (C#)
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/concepts/linq/how-to-work-with-dictionaries-using-linq-to-xml - SQLite
https://www.sqlite.org/