XmlDocument を XML 宣言付きの整形された String に変換する | Visual C# プログラミング

PROGRAM


XmlDocument を XML 宣言付きの整形された String に変換する

ASP.NET で XML のレスポンスとして出力する必要がありました。

単純に Response.Write を使ったり XmlWriter を使って、整形しながらタグをひとつひとつ描く方法もあるとは思ったのですが、少し複雑な XML になると DOM を使った方が楽なように思います。

そこで、今回は XmlDocument と XmlWriter を使って、読みやすく整形された XML テキストを作成してみることにします。このとき、XmlDocument の "WriteTo" や "Save" メソッドを使うことで XML 宣言も出力できるので、作成したテキストを Response.Output.WriteLine に渡すことで、そのまま HTTP のレスポンスとしても使えます。

MemoryStream を介して XML テキストを生成する

流れとしては、テキストを読み書きするのに使うストリームをメモリ上に用意して、そこへ XmlWriter を使って XML テキストを書き出し、それを StreamReader で読み込んで文字列型の変数に格納します。

このとき、XML 宣言に表示される文字コード (encoding) は、XmlWriterSettings を使って指定できるので、XmlDocument で扱っている文字コードと同じものを設定します。XML の場合は、通常は "System.Text.Encoding.UTF8" (UTF-8) にします。

// ここでは、XmlDocument にデータを揃えて返すメソッド ToXML があるものとして、それを使っています。

XmlDocument xml = this.ToXML();

 

// XML を整形するのに使う設定を XmlWriterSettings に用意します。

// Encoding は既定で UTF-8 になっているので、必要であれば設定します。インデントを有効化し、インデント文字を空白 4 つに設定しています。

var settings = new System.Xml.XmlWriterSettings()

{

Encoding = this.XmlEncoding,

Indent = true,

IndentChars = "    "

};

 

// メモリーストリーム (MemoryStream) と、それを読み書きするオブジェクト (XmlWriter, StreamReader) を準備します。

var stream = new System.IO.MemoryStream();

var writer = System.Xml.XmlWriter.Create(stream, settings);

var reader = new System.IO.StreamReader(stream);

 

// XmlDocument の内容を XmlWriter に書き出します。

xml.save(writer);

 

// ストリームの位置を先頭に戻し、文字列型の変数 result にストリームの内容を保存します。

stream.Position = 0;

 

String result = reader.ReadToEnd()

このようにすることで <?xml version=“1.0” encoding=“UTF-8”?> といった XML 宣言も含まれたテキストを XmlDocument から生成できます。

注意点としては、ストリームから読み込むときに、あらかじめ MemoryStream の "Position" プロパティに 0 を設定して、先頭から読み込めるようにする必要があります。その上で "ReadToEnd" メソッドを呼び出すことで、メモリーストリームの最初から最後までをテキストとして取得できます。

 

また、ここでは XmlDocument の "Save" メソッドを使って XmlWriter にテキスト出力していますが、ここで XmlNode から継承されている "WriteTo" メソッドを使うことでも出力できます。

このどちらを使うかで出力の内容そのものにどう違いが出るかは分からなかったのですが、この "WriteTo" メソッドで XmlWriter に書き出した場合は、そのあとに XmlWriter の "Flush" メソッドを呼び出す必要があるようです。これを忘れると、ストリームから読み込むときに、テキストを正しく取得できないことがあるようでした。

StringStream を介する場合は XML 宣言のエンコード表記に注意

上記のように MemoryStream と XmlStream を使う方法の他にも、StringWriter を使って XML テキストを生成する方法も一般に知られているようです。

StringWriter を使った方が MemoryStream と XmlStream を使うのに比べてストリーム自体の準備は簡単なのですけど、XmlDocument の "Save" メソッドと StringWriter との相性の都合で、XML 宣言に表記されるエンコードが "UTF-16" になってしまう問題があるようです。

この原因は StringWriter が扱うエンコードが "Unicode" で固定されていることが原因らしく、StringWriter クラスをオーバーライドして Encoding プロパティで "System.Text.Encoding.UTF8" を返すようにすることで回避できるらしいのですが、あまり自然な方法ではなさそうなので、前述の MemoryStream と XmlStream を使った方法で実装するのが良いでしょう。

XML 宣言や整形が不要な場合

XmlDocument の内容をテキストに変換するときに、XML 宣言や整形が不要な場合は、次のように "OuterXml" プロパティを使用するのが簡単です。

// ここでは、XmlDocument にデータを揃えて返すメソッド ToXML があるものとして、それを使っています。

XmlDocument xml = this.ToXML();

 

// XML 宣言やインデントが不要であれば、単純に OuterXml プロパティで、内容を文字列として取り出せます。

String result = xml.OuterXML;


[ もどる ]