巷では、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 部分はそのまま動くはず…というか、動かないと駄目です。
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 に移し替えているだけです。
ざっとインターフェースを合わせていきます。
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 へ移していきます。