XmlDocumentからXML宣言付きの整形済みXMLをstringで取得する
今回は、XmlDocumentからXML宣言(<?xml ~ ?>)付き、かつインデント入りで整形されたXML形式の文字列を取り出す方法を考えてみます。
C#でXMLドキュメントを扱うときはXmlDocumentクラスを使います。また作成したXMLを文字列として取得したい場合は、下記のようにOuterXmlプロパティなどを用いれば取得できます。
1 2 3 4 5 |
XmlDocument doc = new XmlDocument(); doc.CreateXmlDeclaration("1.0", null, null); // ~XML 要素の追加~ // XML 文字列を取得 string xml = doc.OuterXml; |
でも、このOuterXmlで取得できる文字列はXML宣言や改行、インデントなどが含まれていません。つまり、人間が見たり、XML文書としての体裁が必要なサービスに送信したりするには非常に不便なのです。
このため、XMLファイルに保存したような文字列を取得したい場合は、工夫しなければなりません。
まず、Save()メソッドで整形済み文字列としてファイルに保存できます。のSave()メソッドはファイル名だけでなく、Streamもパラメータとして受け取ることができるので、ここにStringWriterを渡せば文字列に変換できます。
1 2 3 4 5 6 7 8 |
// StringWriterをつくる System.IO.StringWriter writer = new System.IO.StringWriter(); // StringWriterに整形済みXMLを書き出し doc.Save(writer); // 文字列として書き出し string r = writer.ToString(); // StringWriterを閉じる writer.Close(); |
ただし、StringWriterはなぜかUTF-16しか扱えないので、XmlDocumentをUTF-8で作ってもShift-JISで作っても強制的にXML宣言がUTF-16になってしまいます。
これを他のエンコードに変えたい場合は、専用のStringWriterを作る必要があります。下記のようにStringWriterを継承して、Encodingプロパティをオーバーライドしてしましょう。
1 2 3 4 5 6 7 |
class StringWriterUTF8 : System.IO.StringWriter { public override Encoding Encoding { get { return Encoding.UTF8; } } } |
あとはこれを使って、Saveしてあげましょう。最後にこれをいちいち書くのも面倒なので拡張メソッドとして定義しておきます(拡張メソッドはC# 3.0以降のみ使えます)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
public static class XmlEx { /// <summary> /// XML ドキュメントを UTF-8 形式の文字列に変換します。 /// </summary> /// <param name="doc"></param> /// <returns></returns> public static string ToStringXml(this XmlDocument doc) { StringWriterUTF8 writer = new StringWriterUTF8(); doc.Save(writer); string r = writer.ToString(); writer.Close(); return r; } /// <summary> /// UTF-8 用 StringWriter です。 /// </summary> class StringWriterUTF8 : System.IO.StringWriter { public override Encoding Encoding { get { return Encoding.UTF8; } } } } |
こうしておけばdocのメソッドとして呼び出せてべんりです。
1 2 3 4 5 |
XmlDocument doc = new XmlDocument(); doc.CreateXmlDeclaration("1.0", null, null); // ~要素を追加~ // 文字列でXMLを取得! string xml = doc.ToStringXml(); |
That’s it!