[C#]階層化された繰返し要素のXMLをデシリアライズする


XMLArray属性とXMLArrayItem属性を使い、階層化された繰り返し要素の構造を持つXMLファイルをでシリアライズする方法です



これまでXMLをデシリアライズする記事をこれまでいくつか書いてきました。

このページでは、System.Xml.Serialization.XmlArray属性を使って、階層化された繰返し要素のXMLをデシリアライズしてみます

読み込むXML

本サンプルコードが読み込むXMLファイルの内容は以下の通りです(ファイル名 system-config.xmlとします)

<?xml version="1.0" encoding="utf-8"?>
<system-config>
  <system-name>XXXXX</system-name>
  <version>1.1</version>
  <users>
    <user id="0001">
      <email>foo@example.com</email>
      <expired>2015/12/31</expired>
    </user>
    <user id="0002">
      <email>bar@example.com</email>
      <expired>2015/09/30</expired>
    </user>
  </users>
</system-config>

システム名とバージョン、されに、利用可能なユーザ情報が定義されているXMLファイルです。
XMLルートタグ”system-config”の下に、繰返し要素の親タグ”users”があり、”user”タグが繰返し定義される形です。
UsersクラスとUserクラスを作れば、繰返し部分はなんとなくデシリアライズできそうですが、XMLArray属性とXMLArrayItem属性を使えばUserクラスだけでデシリアライズできます

クラス設計

クラスは以下の2つになります。

  • SystemConfigクラス
  • Userクラス

SystemConfigクラスに以下のプロパティを用意します

  • SystemName
  • Version
  • Users ※List

また、Userクラスは以下のプロパティを持ちます

  • Id
  • Email
  • Expired

2つのクラスのコードは以下となります。

SystemConfigクラス

namespace Sample.Model
{
    /// <summary>
    /// システム設定
    /// </summary>
    [System.Xml.Serialization.XmlRoot("system-config")]
    public class SystemConfig
    {
        /// <summary>
        /// システム名
        /// </summary>
        [System.Xml.Serialization.XmlElement("system-name")]
        public string SystemName {get; set;}
        /// <summary>
        /// バージョン
        /// </summary>
        [System.Xml.Serialization.XmlElement("version")]
        public string Version { get; set; }
        /// <summary>
        /// ユーザ情報
        /// </summary>
        [System.Xml.Serialization.XmlArray("users")]
        [System.Xml.Serialization.XmlArrayItem("user")]
        public List<Sample.Model.User> Users { get; set; }
    }
}

ポイントは、プロパティ”Users”を定義している

        [System.Xml.Serialization.XmlArray("users")]
        [System.Xml.Serialization.XmlArrayItem("user")]
        public List<Sample.Model.User> Users { get; set; }

です。
XmlArray属性とXmlArray属性を指定して、階層化された繰返し構造を表現しています
続いてUserクラスです。

Userクラス

namespace Sample.Model
{
    /// <summary>
    /// ユーザ情報
    /// </summary>
    [Serializable]
    public class User
    {
        /// <summary>
        /// ID
        /// </summary>
        [System.Xml.Serialization.XmlAttribute("id")]
        public string Id { get; set; }
        /// <summary>
        /// メールアドレス
        /// </summary>
        [System.Xml.Serialization.XmlElement("email")]
        public string MailAddress {get; set;}
        /// <summary>
        /// 有効期限
        /// </summary>
        [System.Xml.Serialization.XmlElement("expired")]
        public string Expired { get; set; }
    }
}

デシリアライズするコード

デシリアライズするコードは以下となります

System.IO.FileStream fs = new System.IO.FileStream(@"system-config.xml", System.IO.FileMode.Open);
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(Sample.Model.SystemConfig));
Sample.Model.SystemConfig configModel = (Sample.Model.SystemConfig)serializer.Deserialize(fs);

Console.WriteLine(String.Format("SYSTEM={0}, Version={1}", configModel.SystemName, configModel.Version));
foreach (Sample.Model.User userModel in configModel.users)
{
    Console.WriteLine(String.Format("ID={0}, EMAIL={1}, EXPIRED={2}", userModel.Id, userModel.MailAddress, userModel.Expired));
}
fs.Close();

実行結果

SYSTEM=XXXXX, Version=1.1
ID=0001, EMAIL=foo@example.com, EXPIRED=2015/12/31
ID=0002, EMAIL=bar@example.com, EXPIRED=2015/09/30

はい。うまくデシリアライズできました