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

DOMパーサーを用いてXMLファイルをパーシングします。
C#ではDOMパーサーでパーシングする場合はXmlDocumentクラスを用います。
ヒント
XPathを使うとよりシンプルにパーシング処理を記述できます。XPathを使ったXmlDocumentの操作方法はこちらの記事で紹介しています。

概要

DOMを用いてXMLファイルをパー寝具するにはXmlDocumentオブジェクトを作成し、Load()メソッドを用いてXMLファイルを読み込みます。パーシングされた結果の木構造がDocumentElementをルートノードとして格納されます。DocumentElementから子ノードをたどって各要素にアクセスします。

コード例

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;

namespace XMLDocumentDemo
{
  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)
    {
      XmlDocument xmlDocument = new XmlDocument();
      xmlDocument.Load(textBox1.Text);

      XmlElement elem = xmlDocument.DocumentElement;
      textBox2.Text += "NodeType; " + elem.NodeType.ToString() + "\r\n";
      textBox2.Text += "LocalName; " + elem.LocalName + "\r\n";
      textBox2.Text += "Name; " + elem.Name + "\r\n";
      textBox2.Text += "\r\n";

      if (elem.HasChildNodes == true) {
        XmlNode childNode = elem.FirstChild;

        while (childNode != null) {
          textBox2.Text += "NodeType; " + childNode.NodeType.ToString() + "\r\n";
          textBox2.Text += "LocalName; " + childNode.LocalName + "\r\n";
          textBox2.Text += "Name; " + childNode.Name + "\r\n";
          textBox2.Text += "\r\n";

          if (childNode.HasChildNodes == true) {
            for (int i=0; i < childNode.ChildNodes.Count; i++) {
              XmlNode dataNode= childNode.ChildNodes[i];

              textBox2.Text += "NodeType; " + dataNode.NodeType.ToString() + "\r\n";
              textBox2.Text += "LocalName; " + dataNode.LocalName + "\r\n";
              textBox2.Text += "Name; " + dataNode.Name + "\r\n";
              for (int j=0; j < dataNode.Attributes.Count; j++) {
                XmlAttribute xmlAttr = dataNode.Attributes[j];
                textBox2.Text += "LocalName; " + xmlAttr.LocalName + "\r\n";
                textBox2.Text += "Name; " + xmlAttr.Name + "\r\n";
                textBox2.Text += "Value; " + xmlAttr.Value + "\r\n";
              }
              textBox2.Text += "\r\n";
               
              if (dataNode.HasChildNodes == true) {
                XmlNode valueNode = dataNode.ChildNodes[0];
                textBox2.Text += "NodeType; " + valueNode.NodeType.ToString() + "\r\n";
                textBox2.Text += "LocalName; " + valueNode.LocalName + "\r\n";
                textBox2.Text += "Name; " + valueNode.LocalName + "\r\n";
                textBox2.Text += "Value; " + valueNode.Value + "\r\n";
                textBox2.Text += "\r\n";
              }

              textBox2.Text += "\r\n";
            }
          }
          childNode = childNode.NextSibling;
        }
      }
    }
  }
}

解説

XmlDocumentの宣言とインスタンスの作成をします。
  XmlDocument xmlDocument = new XmlDocument();

Load()メソッドでXMLファイルを読み込みます。
  xmlDocument.Load(textBox1.Text);

XmlDocumentのルートノードのにはxmlDocument.DocumentElementプロパティでアクセスできます。
  XmlElement elem = xmlDocument.DocumentElement;

ルートノードの内容をtextBox2に表示しします。今回はNodeType, LocalName, Nameの値をテキストボックスに表示します。
  textBox2.Text += "NodeType; " + elem.NodeType.ToString() + "\r\n";
  textBox2.Text += "LocalName; " + elem.LocalName + "\r\n";
  textBox2.Text += "Name; " + elem.Name + "\r\n";
  textBox2.Text += "\r\n";

ルートノードに子ノードがある場合は、子ノードを読み込みます。
  if (elem.HasChildNodes == true) {

FirstChildプロパティを用いることで最初の子ノードにアクセスできます。
  XmlNode childNode = elem.FirstChild;

子ノードのタグ名をtextBox2に表示します。
  textBox2.Text += "NodeType; " + childNode.NodeType.ToString() + "\r\n";
  textBox2.Text += "LocalName; " + childNode.LocalName + "\r\n";
  textBox2.Text += "Name; " + childNode.Name + "\r\n";
  textBox2.Text += "\r\n";

ノードがさらに子ノードを持っているか確認します。
  if (childNode.HasChildNodes == true) {

子ノードがあれば、子ノードの個数分だけループします。ループ内でi番目の子ノードを取得します。
  for (int i=0; i < childNode.ChildNodes.Count; i++) {
    XmlNode dataNode= childNode.ChildNodes[i];

取得したノードのタグ名をtextBox2に表示します。
  textBox2.Text += "NodeType; " + dataNode.NodeType.ToString() + "\r\n";
  textBox2.Text += "LocalName; " + dataNode.LocalName + "\r\n";
  textBox2.Text += "Name; " + dataNode.Name + "\r\n";

以下のコードでノードの属性を取得し属性の名前と値をtextBox2に表示します。
 for (int j=0; j < dataNode.Attributes.Count; j++) {
   XmlAttribute xmlAttr = dataNode.Attributes[j];
   textBox2.Text += "LocalName; " + xmlAttr.LocalName + "\r\n";
   textBox2.Text += "Name; " + xmlAttr.Name + "\r\n";
   textBox2.Text += "Value; " + xmlAttr.Value + "\r\n";
 }

さらに子ノードがあるか確認し、子ノードがあれば、そのタグ名と値をtextBox2に表示します。
  if (dataNode.HasChildNodes == true) {
    XmlNode valueNode = dataNode.ChildNodes[0];
    textBox2.Text += "NodeType; " + valueNode.NodeType.ToString() + "\r\n";
    textBox2.Text += "LocalName; " + valueNode.LocalName + "\r\n";
    textBox2.Text += "Name; " + valueNode.LocalName + "\r\n";
    textBox2.Text += "Value; " + valueNode.Value + "\r\n";
    textBox2.Text += "\r\n";
  }

次の兄弟ノードを選択します。この処理をすべての兄弟ノードについて繰り返しています。
  childNode = childNode.NextSibling;

実行結果

入力データ (XMLファイル)
<?xml version="1.0" encoding="UTF-8"?> 
<root> 
  <node>
    <data type="text">データ1です</data> 
  </node>
  <node> 
    <data type="text">データ2です</data> 
  </node>
  <node>
    <data type="text">データ3です</data> 
  </node>
</root>
結果
NodeType; Element
LocalName; root
Name; root

NodeType; Element
LocalName; node
Name; node

NodeType; Element
LocalName; data
Name; data
LocalName; type
Name; type
Value; text

NodeType; Text
LocalName; #text
Name; #text
Value; データ1です


NodeType; Element
LocalName; node
Name; node

NodeType; Element
LocalName; data
Name; data
LocalName; type
Name; type
Value; text

NodeType; Text
LocalName; #text
Name; #text
Value; データ2です


NodeType; Element
LocalName; node
Name; node

NodeType; Element
LocalName; data
Name; data
LocalName; type
Name; type
Value; text

NodeType; Text
LocalName; #text
Name; #text
Value; データ3です

著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2022-11-26
作成日: 2011-01-07
iPentec all rights reserverd.