いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

XPathを用いてXMLデータを操作(XPathDocument, XPathNavigator)

前回、XmlReaderを用いてXMLデータの読み出しを書きましたが
実際にXMLを操作する場合、前回のように要素を上から順に見ていくのとは
別にXPath式を使ってデータを操作する方法があります。
XPathを利用するのは、例えるとデータベースに対してSQLを使ってデータを
取得するのに似ているかもしれません。条件を付加した上での特定データの
取得などが一発で行えたりします。


.NETでは、XPathがサポートされていますので、別途ライブラリをインストールする
必要はありません。


やり方ですが、以下のような手順になります。

  1. 元となるStream, File, XmlReaderなどからXPathDocumentオブジェクトを生成.
  2. 作成したXPathDocumentからXPathNavigatorを生成.
  3. XPathNavigator::Evaluateを使ってXPath式を評価.


以下、サンプルです。

// vim:set ts=4 sw=4 et ws is nowrap ft=cs:

using System;
using System.IO;
using System.Xml;
using System.Xml.XPath;

namespace Gsf.Samples.CSharp{

    class XPathSample{
        
        public void Execute(){
            using(Stream stream = GetSampleXmlAsStream()){
                using(XmlReader reader = XmlReader.Create(stream)){
                    //
                    // XmlReaderオブジェクトを用いて、XPathDocumentオブジェクトを作成。
                    // さらに、XPathDocumentオブジェクトからXPathNavigatorオブジェクトを作成.
                    //
                    // このXPathNavigatorがXPathを評価する処理を行います。
                    //
                    XPathNavigator navigator = new XPathDocument(reader).CreateNavigator();

                    //
                    // XPath式を評価.
                    // (今回のXPathではperson要素の子要素全てを取得する式となっています)
                    //
                    // XPathNavigator::Evaluateメソッドは、XPath式の評価の結果により、
                    // bool, double, string, XPathNodeIteratorを返します。
                    // 実際に利用する場合は、各々の型にキャストして利用します。
                    //
                    // XPathNodeIteratorはIEnumeableを実装しているのでforeach可能。
                    //
                    foreach(XPathNavigator nav in (XPathNodeIterator) navigator.Evaluate("//person/*")){
                        Console.WriteLine("{0}={1}", nav.Name, nav.Value);
                    }
                }
            }
        }

        Stream GetSampleXmlAsStream(){
            Stream stream = new MemoryStream();

            using(XmlWriter writer = XmlWriter.Create(stream)){
                writer.WriteStartElement("persons");

                for(int i = 0; i < 10; i++){
                    writer.WriteStartElement("person");
                        writer.WriteStartElement("name");
                            writer.WriteStartAttribute("nickname");
                                writer.WriteString("my_nick_name" + (i + 1));
                            writer.WriteEndAttribute();
                            writer.WriteString("gsf_zero" + (i + 1));
                        writer.WriteEndElement();
                        writer.WriteStartElement("address");
                            writer.WriteString("xxxxxxxxxxxxxxxxxxx-" + (i + 1));
                        writer.WriteEndElement();
                    writer.WriteEndElement();
                }

                writer.WriteEndElement();

                writer.Flush();
            }

            stream.Position = 0;
            Console.WriteLine(new StreamReader(stream).ReadToEnd()); // 出力XML確認.
            stream.Position = 0;

            return stream;
        }

        static void Main(){
            new XPathSample().Execute();
        }
    }
}


================================
過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。