C#でXMLの読み書きをしてみた

C#でXMLを読み書きしてみました。XmlSerializerを使う方法です。 このサイト を思いっきり参考にしました。

この投稿の実施例は、下記環境のものです。

  • Visual Studio Express 2015 for Windows Desktop (C#)

  • Windows 8.1

目次

  1. どうやってデータを格納するか
  2. 処理の流れ
    1. 読み込み
    2. 書き出し
  3. 試してみた
    1. 読み込むXMLファイル
    2. クラス
    3. 処理
    4. 実行してみた

どうやってデータを格納するか

データ格納用のクラスを作るのですが、XMLの構造に合わせる必要があります。以下、注意点です。

  • XMLの構造に合わせたクラスを作る。

  • 子ノードが複数ある場合は、親ノード用のクラスに設定する子ノード用プロパティをコレクションにする。

  • クラスとそのプロパティの属性でXMLの要素名を指定する。

  • 逆シリアル化したときに、要素に値が無くてもエラーにならない。

  • シリアル化したときに、値が無い要素は書き出さない。

処理の流れ

XMLの読み込みと書き出しは、ざっくりと下記の流れになります。

読み込み

  1. 読み込むファイルを指定してファイルストリームを開く。

  2. XmlSerializer()コンストラクターでシリアライザーのインスタンスを作る。

  3. XmlSerializer.Deserialize()メソッドで逆シリアライズしてオブジェクトへ格納する。

書き出し

  1. ファイルストリームを開いて、ストリームライターのインスタンスを作る。

  2. XmlSerializerNamespacesクラスのインスタンスを作る。

  3. XmlSerializerNamespaces.Add()メソッドでXML名前空間の値を設定する。

  4. XmlSerializer()コンストラクターでシリアライザーのインスタンスを作る。

  5. XmlSerializer.Serialize()メソッドで、オブジェクトをXMLにする。

  6. ストリームライターでストリームをファイルに書き込む。

試してみた

文章で説明するよりコードを見た方が早いかもしれません。XMLファイルを読み込んで、逆シリアル化したデータをコンソールに表示し、そのデータをさらにシリアル化してファイルに保存する、コンソールアプリを作ってみます。

読み込むXMLファイル

例として、下記のXMLデータを読み込んでみることにします。ファイル名はtest.xmlにします。

<?xml version="1.0" encoding="utf-8"?>
<company>
  <person id="01">
    <name>まどか</name>
    <color>ピンク</color>
  </person>
  <person id="02">
    <name>ほむら</name>
    <color></color>
    <nickname>ほむほむ</nickname>
  </person>
  <person id="03">
    <name>さやか</name>
    <color></color>
  </person>
</company>

ニックネームの設定がある人が一人しかいないですね。

クラス

ルートノード(company)用のクラスを下記のようにします。

namespace xml_trial
{
    [System.Xml.Serialization.XmlRoot("company")]
    public class Company
    {
        // XMLファイル内にcompany要素直下のperson要素が複数あるので、プロパティをコレクションにする。
        [System.Xml.Serialization.XmlElement("person")]
        public System.Collections.Generic.List<xml_trial.Person> Person { get; set; }
    }
}

personノードが複数あるので、List型のコレクションにしました。

子ノード(person)用のクラスを下記のようにします。

namespace xml_trial
{
    public class Person
    {
        [System.Xml.Serialization.XmlAttribute("id")]
        public String ID { get; set; }

        [System.Xml.Serialization.XmlElement("name")]
        public String Name { get; set; }

        [System.Xml.Serialization.XmlElement("color")]
        public String Color { get; set; }

        [System.Xml.Serialization.XmlElement("nickname")]
        public String NickName { get; set; }

    }
}

属性はXmlAttribute、内容はXmlElementで取り出しですね。

処理

読み書き部分のコードは下記のようにしました。上述の流れに沿ってます。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Xml.Serialization;

namespace xml_trial
{
    class Program
    {
        static void Main(string[] args)
        {
            // 読み込み
            FileStream inputStream = new FileStream(@"test.xml", FileMode.Open); // ファイルストリームのインスタンスを作る。
            XmlSerializer serializer = new XmlSerializer(typeof(xml_trial.Company)); // シリアライザーのインスタンスを作る。
            xml_trial.Company model = (xml_trial.Company)serializer.Deserialize(inputStream); // 逆シリアライズしてオブジェクトに格納する。

            // 読み込んだデータの表示
            foreach (xml_trial.Person person in model.Person)
            {
                Console.WriteLine(String.Format("ID={0}, Name={1}, NickName={2}, Color={3}", person.ID, person.Name, person.NickName, person.Color));
            }

            // 書き出し
            FileStream outputStream = new FileStream("export.xml", FileMode.Create); // ファイルストリームのインスタンスを作る。
            StreamWriter writer = new StreamWriter(outputStream, Encoding.UTF8); // ストリームライターのインスタンスを作る。

            XmlSerializerNamespaces outputNameSpace = new XmlSerializerNamespaces();// XML名前空間のインスタンスを作る。
            outputNameSpace.Add(String.Empty, String.Empty); // XML名前空間の値を設定する。

            XmlSerializer outputSerializer = new XmlSerializer(typeof(xml_trial.Company)); // シリアライザーのインスタンスを作る。
            outputSerializer.Serialize(writer, model,outputNameSpace); // オブジェクトをシリアライズしてストリームへ。

            writer.Flush(); // ストリームをファイルに書き込む。
            writer.Close(); // ストリームを閉じる。
        }
    }
}

ファイルストリームを使うのでSystem.IOを、XMLシリアライザー用にSystem.Xml.Serializationをusingに追加しました。

実行してみた

プロジェクトをビルドして、実行してみました。

実行結果

要素にデータが無くても、エラーも出さずに読み込んでますね。XML出力結果は下記になりました。

<?xml version="1.0" encoding="utf-8"?>
<company>
  <person id="01">
    <name>まどか</name>
    <color>ピンク</color>
  </person>
  <person id="02">
    <name>ほむら</name>
    <color></color>
    <nickname>ほむほむ</nickname>
  </person>
  <person id="03">
    <name>さやか</name>
    <color></color>
  </person>
</company>

データの無い要素は出力されてませんね。希望通りの出力になりました。

公開日

広告