C# で Key、Value な コレクションを XML にしてみた
元ネタ:
GroovyのMarkupBuilderで再起的な構造のXMLを生成する - No Programming, No Life
GroovyでKey、ValueをXMLにクールに出力する-keyValueXml.groovy- - Togetter
Groovy では乗り遅れた/書けない ので C# の勉強も兼ねて書いてみた。
本体
using System.Collections.Generic; using System.Linq; using System.Xml.Linq; public class Class1 { public string ToXml(Dictionary<string, object> data) { var root = new XElement("langs", data.Select( e => new XElement(e.Key, e.Value.CreateValue()) )); return root.ToString(); } } internal static class Extensions { public static object CreateValue(this object source) { if (source is Dictionary<string, object>) { return ((Dictionary<string, object>)source).Select(e => new XElement(e.Key, e.Value.CreateValue())); } return source.ToString(); } }テスト
using System.Collections.Generic; using Microsoft.VisualStudio.TestTools.UnitTesting; [TestClass] public class UnitTest1 { [TestMethod] public void TestMethod1() { var data = new Dictionary<string, object>() { { "key1", "value1" }, { "key2", "value2" }, { "key3", new Dictionary<string, object>() { { "key3-1", "value3-1" }, { "key3-2", "value3-2" }, }}, }; var instance = new Class1(); string actual = instance.ToXml(data); string expected = @"<langs> <key1>value1</key1> <key2>value2</key2> <key3> <key3-1>value3-1</key3-1> <key3-2>value3-2</key3-2> </key3> </langs>"; Assert.AreEqual(expected, actual); } }
LINQ to XML ひゃっはー!
※ここをパクッた。方法 : LINQ to XML を使用してディクショナリを操作する
拡張メソッド CreateValue が少々ダサいけど。。ここまでは LINQ to XML があるので楽に書ける。
で togetter を読み進めると色んな Groovy コードが出てきた。
id:kiy0taka さん作 map2xml.groovy
Marshaller は as で型変換する際に上手い事やってくれる内容を定義してるのかな?
キャスト で良いなら C# でも「一応」書ける。(Groovy よりは不自然…)
本体 (拡張メソッド CreateValue は前回と一緒なので省略)
using System.Collections.Generic; using System.Linq; using System.Xml.Linq; public class XElementEx : XElement { public XElementEx(XName name, object content) : base(name, content) { } public static explicit operator XElementEx(Dictionary<string, object> target) { return new XElementEx("langs", target.Select( e => new XElement(e.Key, e.Value.CreateValue()) )); } }テスト
using System.Collections.Generic; using Microsoft.VisualStudio.TestTools.UnitTesting; [TestClass] public class UnitTest1 { [TestMethod] public void TestMethod2() { var data = new Dictionary<string, object>() { { "key1", "value1" }, { "key2", "value2" }, { "key3", new Dictionary<string, object>() { { "key3-1", "value3-1" }, { "key3-2", "value3-2" }, }}, }; XElementEx xml = (XElementEx)data; string actual = xml.ToString(); string expected = @"<langs> <key1>value1</key1> <key2>value2</key2> <key3> <key3-1>value3-1</key3-1> <key3-2>value3-2</key3-2> </key3> </langs>"; Assert.AreEqual(expected, actual); } }
explicit (C# リファレンス) 使って XElement を継承した型にキャスト出来るようにしてみた。implicit (C# リファレンス) にすると、明示的なキャストも不要(暗黙の型変換)になる。
ただ、変換演算子の使用 (C# プログラミング ガイド)(explicit や impicit) を使うケースは、上の様な時では無いので、仕事じゃ書かないな…。*1
次に id:uehaj さん作の convert map to xml
短くてシンプル、mkp.yield ってのが何か分からなかった。mkp ってのは、MarkupBuilder の中で使える特殊な物なのかな?
MarkupBuilder (Groovy 2.2.1)
MarkupBuilder が便利そうですねー。