巷では、Windows 8 RTM, Visual Studio 2012 RTM で盛り上がっていますが、しばらくは平常運転で。
ちなみに 90日試用版は以下からダウンロードできます。
Download Windows 8 Enterprise Evaluation
http://msdn.microsoft.com/ja-jp/evalcenter/jj554510.aspx
# 英語のページだけど、きちんと日本語版がダウンロードできます。2.4GB 程度です。
# MSDN のほうも Japanese 版が用意されています。
さて、本題の XmlDom のほうはテストルーチンから作っていきます。
内部的には XML文字列 -> XDocument -> XmlDocument -> XmlNavigator の経由で渡しています。
ちまちま XML文字列をパースするコードを書いてもいいのですが、パース自体はあまりスピードを問わないので。
# 実は、System.Xml.Linq は Silverlight に含まれていない(今は含まれている?)ので避けていたのですが、
# Siverlight 自体が終了しそうな雰囲気なので、XDocument を使うことに決定
■テストコードを書く
以前に書いた XNode, XmlNode 構築のコードを XML文字列に直します。
Assert.AreEqual 部分はそのまま動くはず…というか、動かないと駄目です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | namespace TestXmlDom { [TestClass] public class TestXmlDocument { [TestMethod] public void TestParse1() { string xml = "<root><name>masuda tomoaki</name></root>" ; var doc = new XmlDocument(xml); var q = new XmlNavigator(doc) .Where(n => n.TagName == "name" ) .FirstOrDefault(); Assert.AreEqual( "masuda tomoaki" , q.Value); } [TestMethod] public void TestParse2() { string xml = @" <root> <name>masuda</name> <name>yamada</name> <name>yamasaki</name> </root>" ; var doc = new XmlDocument(xml); var q = new XmlNavigator(doc) .Where(n => n.TagName == "name" ) ; Assert.AreEqual(3, q.Count()); Assert.AreEqual( "masuda" , q.First().Value); } [TestMethod] public void TestParse3() { string xml = @" <root> <person id='1'> <name>masuda</name> <age>44</age> </person> <person id='2'> <name>yamada</name> <age>20</age> </person> <person id='3'> <name>tanaka</name> <age>10</age> </person> </root>" ; var doc = new XmlDocument(xml); var q = new XmlNavigator(doc) .Where(n => n.Attrs[ "id" ] == "2" ) .FirstOrDefault(); Assert.AreEqual( "person" , q.TagName); // ExDoc記述 Assert.AreEqual( "yamada" , q / "name" ); Assert.AreEqual( "20" , q / "age" ); } } } |
XNode じゃなくて、XmlNode を使う理由としては「q / “name”」という書き方ができるからです。
この部分はXElemnetを使って「q.Element(“name”).Value」と書いても同じです。
ただし、q 自体は XNode を返すので Element() を含んでいなくていまいち不便なんですよね。
■XDocument から XmlDoucmnet を構築する
インターフェースとして、XmlDocument を用意します。
単純に、XDocument の中身を XmlDocument に移し替えているだけです。
ざっとインターフェースを合わせていきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | namespace Moonmile.XmlDom { public class XmlDocument : XmlNode { public XmlNode documentElement { get { if ( this .Children.Count() > 0) { return Children[0]; } else { return XmlNode.Empty; } } } /// <summary> /// コンストラクタ /// </summary> public XmlDocument() { } /// <summary> /// コンストラクタ(XML文字列で初期化) /// </summary> /// <param name="xml"></param> public XmlDocument( string xml) { this .LoadXml(xml); } /// <summary> /// ファイルから構築する /// </summary> /// <param name="path"></param> /// <returns></returns> public XmlDocument Load( string path) { return this .Load(XDocument.Load(path)); } /// <summary> /// XML文字列から構築する /// </summary> /// <param name="xml"></param> /// <returns></returns> public XmlDocument LoadXml( string xml) { StringReader sr = new StringReader(xml); return this .Load(XDocument.Load(sr)); } /// <summary> /// XDocumentオブジェクトから構築する /// </summary> /// <param name="doc"></param> /// <returns></returns> public XmlDocument Load(XDocument doc) { var root = LoadXNode(doc.FirstNode); this .Children.Add(root); return this ; } protected XmlNode LoadXNode(XNode node) { var nn = new XmlNode(node.TagName(), node.Value()); if (node.NodeType == System.Xml.XmlNodeType.Element) { var el = node as XElement; foreach ( var at in el.Attributes()) { nn.Attrs.Add( new XmlAttr(at.Name.ToString(), at.Value)); } foreach ( var n in el.Nodes()) { nn.Children.Add(LoadXNode(n)); } } return nn; } } } |
という訳で、これで XML を自由に比較的自由に扱うことができました。
今度は HTML 文字列を扱えるように、HtmlNode, HtmlDocument へ移していきます。