XMLでリクエスト/レスポンスするAPIへアクセスする機会がありましたので、XmlSerializerの使い方を備忘録にしておきます。
XMLをシリアライズ/デシリアライズする
まずはC#オブジェクト(ここではBook)とXML形式の文字列でシリアライズ/デシリアライズさせる方法です。
Bookクラス用のXmlSerializer(System.Xml.Serialization名前空間)を定義して、Serializeメソッドでシリアライズできます。
- publicのフィールドまたはプロパティがXML要素になりますが、XmlRootAttribute、XmlElementAttributeで要素名を指定しています
- これらの属性が無い場合は、フィールド名・プロパティ名がそのまま要素名になります
- XMLの繰り返し構造を定義することもでき、その場合はXmlArrayAttributeで親要素名、XmlArrayItemAttributeで子要素名を指定できます
- クラスは入れ子構造にできます(Book内にList
を定義しています)
デシリアライズは、同様にBookクラス用のXmlSerializerを定義し、Deserializeメソッドでデシリアライズします。
using System; using System.Collections.Generic; using System.IO; using System.Xml.Serialization; namespace ConsoleApplication { [XmlRoot("book")] public class Book { [XmlElement("title")] public string Title { get; set; } [XmlElement("publised")] public DateTime Published { get; set; } [XmlArray("authors")] [XmlArrayItem("author")] public List<Author> Authors { get; set; } } public class Author { [XmlElement("authorName")] public string AuthorName { get; set; } } class Program { public static void Main(string[] args) { var book = new Book { Title = "The Art of Readable Code: Simple and Practical Techniques for Writing Better Code (Theory in Practice)", Published = new DateTime(2011, 11, 3), Authors = new List<Author> { new Author {AuthorName = "Dustin Boswell"}, new Author {AuthorName = "Trevor Foucher"} } }; // シリアライズ var writer = new StringWriter(); // 出力先のWriterを定義 var serializer = new XmlSerializer(typeof(Book)); // Bookクラスのシリアライザを定義 serializer.Serialize(writer, book); var xml = writer.ToString(); Console.WriteLine(xml); // デシリアライズ var deserializedBook = (Book)serializer.Deserialize(new StringReader(xml)); Console.WriteLine($"Title: {deserializedBook.Title}"); Console.WriteLine($"Published: {deserializedBook.Published}"); foreach (var author in deserializedBook.Authors) { Console.WriteLine($"AuthorName: {author.AuthorName}"); } } } }
実行すると、以下のように出力されます。
- ルート要素にデフォルトで名前空間(
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://ww w.w3.org/2001/XMLSchema"
)が設定されます
<?xml version="1.0" encoding="utf-16"?> <book xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://ww w.w3.org/2001/XMLSchema"> <title>The Art of Readable Code: Simple and Practical Techniques for Writing B etter Code (Theory in Practice)</title> <publised>2011-11-03T00:00:00</publised> <authors> <author> <authorName>Dustin Boswell</authorName> </author> <author> <authorName>Trevor Foucher</authorName> </author> </authors> </book> Title: The Art of Readable Code: Simple and Practical Techniques for Writing Bet ter Code (Theory in Practice) Published: 2011/11/03 0:00:00 AuthorName: Dustin Boswell AuthorName: Trevor Foucher
大まかな使い方は以上で、以下はtipsです。
デフォルトの名前空間を削除する
Serializeメソッドでは、XmlSerializerNamespacesオブジェクトを引数にとることができ、任意のXML名前空間を定義できます。 先程のデフォルトの名前空間が不要の場合、空のXmlSerializerNamespacesを渡すことで削除できます。
var namespaces = new XmlSerializerNamespaces(); namespaces.Add(string.Empty, string.Empty); serializer.Serialize(writer, book, namespaces);
book要素から名前空間が削除されていることが確認できます。
<?xml version="1.0" encoding="utf-16"?> <book> <title>The Art of Readable Code: Simple and Practical Techniques for Writing B etter Code (Theory in Practice)</title> ・・・
encoding="utf-8"にする
出力のXML宣言を見ますと、encoding="utf-16"
となっています。
StringWriterのEncodingプロパティの値がEncoding.UTF16になっているためですが、このプロパティはsetアクセサを持たないため、直接書き換えることができません。
そのため、StringWriterを継承したクラスを新たに作り、Encodingプロパティをオーバライドすることで、Encoding.UTF8に変えることができます。
private sealed class Utf8StringWriter : StringWriter { public override Encoding Encoding => Encoding.UTF8; } var writer = new Utf8StringWriter(); serializer.Serialize(writer, book, namespaces);
シリアライズされたXMLを見ると、encoding="utf-8"
と出力されることが確認できます。
<?xml version="1.0" encoding="utf-8"?> <book> <title>The Art of Readable Code: Simple and Practical Techniques for Writing B etter Code (Theory in Practice)</title> ・・・