.Net FrameworkにはXML DOMを扱うクラスが用意されていますが、少々面倒だったりします。ここでは、System.Xml.Serialization名前空間にあるクラスを使い、XMLデータから自作クラスのオブジェクトを生成します。

次のようなXMLデータがあるとします。

<?xml version="1.0" encoding="utf-8"?>
<persons>
  <person id="0001">
    <name>一郎</name>
    <age>45</age>
    <birthday>2001/10/01</birthday>
  </person>
  <person id="0002">
    <name>二郎</name>
    <age>33</age>
    <birthday>2001/10/02</birthday>
  </person>
</persons>

このXMLデータは、personタグが繰り返す構造で、personタグには属性 “id” があり、この構造にあわせてロードするクラスを作成します。クラス及びプロパティに属性をそれぞれ定義し、XMLタグ名とクラス及びプロパティを結びつけます。タグ名とクラス名が同じ場合は属性を指定する必要はありませんが、大文字・小文字を判別します。また、シリアル化するクラスは PersonsModelクラスとPersonModelクラスはpublicにする必要があります。クラスメンバについても public なプロパティや変数が対象になります。メソッドは対象とせず、また、get/set の両方が可能である必要があります。

    [XmlRoot("persons")]
    public class PersonsModel
    {
        /// <summary>
        /// 人
        /// </summary>
        [XmlElement("person")]
        public List<PersonModel> Persons { get; set; }
    }
    public class PersonModel
    {
        /// <summary>
        /// ID
        /// </summary>
        [XmlAttribute("id")]
        public String ID { get; set; }
        /// <summary>
        /// 名前
        /// </summary>
        [XmlElement("name")]
        public String Name { get; set; }
        /// <summary>
        /// 年齢
        /// </summary>
        [XmlElement("age")]
        public String Age{ get; set; }
        /// <summary>
        /// 誕生日
        /// </summary>
        [XmlElement("birthday")]
        public String Birthday { get; set; }
    }

XMLデータをデシリアライズする場合、作成するクラスやプロパティに、XMLのタグやXML属性を対応付けしなければなりません。具体的には、クラスやプロパティに”属性”を与えることになります。与えられる属性の代表的なものを次に示します。

クラスやプロパティに与える属性の種類
属性の種類 説明
XmlRoot XMLルートエレメント(タグ)名
XmlElement XMLエレメント(タグ)名
XmlAttribute XMLエレメント(タグ)の属性(Attribute)
XmlText XMLエレメントの内容(テキスト)
XmlIgnore 無視して欲しいXMLエレメントの指定


では、実際にXMLファイル「demo.xml」をPersonModelクラスオブジェクトにロードします

    class Program
    {
        static void Main(string[] args)
        {
            //サンプルコード
            FileStream fs = new System.IO.FileStream(@"demo.xml", FileMode.Open);

            XmlSerializer serializer = new XmlSerializer(typeof(PersonsModel));

            PersonsModel model = (PersonsModel)serializer.Deserialize(fs);

            foreach (PersonModel person in model.Persons)
            {
                System.Console.WriteLine(String.Format("ID={0}, Name={1}, Age={2}, Birthday={3}", person.ID, person.Name, person.Age, person.Birthday));
            }
        }
    }

実行結果は次のようになります。

ID=0001, FirstName=一郎, Age=45, Birthday=2001/10/01
ID=0002, FirstName=二郎, Age=33, Birthday=2001/10/02

このように便利なXmlSerializerですが、XML化するクラスに次の制限があります。

  • シリアライズするクラスはバブリックでなければならない
  • デフォルトコンストラクタ(既定のコンストラクタ)は必須である
  • シリアライズされるフィールド・プロパティはパブリックなフィールド・プロパティのみ
  • 型情報(アセンブリ名・型名)はシリアライズされない
  • HashtableやDictionaryがシリアライズできね

しかし、LINQ to XMLの登場により、手書きで変換するのも手軽なってきており、こうして分かりにくい属性制御するぐらいなら、LINQ to XMLのXElementを使用するケースのほうが多いかもしれません。

また、オブジェクトの保存・復元用にはDataContractSerializerは無類の強さを発揮します。例えば、クラスを丸ごと設定用のXMLにシリアライズ・デシリアライズすると思いますが、Dictionaryや引数なしコントラクタがないクラスでもシリアライズできます。