きな粉もち.net

初級開発者の備忘録です。

log4net × xml 読み込み処理 × その他の種類まとめ

log4netの初期化処理も中盤に入ってきました。

log4netでは、log出力のconfigファイルの読み込みをXmlConfiguratorクラスの中で、XmlReaderと、XmlDocumentを利用して実装しています。

XmlReaderSettings settings = new XmlReaderSettings();

settings.DtdProcessing = DtdProcessing.Ignore;

XmlReader xmlReader = XmlReader.Create(configStream, settings);

// load the data into the document

doc.Load(xmlReader);

 

Xmlの読み込み・・・

これもよく忘れてしまい、そのたびに検索している気がしますw

いい機会なので、どんな実装方法があるか洗い出し、まとめておきたいと思います!

 

ざっとMSDNを見た感じ、今回の調査対象クラスは以下の通りです。

  1. XmlTextReader
  2. XmlReader
  3. XmlDocument
  4. XMLSerializer
  5. XmlValidatingReader
  6. Json.NET 

 

では、順番に見ていきます。

 

1.XmlTextReader

XmlTextReaderは、.NET Framework1.1以降で利用可能なクラスです。

XmlReader, IXmlLineInfo, IXmlNamespaceResolverを継承、実装しているクラスです。

stream,ファイルパス指定など、たくさんのインターフェースを公開しています。

詳しくはここhttps://msdn.microsoft.com/ja-jp/library/1af7xa52(v=vs.110).aspx

 

public static void Main() {

     XmlTextReader reader = null;

     try {

        // Load the reader with the data file and ignore all white space nodes.         
        reader = new XmlTextReader(filename);
        reader.WhitespaceHandling = WhitespaceHandling.None;

        // Parse the file and display each of the nodes.
        while (reader.Read()) {
           switch (reader.NodeType) {
             case XmlNodeType.Element:
               Console.Write("<{0}>", reader.Name);
               break;
             case XmlNodeType.Text:
               Console.Write(reader.Value);
               break;
             case XmlNodeType.CDATA:
               Console.Write("<![CDATA[{0}]]>", reader.Value);
               break;
             case XmlNodeType.ProcessingInstruction:
               Console.Write("<?{0} {1}?>", reader.Name, reader.Value);
               break;
             case XmlNodeType.Comment:
               Console.Write("<!--{0}-->", reader.Value);
               break;
             case XmlNodeType.XmlDeclaration:
               Console.Write("<?xml version='1.0'?>");
               break;
             case XmlNodeType.Document:
               break;
             case XmlNodeType.DocumentType:
               Console.Write("<!DOCTYPE {0} [{1}]", reader.Name, reader.Value);
               break;
             case XmlNodeType.EntityReference:
               Console.Write(reader.Name);
               break;
             case XmlNodeType.EndElement:
               Console.Write("</{0}>", reader.Name);
               break;
           }       
        }           
     }

     finally {
        if (reader!=null)
          reader.Close();
     }

 

Read()メソッドを利用して、Falseが返却されるまで読み込みを続けるとい流れの実装になります。

備考欄には、.NET Framework 2.0 以降では、XmlReaderクラスの利用を推奨と書かれています。
とはいえ、このクラス自体はXmlReaderクラスから派生ているクラスなのでなぜ推奨なのかが気になります。

公式ドキュメントに従い、XmlReaderを利用するのが良いですよね。

 

2.XmlReader

XmlTextReaderクラスの親クラスです。 
IDisposableを実装しています。

XmlTextReaderは、このクラスを継承しているのに、XmlReaderの利用が推奨されています。
メモ欄には、次のように記載されています。

.NET Framework 2.0 では、 XmlReader インスタンスを使用して、 XmlReader.Create の新しい機能を利用する方法です。

新しい機能があるのが理由みたいです。
中の実装を確認していないので想像ですが、XmlTextReaderでは、この機能をラップしているから使えない。そのため親クラスのXmlReaderを利用してくれ。ということなのでしょうか。。。

このクラスも前方方向の読み取りを行うように設計されているで、ループで回しながら必要なデータにアクセスする実装が必要となります。

各値にはプロパティを呼び出すことでアクセスできます。
サンプル実装は以下のようになります。

    XmlReaderSettings settings = new XmlReaderSettings();
    settings.Async = true;

    using (XmlReader reader = XmlReader.Create(stream, settings))
    {
        while (await reader.ReadAsync())
        {
            switch (reader.NodeType)
            {
                case XmlNodeType.Element:
                    Console.WriteLine("Start Element {0}", reader.Name);
                    break;
                case XmlNodeType.Text:
                    Console.WriteLine("Text Node: {0}",
                             await reader.GetValueAsync());
                    break;
                case XmlNodeType.EndElement:
                    Console.WriteLine("End Element {0}", reader.Name);
                    break;
                default:
                    Console.WriteLine("Other node {0} with value {1}",
                                    reader.NodeType, reader.Value);
                    break;
            }
        }
    }
 ||<

** 3.XmlDocument
Xmlの読み込み、編集、追加の操作を可能にするクラスです。
XmlNodeを継承しています。
1.2.と違い、読み込み以外の操作が単独のクラスで利用できるのがこのクラスの特徴です。

 また、検索する方向も、前方だけでなく、必要に応じて後方もサポートされています。

1.2.と比較してのデメリットとしては、検証で利用する XmlReaderSettingsが利用できないというところです。このため、検証を利用するためにはXmlReaderクラスを利用し、XmlReaderSettingsの設定を行い、XmlDocumentのLoadメソッドにそのインスタンスを渡す必要があります。

検証が必要な場面に出くわしていないので、これがどの程度のものなのかわかりませんが、XmlDocumentを利用する時には注意しておきたいです。 

いろいろ書きましたが、XmlDocumemtを使ったシンプルなシナリオは次の通りです。

>|cs|
XmlDocument doc = new XmlDocument();
    doc.LoadXml("<book ISBN='1-861001-57-5'>" +
                "<title>Pride And Prejudice</title>" +
                "<price>19.95</price>" +
                "</book>");

    XmlNode root = doc.FirstChild;

 

4.XmlSerializer

このクラスの説明は以下のようになっていました。

オブジェクトから XML ドキュメントへのシリアル化および XML ドキュメントからオブジェクトへの逆シリアル化を実行します。 XmlSerializer オブジェクトを XMLエンコードする方法を制御することができます。

XmlDocumentを使って、オブェクトに変換したりするときに利用できるクラスのようです。
使ったことが無かったですが、形式が決まったXmlの入出力をするときには、オブェクトに変換してしまってから操作した方が、可読性、保守性はあまり上がりそうですね。

機会があれば積極的に使ってみたいです!


5.XmlValidatingReader

 このクラスは、互換性のために残されているクラスです。

機能としては、XmlReaderSettingsと同じの様ですが、利用することがなさそうなので、無視します。

 

6.Json.NET

OSSJson.NETを利用してXmlを読み込む方法。

Converting between json and xml機能を利用して、xmljsonに変換。
変換後のjsonJson.NETを利用して読み込み。
xmlを変換する前に、結局XmlDocumentを利用する。
変換処理をOSSにたくすことができることがメリットだと思います。
とはいえ、.NETオブジェクトが欲しいだけなら、手数はXmlDocumentより多くなるのがデメリットですね。

 

 

まとめ

結果的に、XmlDocumentで読み取る。が第一選択肢でいいはず!
(使ったことないけど)検証がしたいならXmlRwaderクラスを利用することになるみたいです。
その他は。。。忘れて良いなかなぁ。。。



そして、後半やや雑になってしまったので、後で修正しよう。。。