これらの記事の続きです:
nsf2dxl2web の挑戦(1)
nsf2dxl2web の挑戦(2)
nsf2dxl2web の挑戦(3)
ノーツデータベースのウェブ化ツールである nsf2dxl2web を紹介しています。前回は基本処理となる nsf2dxl と dxl2web 、そして簡易ウェブサーバーを使ってウェブ化されたコンテンツを確認する所までを紹介しました。
4回目となる今回はカスタマイズ編として、オプション機能として提供している2種類のカスタマイズ処理について紹介します。カスタマイズ不要で運用する場合は無視していただいてもいいのですが、「カスタマイズするとこんなことができるようになる」という程度でも知っておくと、思い通りの結果にならなかった場合の対応が楽になることもあるのでは・・と思っています。
前回、基本処理である(1)、(2)と(5)を紹介しているので、順番がおかしいように見えるかもしれませんが続きの(3)から紹介します。
【(3)customxsl.js】
この処理の説明をする前にこちらをご覧ください(特に画面の下半分):

これ↑はノーツの標準テンプレートである「ディスカッション」から作ったデータベースを nsf2dxl2web を使ってウェブ化した結果から「すべての文書」ビュー内のある文書を開いた時の様子です。この文書が参照している MainTopic というフォームがうまく XSL に変換しきれていないため、UI が乱れてしまっています。ちなみに同文書をノーツクライアントで見ると下のように見えます:

このように UI が乱れてしまう原因はいくつかあります。nsf2dxl2web のツール側でも可能な限り対応していくつもりではありますが、残念ながら 100% 再現できるようにするのは難しいと判断しています。その最大の原因は@式です。
@式はノーツが持つマクロ機能の1つです。このマクロがあることで柔軟な処理が実現できていることは事実だと思いますが、nsf2dxl2web のような変換ツールからすると酷な機能となっています。例えば nsf2dxl2web はノーツのフォーム内にサブフォームや共有フィールドが含まれていても(XSL との相性の良さもあって)UI を再現できるようになっています。しかし問題は例えば「サブフォームの参照先が@式の計算結果になっているようなケース」です。nsf2dxl2web は@式を無視するので、その計算結果がどのサブフォームを参照するべきなのかがわかりません。他にも@式の計算結果が含まれる設計要素を自動で正しく再現することはまだ 100% ではありません。それらの理由があり、上述のような UI の乱れが発生してしまうことがあります(いわゆる「ノーツの標準テンプレート」の類は設計要素内で@式が使われていることが多く、このような UI の乱れが発生しやすいと思っています)。
今回紹介する customxsl.js は、このように「自動処理だけでは再現できない UI をカスタマイズすることで修正する処理」を行う機能です。
nsf2dxl2web は標準で以下3つのノーツ標準テンプレート・カスタマイズ用の XSL セットを提供しています:
・メール
・ディスカッション
・ドミノディレクトリ(names.nsf)
nsf2dxl2web を展開したフォルダには customs というフォルダがあり、その中には
・mail
・disc
・names
という3つのサブフォルダがあるはずです。これらが上記3つの標準テンプレート・カスタマイズ用 XSL セットをそれぞれ含んでいます:

ちなみにディスカッションテンプレート用のサブフォルダ(disc)の中には MainTopic.xsl と Response.xsl という2つの XSL ファイルが存在しています:

これらのファイルの内容はそれぞれ以下のようになっています:
詳しい説明は省略しますが、それぞれディスカッションテンプレートの MainTopic フォームと Response フォームを表示するための(シンプルな)XSL となっています。
ではディスカッションテンプレートから作られたノーツデータベースを例に実際に UI をカスタマイズする手順を紹介します。といっても作業はごくシンプルで、上述のように適用したいフォームの UI 定義が記載された XSL ファイルを必要なフォームの分だけ(フォーム名).xsl というファイル名で用意し、一つのサブフォルダ(この例だと disc)内に格納しておきます。なお(フォーム名)部分は大文字小文字も正しく指定する必要があります。
その上で以下のコマンドを customxsl.js ファイルが存在しているフォルダ上で実行します:

すると上図のように指定した DXL フォルダ内の全文書に対して、その文書が参照しているフォーム定義を見つけ、そのフォーム定義を指定したカスタム定義用フォルダ内の XSL を適用して置き換えます。これによって dxl2web.js で作ったフォームの XSL ではなく、あらかじめ用意したフォームの XSL が使われるようになります。なお、この処理を実行後に再度同じデータベース内文書をウェブブラウザで見ると、以下のように(シンプルな見栄えではありますが)UI が乱れることなく表示することができるようになります(MainTopic フォームだけでなく Response フォームも書き換わっています):

なお、この3つの標準テンプレートのカスタマイズサンプルに限って MIT ライセンスでのオープンソースとします(ビジネス利用含めて改変可)。また提供されている3つ以外のデータベースに対しても同様に(そのデータベース内に含まれるフォームの XSL を用意すれば)この customxsl.js を使ってカスタマイズ可能です。
【(4)viewhtml.js】
もう1つのカスタマイズツールが viewhtml.js です。上述の customxsl.js は文書の UI をカスタマイズするツールでしたが、こちらはビュー/フォルダの UI をカスタマイズします。ただ customxsl.js では独自の XSL を用意して文書の UI をフルカスタマイズすることができましたが、ビュー/フォルダの UI については以下の2種類用意していて、そのどちらを使うかを切り替えるツールという位置づけです:
・Simple UI(デフォルトはこちら)
・Standard UI
デフォルトでもある Simple UI はビューに含まれる文書の一覧を簡易的な検索機能とページネーションによって表示する機能を持っています。この検索やページネーションには jQuery を併用した JavaScript で動的に行っています(そのためビュー描画の処理が軽くなっています)。大きな制約事項として別途検索エンジンを使って検索機能を実装しようとした際に(JavaScript で動的に文書リストを取得しているので)HTML 自体には文書へのリンクが含まれないため、各文書がクロール対象にならない(検索対象にならない)、という制約があります。
一方の Standard UI は全文書を一枚の HTML 内で静的に表示します。DataTables も有効になるため、簡易検索に加えてビューの列を指定したソートなど、Simple UI にはない便利な機能が含まれます。この構成の場合、HTML 内に全文書へのリンクも含まれるので検索エンジンのクローラーが文書レベルでのクロールもしてくれます(つまり各文書が検索対象になります)。一方、数万個レベルの文書が含まれるようなビュー/フォルダの場合、HTML 内で対象となる文書数が非常に大きくなるため、描画が非常に重くなります(場合によってはブラウザが out of memory エラーとなります)。「デフォルトで Standard UI がいい」と思う人もいらっしゃると思いますが、このような影響の大きい制約事項があるため、デフォルトの挙動としては Standard UI を採用せずに Simple UI を採用しています。
この Simple UI と Standard UI を切り替えて表示したい場合に viewhtml.js を使います。切り替えを行うには viewhtml.js のあるフォルダで以下のコマンドを実行します:
前回ウェブ化したデータベースを Standard UI に変換してみます:

この状態で(Standard UI で)ビューを参照すると以下のようになります。DataTables が有効なページネーションやフィルタリング(簡易検索)、テーブル列毎のソート機能が有効になった状態で全文書(つまりビュー/フォルダに含まれる全文書)へのリンクが含まれています:

変換前の同じビューも比較のために載せておきます。デフォルトの Simple UI の場合はこちらでした(Standard UI よりも少しシンプルになっているのがわかると思います):

詳しくは次回の記事で説明する予定ですが、クローラー型の検索エンジンを併用してウェブ化されたコンテンツを運用する場合、Standard UI の状態でないと(HTML 内に各文書への静的なリンクが含まれた状態でないと)文書が検索対象になりません。一方で Standard UI は文書数が数万レベルになると(ノーツデータベースの場合は結構ありえると思ってます)ビュー参照時にブラウザが out of memory エラーを起こしてビューが表示できない(したがって文書にもアクセスできない)ことが起こりえます。
というわけで、検索エンジン併用運用の場合は、
・いったん Simple UI から Standard UI に変更して、
・Standard UI の状態で検索エンジンのクローラーでクローリングして、
・クローリングが完了したら(必要に応じて) Simple UI に戻す
という処理をすることをお勧めします。
nsf2dxl2web の機能に関してはここまでで概ね紹介できたと思っています。次回は nsf2dxl2web からは少し離れますが、ここで少し紹介したようなウェブ化した複数データベースによるコンテンツを検索エンジンで全文検索する際の例を紹介するつもりです。
nsf2dxl2web の挑戦(1)
nsf2dxl2web の挑戦(2)
nsf2dxl2web の挑戦(3)
ノーツデータベースのウェブ化ツールである nsf2dxl2web を紹介しています。前回は基本処理となる nsf2dxl と dxl2web 、そして簡易ウェブサーバーを使ってウェブ化されたコンテンツを確認する所までを紹介しました。
4回目となる今回はカスタマイズ編として、オプション機能として提供している2種類のカスタマイズ処理について紹介します。カスタマイズ不要で運用する場合は無視していただいてもいいのですが、「カスタマイズするとこんなことができるようになる」という程度でも知っておくと、思い通りの結果にならなかった場合の対応が楽になることもあるのでは・・と思っています。
前回、基本処理である(1)、(2)と(5)を紹介しているので、順番がおかしいように見えるかもしれませんが続きの(3)から紹介します。
【(3)customxsl.js】
この処理の説明をする前にこちらをご覧ください(特に画面の下半分):

これ↑はノーツの標準テンプレートである「ディスカッション」から作ったデータベースを nsf2dxl2web を使ってウェブ化した結果から「すべての文書」ビュー内のある文書を開いた時の様子です。この文書が参照している MainTopic というフォームがうまく XSL に変換しきれていないため、UI が乱れてしまっています。ちなみに同文書をノーツクライアントで見ると下のように見えます:

このように UI が乱れてしまう原因はいくつかあります。nsf2dxl2web のツール側でも可能な限り対応していくつもりではありますが、残念ながら 100% 再現できるようにするのは難しいと判断しています。その最大の原因は@式です。
@式はノーツが持つマクロ機能の1つです。このマクロがあることで柔軟な処理が実現できていることは事実だと思いますが、nsf2dxl2web のような変換ツールからすると酷な機能となっています。例えば nsf2dxl2web はノーツのフォーム内にサブフォームや共有フィールドが含まれていても(XSL との相性の良さもあって)UI を再現できるようになっています。しかし問題は例えば「サブフォームの参照先が@式の計算結果になっているようなケース」です。nsf2dxl2web は@式を無視するので、その計算結果がどのサブフォームを参照するべきなのかがわかりません。他にも@式の計算結果が含まれる設計要素を自動で正しく再現することはまだ 100% ではありません。それらの理由があり、上述のような UI の乱れが発生してしまうことがあります(いわゆる「ノーツの標準テンプレート」の類は設計要素内で@式が使われていることが多く、このような UI の乱れが発生しやすいと思っています)。
今回紹介する customxsl.js は、このように「自動処理だけでは再現できない UI をカスタマイズすることで修正する処理」を行う機能です。
nsf2dxl2web は標準で以下3つのノーツ標準テンプレート・カスタマイズ用の XSL セットを提供しています:
・メール
・ディスカッション
・ドミノディレクトリ(names.nsf)
nsf2dxl2web を展開したフォルダには customs というフォルダがあり、その中には
・disc
・names
という3つのサブフォルダがあるはずです。これらが上記3つの標準テンプレート・カスタマイズ用 XSL セットをそれぞれ含んでいます:

ちなみにディスカッションテンプレート用のサブフォルダ(disc)の中には MainTopic.xsl と Response.xsl という2つの XSL ファイルが存在しています:

これらのファイルの内容はそれぞれ以下のようになっています:
(MainTopic.xsl)
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="html" encoding="UTF-8"/> <xsl:template match="/"> <html> <head> <title><xsl:value-of select="document/item[@name='Subject']" /></title> <link href="../resources/nsf2dxl2web.css" rel="stylesheet"/> <script src="../resources/nsf2dxl2web.js"></script> </head> <body> <h1><xsl:value-of select="document/item[@name='Subject']" /></h1> <br /> <table border="1"> <thead> <tr> <th>Subject:</th> <th><xsl:value-of select="document/item[@name='Subject']" /></th> </tr> </thead> <tbody> <tr> <td>Categories:</td> <td><xsl:value-of select="document/item[@name='Categories']" /></td> </tr> <tr> <td>From:</td> <td><xsl:value-of select="document/item[@name='From']" /></td> </tr> </tbody> </table> <hr/> <p style="text-align:right;">(<xsl:value-of select="document/noteinfo/created" />)</p> <p><xsl:copy-of select="document/item[@name='Body']" /></p> </body> </html> </xsl:template> </xsl:stylesheet>
(Response.xsl) <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="html" encoding="UTF-8"/> <xsl:template match="/"> <html> <head> <title><xsl:value-of select="document/item[@name='Subject']" /></title> <link href="../resources/nsf2dxl2web.css" rel="stylesheet"/> <script src="../resources/nsf2dxl2web.js"></script> </head> <body> <h1><xsl:value-of select="document/item[@name='Subject']" /></h1> <br /> <table border="1"> <thead> <tr> <th>Subject:</th> <th><xsl:value-of select="document/item[@name='Subject']" /></th> </tr> </thead> <tbody> <tr> <td>Categories:</td> <td><xsl:value-of select="document/item[@name='Categories']" /></td> </tr> <tr> <td>From:</td> <td><xsl:value-of select="document/item[@name='From']" /></td> </tr> </tbody> </table> <hr/> <p style="text-align:right;">(<xsl:value-of select="document/noteinfo/created" />)</p> <p><xsl:copy-of select="document/item[@name='Body']" /></p> </body> </html> </xsl:template> </xsl:stylesheet>
詳しい説明は省略しますが、それぞれディスカッションテンプレートの MainTopic フォームと Response フォームを表示するための(シンプルな)XSL となっています。
ではディスカッションテンプレートから作られたノーツデータベースを例に実際に UI をカスタマイズする手順を紹介します。といっても作業はごくシンプルで、上述のように適用したいフォームの UI 定義が記載された XSL ファイルを必要なフォームの分だけ(フォーム名).xsl というファイル名で用意し、一つのサブフォルダ(この例だと disc)内に格納しておきます。なお(フォーム名)部分は大文字小文字も正しく指定する必要があります。
その上で以下のコマンドを customxsl.js ファイルが存在しているフォルダ上で実行します:
$ node customxsl (対象の DXL が出力されているフォルダ) (カスタム XSL ファイルが格納されているフォルダ)

すると上図のように指定した DXL フォルダ内の全文書に対して、その文書が参照しているフォーム定義を見つけ、そのフォーム定義を指定したカスタム定義用フォルダ内の XSL を適用して置き換えます。これによって dxl2web.js で作ったフォームの XSL ではなく、あらかじめ用意したフォームの XSL が使われるようになります。なお、この処理を実行後に再度同じデータベース内文書をウェブブラウザで見ると、以下のように(シンプルな見栄えではありますが)UI が乱れることなく表示することができるようになります(MainTopic フォームだけでなく Response フォームも書き換わっています):

なお、この3つの標準テンプレートのカスタマイズサンプルに限って MIT ライセンスでのオープンソースとします(ビジネス利用含めて改変可)。また提供されている3つ以外のデータベースに対しても同様に(そのデータベース内に含まれるフォームの XSL を用意すれば)この customxsl.js を使ってカスタマイズ可能です。
【(4)viewhtml.js】
もう1つのカスタマイズツールが viewhtml.js です。上述の customxsl.js は文書の UI をカスタマイズするツールでしたが、こちらはビュー/フォルダの UI をカスタマイズします。ただ customxsl.js では独自の XSL を用意して文書の UI をフルカスタマイズすることができましたが、ビュー/フォルダの UI については以下の2種類用意していて、そのどちらを使うかを切り替えるツールという位置づけです:
・Simple UI(デフォルトはこちら)
・Standard UI
デフォルトでもある Simple UI はビューに含まれる文書の一覧を簡易的な検索機能とページネーションによって表示する機能を持っています。この検索やページネーションには jQuery を併用した JavaScript で動的に行っています(そのためビュー描画の処理が軽くなっています)。大きな制約事項として別途検索エンジンを使って検索機能を実装しようとした際に(JavaScript で動的に文書リストを取得しているので)HTML 自体には文書へのリンクが含まれないため、各文書がクロール対象にならない(検索対象にならない)、という制約があります。
一方の Standard UI は全文書を一枚の HTML 内で静的に表示します。DataTables も有効になるため、簡易検索に加えてビューの列を指定したソートなど、Simple UI にはない便利な機能が含まれます。この構成の場合、HTML 内に全文書へのリンクも含まれるので検索エンジンのクローラーが文書レベルでのクロールもしてくれます(つまり各文書が検索対象になります)。一方、数万個レベルの文書が含まれるようなビュー/フォルダの場合、HTML 内で対象となる文書数が非常に大きくなるため、描画が非常に重くなります(場合によってはブラウザが out of memory エラーとなります)。「デフォルトで Standard UI がいい」と思う人もいらっしゃると思いますが、このような影響の大きい制約事項があるため、デフォルトの挙動としては Standard UI を採用せずに Simple UI を採用しています。
この Simple UI と Standard UI を切り替えて表示したい場合に viewhtml.js を使います。切り替えを行うには viewhtml.js のあるフォルダで以下のコマンドを実行します:
$ node viewhtml (対象の DXL が出力されているフォルダ) (standard または simple)
前回ウェブ化したデータベースを Standard UI に変換してみます:

この状態で(Standard UI で)ビューを参照すると以下のようになります。DataTables が有効なページネーションやフィルタリング(簡易検索)、テーブル列毎のソート機能が有効になった状態で全文書(つまりビュー/フォルダに含まれる全文書)へのリンクが含まれています:

変換前の同じビューも比較のために載せておきます。デフォルトの Simple UI の場合はこちらでした(Standard UI よりも少しシンプルになっているのがわかると思います):

詳しくは次回の記事で説明する予定ですが、クローラー型の検索エンジンを併用してウェブ化されたコンテンツを運用する場合、Standard UI の状態でないと(HTML 内に各文書への静的なリンクが含まれた状態でないと)文書が検索対象になりません。一方で Standard UI は文書数が数万レベルになると(ノーツデータベースの場合は結構ありえると思ってます)ビュー参照時にブラウザが out of memory エラーを起こしてビューが表示できない(したがって文書にもアクセスできない)ことが起こりえます。
というわけで、検索エンジン併用運用の場合は、
・いったん Simple UI から Standard UI に変更して、
・Standard UI の状態で検索エンジンのクローラーでクローリングして、
・クローリングが完了したら(必要に応じて) Simple UI に戻す
という処理をすることをお勧めします。
nsf2dxl2web の機能に関してはここまでで概ね紹介できたと思っています。次回は nsf2dxl2web からは少し離れますが、ここで少し紹介したようなウェブ化した複数データベースによるコンテンツを検索エンジンで全文検索する際の例を紹介するつもりです。
(過去記事や続きはこちらです)
nsf2web2dxl の挑戦(4)
コメント