LoginSignup
3
8

More than 5 years have passed since last update.

C#での、XDocument+LINQを使ったXMLからクラスへの読み込み

Last updated at Posted at 2017-05-28

最近Visual Studio for Macを入れたのをいいことに、Xamarinでのアプリ作成をしています。
XMLデータを読み込む際には、XDocument、XElementを使うのが基本のようです。
(XmlElementはXamarinでは使えない)
これを読み込みクラスにマッピングする際に工夫した点などを書いていきたいと思います。

読み込む対象

今作っているアプリは、XMLで保存された多種類のデータの中から、条件を満たす検索を行い結果を返却するアプリです。
そして、RDBのテーブルのように各データごとにファイルが分かれています。

HumanData.xml - 人についてのデータが入っている
JewerlyData.xml - 宝石についてのデータが入っている
RingData.xml - 指輪についてのデータが入っている。

のような感じです。(わけあって、RDBに変換はしたくないです)
ここでは、以下のようなRingData.xmlを読み込んでみたいと思います。

RingData.xml
<?xml version="1.0" encoding="utf-8"?>
<Ring>
  <RingType TypeName="宝石系">
    <Data No="31" ID="0880" Name="ダイヤモンド指輪">
      <Option Type="3">サイズ+5,金リング</Option>
      <Option Type="2">サイズ+4</Option>
      <Option Type="1">基本</Option>
          </Data>
    <Data No="7" ID="0890" Name="サファイヤ指輪">
      <Option Type="3">サイズ+3,金リング</Option>
      <Option Type="2">サイズ+2</Option>
      <Option Type="1">基本</Option>
    </Data>
  </RingType>
</Ring>

XDocument+LINQでオブジェクトに読み込むまで

PCLStorageの利用

まず、PCLStorageを利用して、ローカルのXMLデータをplatform依存なしに読み込めるようにします。
NugetパッケージにPCLStorageを追加しておきます。

PCLStorageについてはgithubのテストコードを読むとだいたい使い方がわかると思います。

クラスの用意

ring.cs
public class Ring{
    public string Name{get;set;}
    public string TypeName { get;set;}
    public Option[] Options;
    public int Id {get;set;}
}
public class Option{
   public int Type {get;set;}
   public string Value { get;set;}
}

読み込み

書き方は色々あると思いますが、以下のように読み込むことにしました。
LINQの書き方は
http://fernweh.jp/b/linqtoobject/ 
を参考にさせて頂きました。
商品名のキーをもったDictionaryに格納します

readingXml.cs
  var file = await SubFunc.MakeFileInterfaceAsync("data", "RingData.cs");
  var ret = new Dictionary<string,Ring>();
using (var stream = await file.OpenAsync(FileAccess.Read)){
      XElement root = XDocument.Load(stream).Root;

      var e2 = root.Elements("RingType");
                    var e3 = e2.SelectMany(i => i.Elements("Data"));
                    var q = from element in e3
                            let name= (element as XElement).Attribute("Name")
                            let id= (element as XElement).Attribute("ID")
                            where xAttribute != null
                            let xElement = element.Parent
                            where xElement != null
                            let typeAttr= xElement.Attribute("TypeName")
                            where typeAttr!= null
                            select new Ring
                            {
                                Name = name.Value,
                                Id= int.Parse(id.Value),
                                TypeName= typeAttr.Value,
                                Option = (from qoption in element.Elements("Option")
                                               select new Option
                                               {Type=int.Parse(qoption.Attribute("Type")),
                                                Value=qoption.Value}).ToArray()
                           };


                    ret = q.ToDictionary(skill => skill.Name);
}

といった要領で読み込むことができます。
MakeFileInterfaceAsync は、PCLStorageのIFileインターフェースを返却します。
LINQの理解が浅いので書き方が変なところもありますので、ご指摘お願いします。

3
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
8