2023/09/23

DXL Step-by-Step:#2)文書の新規作成 - DOM クラスの利用

前回 は、DXL を使って文書を新規作成する方法を紹介しました。ただ、DXL の作成は文字列を連結しただけの単純な方法でした。今回は、その DXL の作成を DXL 関連の Notes DOM クラスを使用して作成する方法を整理します。

プログラムの構造は 前回 と揃えています。よって、修正するのは、DXL の文字列を作成する関数 xGetDXL だけとなります。関数で作成する DXL は前回と同じ構造の次の通りとします。

<document form='DXL_SbS'>
   <item name='Title'>
      <text>
         #2 DOM クラスで DXL 文字列を作成
      </text>
   </item>
</document>


DOMクラスの利用準備

まず、DOM クラスを利用して DXL を操作するためには、NotesDOMParser クラスが必要でした。このクラスは、DXL を LotusScript で扱いやすくなるよう、構造(DOM 文書ツリー)をオブジェクトに変換する役割を担います。

NotesDOMParser オブジェクトの Document プロパティにより取得できる NotesDOMDocumentNode が XML 全体を表し、文書ツリーのルートとなります。

   Dim ns As New NotesSession
   Dim dprs As NotesDOMParser
   Dim ddn As NotesDOMDocumentNode
        ・・・
   Set dprs = ns.CreateDOMParser()
   Set ddn = dprs.Document

今回は新規文書の作成ですので、DXL をゼロから作成することになります。よって、上記のシンプルなコードで OK です。

ちなみに ddn の値をデバッガで確認すると次の通り、中身は空っぽとなっています。


ノードの作成

ルートの準備ができたので、DXL の中身を追加します。最初は、文書を表す <document> ノードです。

DXL でノードを追加する方法は少し特殊です。

まず、ノードを作成するメソッドは、ルートである NotesDOMDocumentNode オブジェクトにしか存在しません。複数ある Create?????Node というメソッドで、それぞれタイプの違うノードを作成します。

これらメソッドを使って必要なノードを作成して、各ノードオブジェクトの AppendChild メソッドでそのノード配下のノードとしてセットします。

   Dim denCur As NotesDOMElementNode
   Dim denNew As NotesDOMElementNode
        ・・・
   Set denNew = ddn.CreateElementNode("document")
   Call denNew.SetAttribute("form", "DXL_SbS")
   Set denCur = ddn.AppendChild(denNew)

あえて例えるなら、一旦文書を作成しておいて、あとから返答文書にセットするイメージでしょうか?ノーツ屋としてわからなくもないですが、ちょっと回りくどいですね...

なお、<document> ノードは、フォーム名を form 属性で指定します。SetAttribute メソッドを使用してセットしています。属性はオブジェクトに直接追加できるようですね...


ここまで実行すると、ルートオブジェクトの ddn の NumberOfChildNodes が 1 となりノードの追加が成功したことがわかります。また、DocumentElement や FirstChild などの子ノードにアクセスするためのプロパティにも値がセットされています。


フィールドの作成

文書を表す <document> ノードが作成できたので、次は、フィールドである <item> ノードを追加します。

ノードの追加なので、<document> ノードと同様の手順で作成します。注意すべきは、親となるノードが <document> となるだけです。

   Set denCur = ddn.AppendChild(denNew)

   Set denNew = ddn.CreateElementNode("item")
   Call denNew.SetAttribute("name", "Title")
   Set denCur = denCur.AppendChild(denNew)

AppendChild メソッドの戻り値は、追加したノード自身となります。追加した <document> ノードは denCur 変数で受けていますので、これにフィールドを追加することになります。

このように、DOM クラスでノードを追加するには、親となるノードと追加するノードの2つを操作することになります。変数名を工夫するなど、見やすくしておかないと、あとで見た時に理解に時間がかかりそうです。


フィールドの中身の作成

フィールドを表す DXL は、値の型を表す <text> ノードがあり、そのタグの間に値がべた書きされています。この値を表す部分は、DOM クラスでは、NotesDOMTextNode となります。

具体的には次のように <text> ノードを作成し、それに対して、テキストノードを追加します。テキストノードは NotesDOMTextNode オブジェクトとなるので、別の変数 dtnNew で受け取っています。

   Dim dtnNew As NotesDOMTextNode
        ・・・
   Set denCur = denCur.AppendChild(denNew)


   Set denNew = ddn.CreateElementNode("text")
   Set denCur = denCur.AppendChild(denNew)

   Set dtnNew = ddn.CreateTextNode("#2 DOM クラスで DXL 文字列を作成")
   Call denCur.AppendChild(dtnNew)


DXL を文字列で取得

DXL の構造(DOM 文書ツリー)は、NotesDOMParser が管理していました。ここから、完成した DXL をテキスト文字列で抽出する必要があります。

   Dim nst As NotesStream
        ・・・
   Set nst = ns.CreateStream()
   Call dprs.SetOutput(nst)
   Call dprs.Serialize()

   xGetDXL = nst.ReadText()

まず、SetOutput メソッドを使用して、NotesDOMParser クラスの出力先を指定します。今回は出力先に NotesStream クラスのオブジェクトを使用しました。

NotesStream クラスは、テキストデータやバイナリデータを効率よく扱うためのクラスです。今回は、NotesDOMParser の出力を NotesStream で受け取り、ReadText メソッドで DXL 全体を文字列として取得しています。

なお、NotesDOMParser クラスの Serialize メソッドは、DOM 文書ツリーを検索し XML を出力オブジェクトにストリーミングします。この命令を実行することにより、NotesStream クラスのオブジェクト nst に値がセットされます。


まとめ

xGetDXL 関数の全体を掲載します。

文書を作成して、フィールドを1つ作成するだけですが、なかなか長いコードとなります。NotesDocument クラスなど LotusScript 標準のクラスで実現できることは、わざわざDXL で実施する必要はなさそうですね...

Function xGetDXL() As String
   Dim ns As New NotesSession
   Dim dprs As NotesDOMParser
   Dim ddn As NotesDOMDocumentNode
   Dim denCur As NotesDOMElementNode
   Dim denNew As NotesDOMElementNode
   Dim dtnNew As NotesDOMTextNode

   ' DXL 作成準備
   Set dprs = ns.CreateDOMParser()
   Set ddn = dprs.Document
   
   '<document>ノード作成
   Set denNew = ddn.CreateElementNode("document")
   Call denNew.SetAttribute("form", "DXL_SbS")
   Set denCur = ddn.AppendChild(denNew)

   '<item>ノード作成
   Set denNew = ddn.CreateElementNode("item")
   Call denNew.SetAttribute("name", "Title")
   Set denCur = denCur.AppendChild(denNew)

   '<text>ノード作成
   Set denNew = ddn.CreateElementNode("text")
   Set denCur = denCur.AppendChild(denNew)

   '<text>ノードに値を作成
   Set dtnNew = ddn.CreateTextNode("#1 DXLをDOMクラスから作成")
   Call denCur.AppendChild(dtnNew)

   '作成した DXL をテキストで抽出
   Dim nst As NotesStream
   Set nst = ns.CreateStream()
   Call dprs.SetOutput(nst)
   Call dprs.Serialize()

   xGetDXL = nst.ReadText()
End Function


前回 DXL Step-by-Step 次回

0 件のコメント:

コメントを投稿