概要
C#でxmlデータをデシリアライズする際の、データクラスの構成や属性定義についてのサンプルをまとめました。
属性名について
本稿で登場する、xmlのデシリアライズを行う際に必要な属性についてまとめました。
XmlRoot
XMLのルート要素名を指定できます。
クラスに適用します。
XmlElement
プロパティやフィールドの名前をXML要素にマップできます。
XmlAttribute
プロパティやフィールドの値をXML属性としてマップできます。
XmlArray
配列やリストをXML配列としてマップする際に使用します。
XmlArrayItem
XML配列内の各アイテムを指定する際に使用します。
XmlArray属性と組み合わせて使用します。
XmlInclude
XmlSerializerが派生クラスを認識できるようにするために使用されます。
XmlText
XMLの要素内のコンテンツテキストを指定する際に使用します。
デシリアライズの例
パターン1
XMLデータの構成の説明
要素名 | 説明 |
---|---|
Sample | ルート要素 |
HogeInfos FugaInfos PiyoInfos |
要素数は必ず1つのみ |
ItemInfo | HogeInfos、FugaInfos、PiyoInfosの子要素 要素数は1つ以上 |
xmlデータ
<Sample>
<HogeInfos>
<ItemInfo Keyword="keyword1" Name="Name1" Value="Value1"/>
<ItemInfo Keyword="keyword2" Name="Name2" Value="Value2"/>
</HogeInfos>
<FugaInfos>
<ItemInfo Keyword="keyword3" Name="Name3" Value="Value3"/>
</FugaInfos>
<PiyoInfos>
<ItemInfo Keyword="keyword4" Name="Name4" Value="Value4"/>
<ItemInfo Keyword="keyword5" Name="Name5" Value="Value5"/>
<ItemInfo Keyword="keyword6" Name="Name6" Value="Value6"/>
</PiyoInfos>
</Sample>
データクラスの定義
定義例1
[XmlRoot("Sample")]
public class Sample
{
[XmlArray("HogeInfos")]
[XmlArrayItem("ItemInfo")]
public List<ItemInfo> HogeInfos { get; set; }
[XmlArray("FugaInfos")]
[XmlArrayItem("ItemInfo")]
public List<ItemInfo> FugaInfos { get; set; }
[XmlArray("PiyoInfos")]
[XmlArrayItem("ItemInfo")]
public List<ItemInfo> PiyoInfos { get; set; }
}
public class ItemInfo
{
[XmlAttribute("Keyword")]
public string Keyword { get; set; }
[XmlAttribute("Name")]
public string Name { get; set; }
[XmlAttribute("Value")]
public string Value { get; set; }
}
-
XmlRoot
属性に定義した名前はクラス名と同じなら、属性自体の記載を省けます。 -
XmlArray
属性はプロパティ名が、XmlArrayItem
は対応するクラス名が同じなら属性自体の記載を省けます。 -
XmlAttribute
属性は記載を省くとプロパティの値がnullになってしまうので、記載する必要があります。
定義例2
[XmlRoot("Sample")]
public class Sample
{
[XmlElement("HogeInfos")]
public HogeInfo HogeInfos { get; set; }
[XmlElement("FugaInfos")]
public FugaInfo FugaInfos { get; set; }
[XmlElement("PiyoInfos")]
public PiyoInfo PiyoInfos { get; set; }
}
public class HogeInfo
{
[XmlElement("ItemInfo")]
public List<ItemInfo> ItemInfos { get; set; }
}
public class FugaInfo
{
[XmlElement("ItemInfo")]
public List<ItemInfo> ItemInfos { get; set; }
}
public class PiyoInfo
{
[XmlElement("ItemInfo")]
public List<ItemInfo> ItemInfos { get; set; }
}
public class ItemInfo
{
[XmlAttribute("Keyword")]
public string Keyword { get; set; }
[XmlAttribute("Name")]
public string Name { get; set; }
[XmlAttribute("Value")]
public string Value { get; set; }
}
-
Sample
クラス内のXmlElement
属性は、定義した名前とプロパティ名が同じなら、属性自体の記載を省けます。 -
HogeInfo
、FugaInfo
、PiyoInfo
クラス内のXmlElement
属性は、定義した名前とリストとなるクラス名が同じなら省けます。
デシリアライズ方法
private Sample ReadXml(string path)
{
try
{
if (!File.Exists(path))
{
// エラー処理
}
var xml = XElement.Load(path);
string xmlText = xml.ToString();
var serializer = new XmlSerializer(typeof(Sample));
var deserializedData = (Sample)serializer.Deserialize(new StringReader(xmlText));
return deserializedData;
}
catch (Exception ex)
{
// エラー処理等
}
}
備考
データクラスの定義例1と2でデシリアライズ後のデータクラスの階層の構成は違いがありますが、どちらもデシリアライズできます。
パターン2
XMLデータの構成の説明
要素名 | 説明 |
---|---|
Sample | ルート要素 |
HogeData FugaData |
要素数は必ず1つのみ |
Targets | HogeData、FugaDataの子要素 要素数は1つ以上 |
Keyword | Targetsの子要素 要素数は1つ以上 |
xmlデータ
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Sample version="">
<HogeData>
<Targets Value="あたい">
<Keyword Text="もじ">AA</Keyword>
<Keyword Text="モジ">BB</Keyword>
</Targets>
<Targets Value="アタイ">
<Keyword Text="文字">CC</Keyword>
</Targets>
</HogeData>
<FugaData>
<Targets Value="値">
<Keyword Text="moji">DD</Keyword>
</Targets>
</FugaData>
</Sample>
データクラス
定義例1
[XmlRoot("Sample")]
public class Sample
{
[XmlElement("HogeData")]
public HogeData hogeData { get; set; }
[XmlElement("FugaData")]
public FugaData FugaData { get; set; }
}
public class DataTypeBase
{
[XmlElement("Targets")]
public List<Targets> Targets { get; set; }
}
public class HogeData : DataTypeBase
{
}
public class FugaData : DataTypeBase
{
}
public class Targets
{
[XmlAttribute("Value")]
public string Value { get; set; }
[XmlElement("Keyword")]
public List<Keyword> Keywords { get; set; }
}
public class Keyword
{
[XmlAttribute("Text")]
public string Text { get; set; }
[XmlText]
public string Value { get; set; }
}
定義例2
[XmlRoot("Sample")]
public class Sample
{
[XmlElement("HogeData")]
public HogeData hogeData { get; set; }
[XmlElement("FugaData")]
public FugaData FugaData { get; set; }
}
[XmlInclude(typeof(HogeData))]
[XmlInclude(typeof(FugaData))]
public abstract class DataTypeBase
{
[XmlElement("Targets")]
public List<Targets> Targets { get; set; }
}
public class HogeData : DataTypeBase
{
}
public class FugaData : DataTypeBase
{
}
[XmlInclude(typeof(Targets))]
public class Targets
{
[XmlAttribute("Value")]
public string Value { get; set; }
[XmlElement("Keyword")]
public List<Keyword> Keywords { get; set; }
}
public class Keyword
{
[XmlAttribute("Text")]
public string Text { get; set; }
[XmlText]
public string Value { get; set; }
}
デシリアライズ方法
こちらと同様。
補足
シリアライズについて
デシリアライズ後のクラスを使用して、以下のようにシリアライズもできます。
var xml = XElement.Load(path);
string xmlText = xml.ToString();
// デシリアライズ
var serializer = new XmlSerializer(typeof(Sample));
var deserializedData = (Sample)serializer.Deserialize(new StringReader(xmlText));
// シリアライズ
serializer = new XmlSerializer(typeof(Sample));
var writer = new StringWriter();
serializer.Serialize(writer, deserializedData);
xmlText = writer.ToString(); // xml形式の文字列が取得できる (デシリアライズ前と同様の文字列)
終わりに
それぞれの属性の細かな動きはまだ学習中ですが、単純なxmlのデシリアライズの際に役に立てればと思い記載しました。