C#.NET XmlTextReader

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

error: コピーできません !!