XPathを使ってXMLファイルをパースする (XmlDocumentを利用)

XPathを使うとXmlDocumentでのXMLパーシングがよりシンプルになります。
XPathを使ったXmlDocumentの操作方法を紹介します。

XPathを利用すると何が便利なのか

従来のXMLをDOMでパージングする場合、ノードを一つづつたどる必要があります。

<root> 
  <node>
    <sub-node>
      <data type="text">データ</data> 
    <sub-node>
  </node>
</root> 

上記のXMLをパージングする場合、以下のコードになります。
ノードの階層をたどって取得したいノードにアクセスする必要があります。ノードの階層が多い場合、コードは量は多くなり、可読性も落ちます。
取得したいノードを直接、"/root/node/sub-node/data" のようにパスで指定できれば、非常にシンプルにノードにアクセスできます。XPathを利用すると、ノードへのアクセスがパス形式でシンプルに実装できます。

  XmlDocument xmlDocument = new XmlDocument();
  
  //XML読み込み
  /*(何らかのXML読み込み処理)*/

  //rootノードの取得
 XmlElement elem = xmlDocument.DocumentElement;
  
  //子ノードの確認
 if (elem.HasChildNodes == true){
    //子ノードの取得
    XmlNode childNode = elem.FirstChild;

    //孫ノードの確認
    if (childNode.HasChildNodes ==  true){
      //孫ノードの取得
      XmlNode childNode2 = childNode.FirstChild;

      //データノードの確認
      if (childNode2.HasChildNodes == true) {
        XmlNode dataNode = childNode2.ChildNodes[i];
        //データの取得
        string value = dataNode.Name;
      }
    }
  }

概要

XPathを用いる場合は、XmlDocumentクラスのSelectNodesメソッドを用います。SelectNodesメソッドの引数にXPath式を与えることでXPath式に一致するノードをまとめて選択できます。

コード例

private void button3_Click(object sender, EventArgs e)
{
  XmlDocument xmlDocument = new XmlDocument();
  xmlDocument.Load(textBox1.Text);

  XmlNodeList nodeList = xmlDocument.SelectNodes("/root/node/data");
      
  for (int i=0; i < nodeList.Count; i++){
    textBox2.Text += "NodeType: " + nodeList[i].NodeType + "\r\n";
    textBox2.Text += "Name: " + nodeList[i].Name + "\r\n";
    textBox2.Text += "LocalName: " + nodeList[i].LocalName + "\r\n";
    textBox2.Text += "Value: " + nodeList[i].Value + "\r\n";
    textBox2.Text += "InnerText: " + nodeList[i].InnerText + "\r\n";
    textBox2.Text += "\r\n";
    if (nodeList[i].HasChildNodes == true){
      for (int j=0; j < nodeList[i].ChildNodes.Count; j++) {
        textBox2.Text += "NodeType: " + nodeList[i].ChildNodes[j].NodeType + "\r\n";
        textBox2.Text += "Name: " + nodeList[i].ChildNodes[j].Name + "\r\n";
        textBox2.Text += "LocalName: " + nodeList[i].ChildNodes[j].LocalName + "\r\n";
        textBox2.Text += "Value: " + nodeList[i].ChildNodes[j].Value + "\r\n";
        textBox2.Text += "InnerText: " + nodeList[i].ChildNodes[j].InnerText + "\r\n";
      }
    }
    textBox2.Text += "\r\n";
  }
}

解説

XmlDocumentの宣言とインスタンスの作成をします。

  XmlDocument xmlDocument = new XmlDocument();

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

  xmlDocument.Load(textBox1.Text);

XPath書式を用いて複数ノードを選択します。

  XmlNodeList nodeList = xmlDocument.SelectNodes("/root/node/data");

ループで選択されたノードの数だけループします。

  for (int i=0; i<nodeList.Count; i++){

ノードの情報をtextBox2に出力します。

  textBox2.Text += "NodeType: " + nodeList[i].NodeType + "\r\n";
  textBox2.Text += "Name: " + nodeList[i].Name + "\r\n";
  textBox2.Text += "LocalName: " + nodeList[i].LocalName + "\r\n";
  textBox2.Text += "Value: " + nodeList[i].Value + "\r\n";
  textBox2.Text += "InnerText: " + nodeList[i].InnerText + "\r\n";
  textBox2.Text += "\r\n";


ノードに子ノードがあるか確認します。

  if (nodeList[i].HasChildNodes == true){

子ノードがある場合は、子ノードの内容をtextBox2に表示します。

  for (int j=0; j<nodeList[i].ChildNodes.Count; j++) {
    textBox2.Text += "NodeType: " + nodeList[i].ChildNodes[j].NodeType + "\r\n";
    textBox2.Text += "Name: " + nodeList[i].ChildNodes[j].Name + "\r\n";
    textBox2.Text += "LocalName: " + nodeList[i].ChildNodes[j].LocalName + "\r\n";
    textBox2.Text += "Value: " + nodeList[i].ChildNodes[j].Value + "\r\n";
    textBox2.Text += "InnerText: " + nodeList[i].ChildNodes[j].InnerText + "\r\n";
  }

実行結果

入力データ (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
Name: data
LocalName: data
Value: 
InnerText: データ1です

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

NodeType: Element
Name: data
LocalName: data
Value: 
InnerText: データ2です

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

NodeType: Element
Name: data
LocalName: data
Value: 
InnerText: データ3です

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

補足:うまく動作しない時

実行時にXPathのノードが取得できない場合があります。XMLでネームスペースが指定されている場合に動作しない現象が発生します。ネームスペースが指定されているXMLでXPathを利用してノードを取得するコードに関してはこちらの記事を参照してください。

AuthorPortraitAlt
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
作成日: 2011-01-07
Copyright © 1995–2025 iPentec all rights reserverd.