前回はインラインイメージ(リッチテキストに直接貼り付ける画像)を貼り付ける方法を紹介しました。今回はインラインイメージを取得する方法についてまとめます。
DXL の構造
まずはインラインイメージの DXL の確認です。
前回説明したように picture ノードがリッチテキストに貼り付けられた画像を表します。その配下に gif ノードなど画像データが直接存在すればインラインイメージです(画像がイメージリソースを参照している場合は imageref ノード)。
DXL の読み込みにおいては、注意点があります。
上記 DXL で picture ノードの最初の子ノードは border となっています。これは、イメージリソースに設定された枠の情報です。
border ノードは画像データより前に配置され、標準の設定(枠なし)の場合は出力されません。画像データを取得するには ”最初の子ノード” ではなく、子ノードの中から画像データを探す必要があるということになります。
エージェントの作成
#14 以降、文書の DXL について解説してきました。ただ、これまでずっと文書やリッチテキスト内のオブジェクトを新規作成する方法が中心でした。今回は既存文書を DXL でアクセスする方法となります。
そこで、今回はプログラム全体を確認しながら進めます。まずは、選択した文書に対して実行するエージェントを作成します。エージェントのメインプログラムは次の通りです。
Option Declare Private xns As NotesSession Sub Initialize Dim ndb As NotesDatabase Dim ndc As NotesDocumentCollection Dim nd As NotesDocument '処理対象の文書を取得 Set xns = New NotesSession Set ndb = xns.CurrentDatabase Set ndc = ndb.UnprocessedDocuments Set nd = ndc.GetFirstDocument() '画像データの取得 Dim nst As NotesStream '画像データ Dim sTag As String '画像の拡張子 If Not(nd Is Nothing) Then sTag = xGetDXL_FirstInlineImage(nd, "Body", nst) If sTag <> "" Then '取得できたらファイルとして保存 Call StreamToImageFile(nst, "c:\tmp\test." & sTag) End If End If End Sub |
StreamToImageFile 関数は #9 でイメージリソースから画像をダウンロードした際に作成した関数をそのまま再利用しています。
xGetDXL_FirstInlineImage が画像データを取得する関数で、今回の主題のプログラムとなります。
画像データの取得
関数の全体は次の通りです。
引数は、画像が含まれる文書 vnd、インラインイメージが存在するフィールド名 vsFld、取得した画像を NotesStream オブジェクトで返す rnst です。戻り値は画像データがあったノード名で、png / gif / jpeg となり、メインプログラムでは保存するファイルの拡張子として使用しています。もし、インラインイメージが見つからない場合には null を返します。
Function xGetDXL_FirstInlineImage(vnd As NotesDocument, ByVal vsFld As String, rnst As NotesStream) As String 'DXL の準備 Dim dprs As NotesDOMParser Set dprs = xGetDOMParser(vnd) 'DOM ツリーのルートを取得 Dim ddn As NotesDOMDocumentNode Set ddn = dprs.Document 'リッチテキストの取得 Dim denRT As NotesDOMElementNode Set denRT = xGetDXL_item(ddn, vsFld) '画像の取得 Dim denPct As NotesDOMElementNode Set denPct = xGetDXL_FirstNodeByName(denRT, "picture") '画像ファイル取得 Dim denImg As NotesDOMElementNode Dim dnl As NotesDOMNodeList Dim dtn As NotesDOMTextNode Dim nst As NotesStream Dim sB64 As String '調査対象ノード Dim asTag(2) As String asTag(0) = "png" asTag(1) = "gif" asTag(2) = "jpeg" '画像データの捜索 If Not(denPct Is Nothing) Then ForAll sTag In asTag Set denImg = xGetDXL_FirstNodeByName(denPct, sTag) If Not(denImg Is Nothing) Then 'エンコードされた画像データ取得 Set dtn = denImg.FirstChild sB64 = dtn.NodeValue 'デコードしてストリームとして取得 Set nst = xns.CreateStream() Call Base64ToBinary(sB64, nst) '戻り値セット Set rnst = nst xGetDXL_FirstInlineImage = sTag Exit ForAll End If End ForAll End If End Function |
DXL の準備では文書を DXL に変換しています。コールしている xGetDOMParser 関数は #3 で紹介したものをそのまま流用しています。
xGetDXL_item 関数でフィールドを表す item ノードを取得、xGetDXL_FirstNodeByName 関数で、item ノードの中から最初に出現する画像のノード picture を取得しています。それぞれの関数は後述します。
picture ノード配下から画像データ(png / gif / jpeg のどれか)を捜索します。見つかったら、画像データであるテキストノードを取得、Base64 でエンコードされているので、デコードして NotesStream オブジェクトに変換します。デコードには #9 で紹介した Base64ToBinary 関数を利用しています。
画像が取得できたら戻り値にセットして、関数を終了しています。
フィールドを取得する関数
引数で指定したフィールドを取得する関数 xGetDXL_item は次の通りです。すべての item ノードを取得して、name 属性の値で判定しています。
Option Declare Private xns As NotesSession Function xGetDXL_item(vddn As NotesDOMDocumentNode, ByVal vsFld As String) As NotesDOMElementNode '文書のノードの取得 Dim denDoc As NotesDOMElementNode Set denDoc = vddn.DocumentElement 'itemノードをチェック Dim den As NotesDOMElementNode Dim dnl As NotesDOMNodeList Dim i As Integer Dim sFld As String Set dnl = denDoc.GetElementsByTagName("item") For i = 1 To dnl.NumberOfEntries Set den = dnl.GetItem(i) 'フィールド名をチェック sFld = den.GetAttribute("name") If LCase(sFld) = LCase(vsFld) Then '戻り値セットしてループ脱出 Set xGetDXL_item = den Exit For End If Next End Function |
配下のノードを取得
最初に紹介した picture ノード配下の画像データを取得しているのが xGetDXL_FirstNodeByName 関数です。この関数は GetElementsByTagName で配下のノードを検索し、最初のノードを取得しています。
フィールドの取得とほぼ同じ構造ですが、name 属性の判定がない分シンプルです。
Function xGetDXL_FirstNodeByName(vdenParent As NotesDOMElementNode, ByVal vsName As String) As NotesDOMElementNode Dim dnl As NotesDOMNodeList On Error Resume Next '配下のノードを検索 Set dnl = vdenParent.GetElementsByTagName(vsName) If dnl.NumberOfEntries > 0 Then '最初のノードを戻り値にセット Set xGetDXL_FirstNodeByName = dnl.GetItem(1) End If End Function |
まとめ
今回は、既存文書内に貼り付けられたインラインイメージを画像ファイルとして取得する方法についてまとめました。処理を簡素化するため、リッチテキスト内の最初の picture ノードがインラインイメージであることを前提としています。
リッチテキストにおいて、picture ノードはイメージリソースを貼り付けた時、添付ファイルのアイコン画像などさまざまな用途で出現します。GetElementsByTagName メソッドで単純に配下すべてを検索すると、想定外の picture ノードを取得することがあります。実際のリッチテキストを処理する場合には、注意が必要です。
前回 | DXL Step-by-Step |
0 件のコメント:
コメントを投稿