巷では、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 へ移していきます。

