高見知英のかいはつにっし(β)

高見知英のアプリケーション開発日誌 のほか、地域活動などの活動報告ブログ。

XmlTextWriterで概要を書いて、XmlDocumentで整形する

――というわけで、今日まで個人プロジェクトのXML保存処理を書いていました。以前はXmlSerializerでやろうと考えていたデータの保存処理ですが、今後のデータ構成などを考えて、結局一つ一つXmlTextWriterで書き込むことに。データの型変換などなかなか面倒くさいですが。やはりXmlSerializerを設定の保存以外の部分に使うのは難しいようです。

さて、以前に書いたように(二つ目のデータ参照)、今回保存したいのは、配列の中の各オブジェクトのデータ。
しかし、個々のオブジェクトを単独でXmlに保存したい場合もあるので、個々のオブジェクトにXMLを保存するメソッドを作ることにします。各オブジェクトのメソッドにXmlTextWriterを渡して書き込みたくないので、XmlNodeにして、ほかのXmlDocumentの一部に取り込むような形で実装したい。
ここで、XmlDocumentにいちいちCreateElementなどでノードを書き込むのは面倒なので方法を考えてみたところ、以下のようにXmlTextWriterを使って書き込むことが出来ることがわかりました。

    public void SaveToXML(XmlNode node)
    {
      using (StringWriter s = new StringWriter())
      {
        using (XmlTextWriter writer = new XmlTextWriter(s))
        {
          writer.WriteStartElement("rootNode");
          {
            /* ・・・XML書き込み処理・・・ */
          }
          writer.WriteEndElement();
        }
        node.InnerXml = s.ToString();
      }
    }

こうすると、XmlDocumentに単一のオブジェクトを保存したいときは、以下のように書けばいい。

      XmlDocument xml = new XmlDocument();
      oTargetObject.SaveToXML(xml);
      Clipboard.SetDataObject(xml.InnerXml);

そして、ほかのXmlDocumentの一部に取り込みたいときは、以下のように書くことが出来ます。

      XmlElement targetRoot = doc["objectlist"];
      XmlDocumentFragment docflag = doc.CreateDocumentFragment();
      oTargetObject.SaveToXML(docflag);
      targetRoot.AppendChild(doc.ImportNode(docflag, true));

XmlDocumentFragmentのおかげで結構楽にこういう処理が出来ます。
ちなみにXmlDocumentFlagment自体は何も値を持っていない(生成したばかりのXmlDocumentFragmentをImportNodeしても、何も表示されない)ようで、気軽にXMLノードを入れてインポートするためのノードのようです。こうやって子オブジェクトからノードを受け取って回るような処理を書くときには、結構便利かも。