.netで XMLファイルを読む方法はいろいろあるが、そのうちもっとも容易と思われる
『ファイルを直接 DataSetに読み込む』という方法を ちかごろ試しに使っている。
例えば、仮の題材として ASP.net での Web.Config を使うとする。
<configuration>
<system.web>...(略)...</system.web>
<appSettings>
<add key="foo" value="VAR" />
</appSettings>
</configuration>
ASP.netでは 各アプリケーション用に定義した項目を取得するには
それ専用のメソッドを使用するのがもっとも簡単。
これに相当することを、コード(XMLファイルとして読み込み、DataSetとする)で処理するには、
以下のようにする。
DataSet ds= new DataSet();
ds.ReadXml( @"c:\inetpub\wwwroot\hogehoge\Web.Config" );
DataRow dr= ds.Tables["appSettings"].Select("")[0].GetChildRows("appSettings_add")[0].Table.Select("key='foo'")[0];
string sRetValue= (dr.ItemArray.GetValue(1)).ToString();
なんと DataSet.ReadXml というメソッドが『<appSettings>』と『<add>』というタグをデータベースの
テーブルに見立てて、親子関係(リレーション:この場合“appSettings_add”と勝手に命名される)が
あるものと自動的に認識してくれるのだ。
本来、厳密には .XSDというスキーマファイルを作成しなくてはいけないが、
なくてもかなりの程度までは柔軟に解釈してくれる。
すばらしい。
・・・しかし、これには欠点があった。
データの構造が以下のようになったとしよう。
<configuration>
<system.web>...(略)...</system.web>
<appSettings Page="pg1">
<add key="foo" value="HOGE" />
</appSettings>
<appSettings Page="pg2">
<add key="foo" value="VAR" />
</appSettings>
</configuration>
『<appSettings>』を“Page”という条件別に分けたとする。
気持ち的には以下のように『<appSettings>』の“Page='pg2'”で絞った結果だけを取得したい。
DataRow dr= ds.Tables["appSettings"].Select("Page='pg2'")[0].GetChildRows("appSettings_add")[0].Table.Select("key='foo'")[0];
string sRetValue= (dr.ItemArray.GetValue(1)).ToString();
しかし、実際試してみると上記コードの2個目の .Select メソッドは、親テーブルの条件を考慮しないで
再度フル検索をかけるようで、上記例では複数の結果が得られる。
そのままでは期待する2件目の“VAR”ではなく1件目の“HOGE”が取れることになってしまう。
試行錯誤を重ねた結果だが、この症状を回避するには、今のところ下のようなやり方しか見つけていない。
foreach ( DataRow dr in ds.Tables["appSettings"].Select("Page='pg2'")[0].GetChildRows("appSettings_add")[0].Table.Select("key='foo'") ) {
if ( dr.GetParentRow("appSettings_add").ItemArray.GetValue(1).ToString() == "pg2" )
{ sRetValue= (dr.ItemArray.GetValue(1)).ToString(); }
}
つまり、見つけた DataRow の親の Page条件が何なのかをループでまわしながら1件ずつ再度確認するのだ。
なんと不毛な・・・。
もっと良い方法があったら、誰か教えて。