XMLファイルをパースする (SAXパーサー XmlReaderを利用) - C#

SAXパーサーを用いてXMLファイルをパーシングします。
C#ではSAXパーサーでパーシングする場合はXmlReaderクラスを用います。

コード例

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.IO;

namespace XMLReaderDemo
{
  public partial class Form1 : Form
  {
    public Form1()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
        textBox1.Text = openFileDialog1.FileName;
      }
    }

    private void button2_Click(object sender, EventArgs e)
    {
      FileStream fs=null;
      XmlReader xmlReader=null;
      XmlReaderSettings settings =null;

      try {
        fs = new FileStream(textBox1.Text, FileMode.Open);

        settings = new XmlReaderSettings();
        settings.IgnoreComments = true;
        settings.IgnoreWhitespace = true;

        xmlReader = XmlReader.Create(fs, settings);
        while (xmlReader.Read() == true) {
          XmlNodeType nType = xmlReader.NodeType;
          textBox2.Text += "NodeType: " + nType.ToString() + "\r\n";

          textBox2.Text += "LocalName: " + xmlReader.LocalName + "\r\n";
          textBox2.Text += "Depth: " + Convert.ToString(xmlReader.Depth) + "\r\n";
          textBox2.Text += "Name: " + xmlReader.Name + "\r\n";
          if (xmlReader.HasValue == true) {
            Type valueType = xmlReader.ValueType;
            textBox2.Text += "ValueType: " + valueType.ToString() + "\r\n";
            textBox2.Text += "Value: " + xmlReader.Value + "\r\n";
          }
          
          //属性がある場合
          if (xmlReader.HasAttributes == true) {
            for (int i=0; i < xmlReader.AttributeCount; i++) {
              xmlReader.MoveToAttribute(i);
              textBox2.Text += "Attribute Name: " + xmlReader.Name + "\r\n";
              if (xmlReader.HasValue == true) {
                Type valueType = xmlReader.ValueType;
                textBox2.Text += "ValueType: " + valueType.ToString() + "\r\n";
                textBox2.Text += "Attribute Value: " + xmlReader.Value + "\r\n";
              }
            }
            xmlReader.MoveToElement();
          }

          textBox2.Text += "\r\n";
        }
      }
      catch (Exception exc) {
        textBox2.Text += "Error: " + exc.Message;
      }
      finally {
        if (fs != null) {
          fs.Close();
        }
        if (xmlReader != null) {
          xmlReader.Close();
        }
      }
    }
  }
}

解説

XMLファイルを読み込むストリーム(FileStream)を準備します。
  fs = new FileStream(textBox1.Text, FileMode.Open);

XmlReaderに渡すオプション(XmlReaderSettings)を作成します。
  settings = new XmlReaderSettings();

XmlReaderの設定(XmlReaderSettingsの設定)をします。今回の例ではXMLのコメントとホワイトスペースを無視する設定としました。
  settings.IgnoreComments = true;
  settings.IgnoreWhitespace = true;

XmlReaderを作成します。newではなくCreate()メソッドを利用します。第一引数にXMLの読み込みストリームを第二引数にXmlReaderSettingsを渡します。
  xmlReader = XmlReader.Create(fs, settings);

XmlReaderから読み込みます。Read()メソッドの戻り値がTrueである限り読み続けます。読み込みができなくなるまで(ストリームの末尾にたどり着くまで)読み込み続けます。
  while (xmlReader.Read() == true) {

while文の内部は、読み込んだノードの情報をtextBoxに表示するコードです。 次のコードでXMLタグの名称を取得できます。
  xmlReader.LocalName 

XMLのタグに挟まれた値については xmlReader.HasValue プロパティで値があるか判断し、xmlReader.Value プロパティで値を取得できます。
タグの属性については xmlReader.HasAttributes プロパティで属性のありなしを取得でき xmlReader.MoveToAttribute()メソッドでタグ内の属性にアクセスできます。

処理の終了後、finallyブロックでファイルストリームと、XmlReaderをクローズします。
  fs.Close();
  xmlReader.Close();

実行結果

入力データ (XMLファイル)
<?xml version="1.0" encoding="UTF-8"?>
<root>
  <node>
    <data type="text">データです</data>;
  </node>
</root>
結果
NodeType: XmlDeclaration
LocalName: xml
Depth: 0
Name: xml
ValueType: System.String
Value: version="1.0" encoding="UTF-8"
Attribute Name: version
ValueType: System.String
Attribute Value: 1.0
Attribute Name: encoding
ValueType: System.String
Attribute Value: UTF-8

NodeType: Element
LocalName: root
Depth: 0
Name: root

NodeType: Element
LocalName: node
Depth: 1
Name: node

NodeType: Element
LocalName: data
Depth: 2
Name: data
Attribute Name: type
ValueType: System.String
Attribute Value: text

NodeType: Text
LocalName: 
Depth: 3
Name: 
ValueType: System.String
Value: データです

NodeType: EndElement
LocalName: data
Depth: 2
Name: data

NodeType: EndElement
LocalName: node
Depth: 1
Name: node

NodeType: EndElement
LocalName: root
Depth: 0
Name: root
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
掲載日: 2011-01-07
iPentec all rights reserverd.