2025/06/10

DXL Step-by-Step:#58)ノード操作 ⑪ - ノードの置き換え

ノード操作シリーズの最終回は、ノードの置き換え操作についてまとめます。


置き換え操作の必要性

例えば、リッチテキスト内のプレーンテキストに装飾をする場合を考えます。

それぞれを DXL で表現すると下図のようになるのですが、装飾を加えるためには、プレーンテキストを run や font ノードで装飾されたノードに置き換えることになります。


ReplaceChild メソッドの注意点

このような操作を行う際に利用するのが、ReplaceChild メソッドです。

ReplaceChild (NotesDOMNode - LotusScript®)

構文は以下の通りです。

Set notesDOMNode = notesDOMNode .ReplaceChild( newChild , oldChild )

引数には、置き換えるノードの新・旧を指定する仕様となっています。そのためか、メソッドをコールするノードは、RemoveChild メソッドと同じく、親のノードから実行する仕様になっています。NotesDOM??? クラスの設計者の親はよほど偉大な方なのかもしれませんね...

このヘルプを見ればわかるのですが、このメソッドには重大な注意点があります。それは戻り値が、置換されたノードであることです。


ReplaceChild メソッドの挙動

ヘルプを読んだだけではわかりにくいので、最初に記載したプレーンテキストを装飾する場合を例に、挙動を順に確認しましょう。

ReplaceChild 実行前はこのような状態となります。

紫色のノードが置換元のプレーンテキストのノードで、par ノードの配下に配置されています。置換先のノードは Create ??? Node メソッドを利用して新規で作成し準備します。これはノードの新規作成と同じ操作ですね。

この置換元と置換先のノードを引数に、親のノードである par ノードから ReplaceChild メソッドを実行することになります。実行後の状態は下図のような状態となります。

新規で作成したノードが par ノード配下に配置され、希望通りの結果になっています。問題は、はじき出されたノードです。このノードは、新規作成したてのノードと同じく、DXL ツリーには属さない宙に浮いた状態となっているのですが、このノードが ReplaceChild メソッドの戻り値となります。

DXL のコーディングをしていると、この挙動がとても煩わしく感じます。例えば、ノードを置き換えた後、後続の処理でそのノードを使いたくても、プログラム上は行方不明になってしまうからです。


ノードを置き換える関数

なぜこのようなインプリになっているか真意はわかりかねますが、この仕様では DXL を自由自在な操作に支障をきたします。そこで、次のような関数を作成して、標準メソッドの不便を解消しています。

Function xReplaceNode(vdnNew As NotesDOMNode, vdnOld As NotesDOMNode) As NotesDOMNode
   Dim dnParent As NotesDOMNode
   Dim dnNext As NotesDOMNode
   Dim dnPrev As NotesDOMNode

   ' 元の位置を保存
   Set dnNext = vdnOld.NextSibling           ’ 次のノード
   Set dnPrev = vdnOld.PreviousSibling  ' 手前のノード
   Set dnParent = vdnOld.ParentNode     ' 親のノード

   ' 置き換え
   Call dnParent.ReplaceChild(vdnNew, vdnOld)

   ' 行方不明の捜索
   If dnPrev.IsNull = False Then
      '手前のノードが存在したのでその次のノードが置換されたノード
      Set xReplaceNode = dnPrev.NextSibling
   ElseIf dnNext.IsNull = False Then
      '手前のノードがないので、次のノードの1つ前が置換されたノード
      Set xReplaceNode = dnNext.PreviousSibling
   Else
      '前後にノードがないので一人っ子、置換後も最初のノードが置換されたノード
      Set xReplaceNode = dnParent.FirstChild
   End If
End Function

関数内の処理のポイントは、置換前に前後と親ノードを取得しておく点です。これで、置換後、自分自身が行方不明になっても、前後関係や親から自分探しができるというわけです。


ノード操作まとめ

昨年の DominoHub 2024 のオンラインセッション『 ”DXL” でリッチテキスト縦横無尽』でご紹介した DXL ノード操作をまとめたこのシリーズですが、今回の ⑪ で終了です。ここで紹介したテクニックは、DXL を使ったプログラミングをする中で必要となった知識や関数たちで、実体験に即したものをまとめました。

これらテクニックを利用すれば、DXL を自由自裁、縦横無尽に操作できるようになります。

前回 DXL Step-by-Step


0 件のコメント:

コメントを投稿