前回のSAXと同じ仕事をする、XmlTextReaderを使ったコードをご紹介します。言語はC#、クラスの主要部分だけを抜き出しました。
class MyXmlReader
{
private List<Area> o_lstArea = new List<Area>();
public void XmlRead()
{
Area o_Area = null;
Area.Info_data o_Info = null;
Stack<String> elmNameStack = new Stack<String>();
int rangCnt = 0;
int periodCnt = 0;
using (XmlReader reader = XmlTextReader.Create("http://www.drk7.jp/weather/xml/12.xml";))
{
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
switch (reader.Name)
{
case "area":
o_Area = new Area();
o_Area.AreaName = reader.GetAttribute("id");
o_lstArea.Add(o_Area);
break;
case "info":
o_Info = o_Area.makeInfo();
o_Info.Dt = reader.GetAttribute("date");
break;
case "temperature":
rangCnt = 0;
break;
case "rainfallchance":
periodCnt = 0;
break;
}
elmNameStack.Push(reader.Name);
break;
case XmlNodeType.Text:
string elmName = elmNameStack.Pop();
elmNameStack.Push(elmName);
switch (elmName)
{
case "weather":
o_Info.Weather = reader.Value;
break;
case "weather_detail":
o_Info.Weather_detail = reader.Value;
break;
case "wave":
o_Info.Wave = reader.Value;
break;
case "range":
o_Info.Range[rangCnt++] = Convert.ToInt32(reader.Value);
break;
case "period":
o_Info.Rainfall[periodCnt++] = Convert.ToInt32(reader.Value);
break;
}
break;
case XmlNodeType.EndElement:
elmNameStack.Pop();
break;
}
}
}
}
public List<Area> getWeather()
{
return o_lstArea;
}
}
}
前回と同じAreaクラスを使っていますし、やることもSAXと同じようなことをしています。
しかし、このクラスは何かのクラスを「継承していない」で、
XmlReaderを使っているだけです。
またSAXとXmlReaderの動作には大きな違いがあります。
SAXはElement(タグ)に「入った」と「出た」に対してイベントが発生するのにに対して、XmlReaderは、「Elementに入った」とか、「Textに入った」とか(他に沢山フラグが用意されています)、入った内容を知らせてきます(Elementから出たというフラグもあります)。
そして、気を付けてなければならないことはXmlReaderが読み込んで、「あ、要素だった」とか「あ、要素の内容(Text)だったか」とか分かるのですが、内容だったとき「何(タグ)の」内容なのかわからないのです。
そのために、Stackを使いました。
要素Elementに入った時に、要素名=タグ名をスタックにプッシュし、Elementから出るときにポップしています。
要素の内容(Text)が見つかった時に、スタックの一番上のタグ名を取り出し、タグ名を確認し、またプッシュしておきます。
そのほかは、前回のSAXと同じです。
XmlReaderはXMLドキュメントの特定の要素を直接読みに行く機能があるようで、もっと様々な使い方ができるのでしょうが、今の関心事は、これでおしまいです。
少なくとも、SAXの訳の分からないcharactersメソッドがないだけ、XmlReaderの方が気分的にはいいです。