前回の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の方が気分的にはいいです。