連載

.NETで簡単XML

第11回 オブジェクトをXMLでシリアライズ(3)

株式会社ピーデー 川俣 晶
2003/11/22

要素のシーケンスとしての配列のシリアライズ

 前回の最後に、以下のように書いた。

実際に実行した例を見ると、配列の中に入っているクラスもシリアライズされ、Personクラスの配列は、単純なPerson要素の繰り返しに置き換えられていることが分かるだろう。しかし、これだけでは、思い通りのXML文書を出力するには不十分である。例えば、この例では、Persons要素の子要素にpersons要素があり、その子要素にPerson要素があるため、少し不必要に要素の階層が深すぎる印象も受ける。

 これらの問題に対処する方法は、次回に続くとしたが、それをここで解説する。つまり、Persons要素の子要素にpersons要素があり、その子要素にPerson要素があるため、少し不必要に要素の階層が深すぎるという問題に対処するために、階層を浅くする方法を解説してみよう、という意味である。

 まず、シリアライズされるクラスを見てみよう。前回の「配列のシリアル化」のサンプル・プログラムとほとんど同じだが、ほぼ全体をもう一度掲載する。

Public Class Person
  Private m_name As String = "未設定"
  Private m_age As Integer = 0
  Public Property Name() As String
    Get
      Return m_name
    End Get
    Set(ByVal Value As String)
      m_name = Value
    End Set
  End Property

  Public Property Age() As Integer
    Get
      Return m_age
    End Get
    Set(ByVal Value As Integer)
      m_age = Value
    End Set
  End Property
End Class

Public Class Persons
  <XmlElement()> Public persons(2) As Person

  Public Sub SetPersons(ByVal person1 As Person, ByVal person2 As Person, ByVal person3 As Person)
    persons(0) = person1
    persons(1) = person2
    persons(2) = person3
  End Sub

  Public Sub Dump()
    For Each person As Person In persons
      Trace.WriteLine(person.Name)
      Trace.WriteLine(person.Age)
    Next
  End Sub
End Class
サンプル・プログラム2-1:シリアライズされるクラス(VB.NET版C#版

 これを呼び出す側を記述してみよう。ただし、Form1_Loadメソッドと、deserializeSampleメソッドは今回最初の「派生クラスを含む配列のシリアライズ」のサンプル・プログラムと同じ内容になるので、省略している。

Private Sub serializeSample()
  Dim person1 As New Person
  person1.Name = "山田太郎"
  person1.Age = 17

  Dim person2 As New Person
  person2.Name = "山田二郎"
  person2.Age = 16

  Dim person3 As New Person
  person3.Name = "山田三郎"
  person3.Age = 15

  Dim persons As New Persons
  persons.SetPersons(person1, person2, person3)

  Dim serializer As XmlSerializer = New XmlSerializer(GetType(Persons))
  Dim stream As FileStream = New FileStream("c:\sample.xml", FileMode.Create)
  Try
    serializer.Serialize(stream, persons)
  Finally
    stream.Close()
  End Try
End Sub
サンプル・プログラム2-2:シリアライズを行うメソッド(VB.NET版C#版

 これを実行すると以下のような結果が得られる。

山田太郎
17
山田二郎
16
山田三郎
15

 また、生成されるXML文書は以下のようになる。

<?xml version="1.0"?>
<Persons xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <persons>
    <Name>山田太郎</Name>
    <Age>17</Age>
  </persons>
  <persons>
    <Name>山田二郎</Name>
    <Age>16</Age>
  </persons>
  <persons>
    <Name>山田三郎</Name>
    <Age>15</Age>
  </persons>
</Persons>
生成されるXML文書

 さて、階層がどうなっているか、結果を調べてみよう。この結果を見ると、Persons要素の子要素にpersons要素があるが、その下に直接Name要素やAge要素があり、前回の例にはあったPerson要素は見あたらない。つまり、階層が1つ減って、すっきりしている。しかし、XML文書として不自然になったり、データの解釈があいまいな状態に陥ったりしているわけでもない。もともとXMLでは、同じ要素の繰り返しはよくあるデータ構造として用いられる。配列に相当する情報をXML文書に記録する場合、配列の中身のデータを繰り返し書き込むだけでもよく、配列であることを示す要素を強いて付けなくても済む場合が多い。

 では、何が階層を浅くしてくれたのだろうか。それは、サンプル・プログラムに追加されたたった1つの属性である。配列の宣言に付いているXmlElement属性(System.Xml.Serialization.XmlElementAttributeクラス)がそれである。XmlElement属性といえば、前々回、前回にも要素の名前を指定する属性として登場しているが、ここではそれらとは違った機能を発揮していることになる。要素の名前を指定する場合は、XmlElement属性の引数に名前を指定したが、ここでは名前を指定してはいない。それどころか引数は1つもない。それにより、XmlElement属性が持つ本来の主要な機能、指定された対象を要素で表現するという機能だけでなく、XmlElement属性の「配列を返すフィールドまたはプロパティにXmlElementAttributeを適用すると、その配列内の項目はXML要素のシーケンスとしてエンコードされる」という機能も発揮されているわけである。XML要素のシーケンスとは、同じ種類の要素が繰り返し出現していることを意味する。


 INDEX
  .NETで簡単XML
  第11回 オブジェクトをXMLでシリアライズ(3)
    1.派生クラスを含む配列のシリアライズ
    2.派生クラスを含む配列をシリアライズするプログラムの内容
  3.要素のシーケンスとしての配列のシリアライズ
    4.ArrayListオブジェクトのシリアライズ
    5.自作コレクションのシリアライズ
 
インデックス・ページヘ  「連載 :.NETで簡単XML」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間