【.NET】XMLファイルを DataSet に読み込み


はじめに

同僚がデータ修正ツールを作成する上で、ASP.NETでドロップボックスのリストを作成するサンプルを作成していた。
リストを作成する上で対象データをXMLファイルから読む込むようにしていたが、XMLデータの作り方で、DataSet のTableの生成方法が違っていたので幾つかのパターンを作成して調べてみました。

共通

ASP.NETのドロップボックスのリスト用クラス定義

public class ListViewModel
{
    public string Value;
    public string DisplayText;
}

Valueには値、DisplayTextは「値:名前」としている。

パターン1

Sample.xml
<?xml version="1.0" encoding="UTF-8" ?>
<Goods>
    <Good id = "1" lang="ja" name = "みかん" />
    <Good id = "2" lang="ja" name = "バナナ" />
    <Good id = "3" lang="ja" name = "いちご" />
    <Good id = "4" lang="ja" name = "りんご" />
    <Good id = "5" lang="ja" name = "ブドウ" />
</Goods>

ソースコード

DataSet dsGood = new DataSet();
dsGood.ReadXml("Sample.xml");

var items = dsGood.Tables["Good"].AsEnumerable().
            Select(x => new ListViewModel()
            {
                Value = x.Field<string>("id"),
                DisplayText = x.Field<string>("id") + ":" + x.Field<string>("name")
            });

var items2 = items;

パターン2

Sample2.xml
<?xml version="1.0" encoding="UTF-8" ?>
<Goods>
    <Good>
        <id>1</id>
        <lang>ja</lang>
        <name>りんご</name>
    </Good>
    <Good>
        <id>2</id>
        <lang>ja</lang>
        <name>バナナ</name>
    </Good>
    <Good>
        <id>3</id>
        <lang>ja</lang>
        <name>いちご</name>
    </Good>
    <Good>
        <id>4</id>
        <lang>ja</lang>
        <name>りんご</name>
    </Good>
    <Good>
        <id>5</id>
        <lang>ja</lang>
        <name>ブドウ</name>
    </Good>
</Goods>

ソースコード

パターン1とファイル名が違うのみ

DataSet dsGood = new DataSet();
dsGood.ReadXml("Sample2.xml");

var items = dsGood.Tables["Good"].AsEnumerable().
            Select(x => new ListViewModel()
            {
                Value = x.Field<string>("id"),
                DisplayText = x.Field<string>("id") + ":" + x.Field<string>("name")
            });

var items2 = items;

パターン3

Sample3.xml
<?xml version="1.0" encoding="UTF-8" ?>
<Goods>
    <Good id="1">
        <lang>ja</lang>
        <name>りんご</name>
    </Good>
    <Good id="2">
        <lang>ja</lang>
        <name>バナナ</name>
    </Good>
    <Good id="3">
        <lang>ja</lang>
        <name>いちご</name>
    </Good>
    <Good id="4">
        <lang>ja</lang>
        <name>りんご</name>
    </Good>
    <Good id="5">
        <lang>ja</lang>
        <name>ブドウ</name>
    </Good>
</Goods>

ソースコード

パターン1とファイル名が違うのみ

DataSet dsGood = new DataSet();
dsGood.ReadXml("Sample3.xml");

var items = dsGood.Tables["Good"].AsEnumerable().
            Select(x => new ListViewModel()
            {
                Value = x.Field<string>("id"),
                DisplayText = x.Field<string>("id") + ":" + x.Field<string>("name")
            });

var items2 = items;

パターン4

Sample4.xml
<?xml version="1.0" encoding="UTF-8" ?>
<Goods>
    <Good id="1">
        <name lang="ja">みかん</name>
    </Good>
    <Good id="2">
        <name lang="ja">バナナ</name>
    </Good>
    <Good id="3">
        <name lang="ja">いちご"</name>
    </Good>
    <Good id="4">
        <name lang="ja">りんご"</name>
    </Good>
    <Good id="5">
        <name lang="ja">ブドウ</name>
    </Good>
</Goods>


ソースコード

GoodテーブルとnameテーブルをIdで結合する必要があります。
nameテーブルには、親のGoodテーブルのIdがGood_Id列として自動で追加されます。
nameタグの名前は、_Textが列名に自動追加されて、name_Text列になります。

DataSet dsGood = new DataSet();
dsGood.ReadXml("Sample4.xml");

var items = from g in dsGood.Tables["Good"].AsEnumerable()
            join n in dsGood.Tables["name"].AsEnumerable() on g.Field<int>("Good_Id") equals n.Field<int>("Good_Id")
            select new ListViewModel()
            {
                Value = g.Field<string>("id"),
                DisplayText = g.Field<string>("id") + ":" + n.Field<string>("Name_Text")
            };

var items2 = items;

最後に

XMLデータを上手く解析されて DataSet にセットされるようになっています。
パターン4になった時に、親子テーブルに分かれるのでLINQで内部結合を使う必要があります。
タグに属性がついている場合など、列名に_Textが自動追加されたりします。