まだプログラマーですが何か?

プログラマーネタ中心。たまに作成したウェブサービス関連の話も https://twitter.com/dotnsf

タグ:nsf2dxl2web

ブログ更新が2か月ほど滞っておりました。いろいろなアプリ開発にいそしんでいたり、業務が忙しかったりもしたのですが、まあ言い訳はやめます。失礼しました。

で、その「いろいろなアプリ開発」の中の1つを何回かにわけて紹介したいと思います。もともと公開前提では作ってなかったのですが、友人の助言などから考えを変えて、とりあえずツールとしては近い将来に最初は招待制みたいな感じで(無料で)公開しようと思っています。

で、そのツールは名前を nsf2dxl2web(読み方は「えぬえすえふ・つー・でぃーえっくすえる・つー・うぇぶ」)です。正式名称ではないので公開時には変えるかもしれませんが、現在はこの名前でいくつもりです。この名称が用途を表しているともいえるのですが nsf2dxl2web は「ノーツデータベースのウェブ化」ツールの1つです。ただユースケースは限られていると思っています。

このシリーズの第一回目は紹介編と位置づけ、 nsf2dxl2web の持つ機能と、自分が考えているそのユースケースを紹介します。

【機能】
本当はまず開発背景を紹介したい気持ちもあるのですが、まずは nsf2dxl2web がどんなツールなのかを簡単に紹介します。以下のような機能と特徴を持ったツールです:

・指定したノーツデータベース (.nsf) をウェブ化する(ツール利用後は Domino サーバーは不要で、nginx などの HTTP サーバーで動きます)
・ノーツデータベースはウェブ用に作られている必要はない(実行時に HTTP タスク不要、というか Domino サーバー不要)。ノーツクライアント向けの UI をウェブで可能な限り再現することを目指しています
・対象ノーツデータベースの設計を理解している必要はない。標準データベースでも独自データベースでもノーツデータベースの設計内容から UI を再現します
・ウェブ化対象コンテンツはビュー/フォルダ一覧、全ビュー/フォルダ、ビュー/フォルダからリンクされた文書だけ(文書が参照するフォーム/サブフォーム/共有フィールドも対象、ページやアウトライン、ナビゲーター、エージェントなどは対象外)。オプションで検索エンジンによるコンテンツの検索が可能になる
・文書やフォーム内のリッチテキストは画像や添付ファイルを含めて再現される(添付ファイルはウェブ化後もダウンロード可)
・文書内の DB リンク、ビューリンク、文書リンクも再現される。リンク先が他 DB の場合、その DB も nsf2dxl2web でウェブ化されていれば各種リンクが有効になる
・UI はカスタマイズ可。文書の UI はウェブ化後のフォームの UI データをカスタマイズすることで全文書の UI が変わる
ウェブ化されたコンテンツは ACL がなく、リードオンリーとなる

2023110601



2023-11-06 の現時点で上記はすべて実現できています。ノーツのウェブ化ツールは数あれど、誰が作ったかもわからないような(作った人と連絡が取れなくなっているような)カスタムデータベースまでツール一発でウェブ化できるというのはかなり珍しいはず。

2023110505

(上がノーツ、下がブラウザで同じビューの同じ文書を見ている様子です。以下同様)

2023110506


またノーツの超便利な機能といえるリッチテキストは可能な限り再現することを心掛けています。テーブルやタブ、セクション、フォントなどの情報はもちろん、画像(添付されていたり、イメージリソースだったり、画像データのコピペだったり、・・)や添付ファイルも再現します。添付ファイルはクリックすればダウンロードできる形で表示されます:

2023110501

2023110502


DB リンクやビューリンク、文書リンクも再現され、リンク先が同じデータベース内である必要はありません(ただし外部データベースの場合、そのリンク先のデータベースも nsf2dxl2web でウェブ化されている必要があります):

2023110503

2023110504


ただし「ノーツをウェブで完全に再現するツール」ではありません。この辺りは↓の背景で補足します。自分の思いが含まれていて長いので(笑)、背景に興味はなく単に使ってみたいという人は読み飛ばしてください。


【背景】
そもそも何故この nsf2dxl2web を作ろうと思い立ったのか? 理由は1つだけではないのですが、最も大きな理由を紹介します。

まず私自身が元ノーツの製品開発者として働いていた時期があり、ノーツはその設計思想含めて非常に素晴らしい製品であると思っています(今もです)。

そして様々な理由でノーツデータベースは「塩漬け」と呼ばれるような運用形態になることがあります。ノーツからウェブに移行したいけど技術的なものも含めた様々な理由からあきらめるか、膨大な移行コストを覚悟する必要が生じてしまい、「それならやっぱりノーツで」と判断されるケースです。といっても引き続き有効活用されるというよりは「過去のデータ資産を捨てるという決断ができない」ために仕方なく使い続けるような形態です(この状態を「塩漬け」と呼んでいます)。これは利用者にとっても残念ですが、以前ノーツを提供する立場にあった自分としても非常に残念な運用形態です。積極的に使いたいわけではないのに移行できないから、参照のためだけであってもノーツを使い続けなければならない、というのは誰もが不幸な状態であって、そのような状態を解決できないだろうか、とずっと考えていたのでした。

このような背景の中で nsf2dxl2web を設計しています。つまりこれが nsf2dxl2web の設計思想の1つです。このような背景があるため、上述の機能一覧の最後に記述されている「ウェブ化されたコンテンツは ACL がなく、リードオンリーとなる」があります。今でもノーツを使って業務で新規に文書データを作ったり、編集したりしてる人に向けたウェブアプリケーション化ツールではありません。そのようなケースの場合は(今でもノーツの機能を使っている場合は)私自身はノーツを使い続けることが正しいと考えています。


【パフォーマンス】
ノーツの .nsf ファイル(データベースファイル)を nsf2dxl2web ツールを使ってウェブで(HTTP サーバーで)参照できるようになるまでに必要な時間は従来の方法と比べて劇的に改善されていると思っています。数字は私の手元にあるノーツのメールデータベース(文書数=約 75,000 、ファイルサイズ=約 12 GB)を私が使っている Windows 11 PC (AMD Ryzen 5 Pro 6650U + 16GB メモリ)で変換した場合の参考速度だと思ってほしいのですが、約4時間弱でした(作った私の感覚ですが、このツールに関して GPU は高速化にあまり役立ってないかも)。これは文書数が多いことに加えて設計自体がかなり複雑なデータベースでしたが、それでも4時間あればなんとかなる、ということです。ここまで文書数が多くなく、1000 程度の普通(?)の独自設計ノーツデータベースであれば変換に必要な時間は軒並み一瞬でした。

我ながらかなりの高パフォーマンスが実現できていると思います。12 GB のノーツデータベースの設計なんて調べるのも嫌なレベル(苦笑)だと思っていますし、そんなノーツデータベースのビューなんて何も考えずに <table> などでウェブ化したら、ビューを開こうにも(ブラウザが) out of memory エラーを多発することになるはずです。それをコマンドを数回実行して4時間待つだけ、でウェブ移行できるならかなり楽ですよね。


【カスタマイズ】
残念ながらすべてのノーツデータベースのすべての文書でフォーム定義された通りの UI を完全再現することはできていません。最大の理由は式言語やスクリプトといったマクロでカスタマイズされているケースが多く、例えば画面内に表示される値がマクロの実行結果に依存していると(このツールはマクロの実行エンジンを再現しているわけではないので)、ツールで変換しただけでは表示結果が期待通りにならないことがあります。


2023110601

ノーツ標準のディスカッションテンプレートから作ったデータベースの例。上がノーツで下が nsf2dxl2web で変換後。式言語を使った複雑なフォーム定義を完全に変換することができず、表示が乱れてしまっています:

2023110602


このような標準ツールだけでは UI が乱れてしまうケースのためにカスタマイズを可能にしています。nsf2dxl2web ではノーツの(サブフォームや共有フィールドを含む)フォームに相当する設計ファイルを設計から自動生成し、文書データを表示する際には、その文書が表示用に使っていたフォームの設計ファイルを参照して文書 UI を動的に生成します(具体的にな仕組みには XML と XSL を使っているのですが、そのあたりはまたいずれ詳しく・・)。なので、フォームの XSL をカスタマイズすることでそのフォームを使う全文書の見栄えをまとめて変更することができるようにしています。この辺りはノーツの設計思想を残しつつウェブ移行していて、これによってカスタマイズ作業そのものを容易にできています(ノーツ標準のメール、ディスカッション、ドミノディレクトリーのカスタマイズサンプルを提供します):
2023110603


nsf2dxl2web が標準で提供するサンプルを適用してカスタマイズすると↑のように表示の乱れを修正することができるようになります。自分があまり UI が得意でないこともあって、実際の業務データベースをウェブ移行する際にはこの「カスタマイズ」が必要になるケースもあるのではないかと思っていますが、この辺りを(有償サービスのような形で)支援していただけるような人に使っていただけないかと考えています。ただその場合であってもゼロから移行支援するのではなく、ある程度動くようになっている状態での UI カスタマイズになるので、作業量を減らすことはできるのではないかと考えています。


【ユースケース】
想定ユーザーというか「想定利用シーン」として、「ノーツデータベースをノーツの機能としては使っていないのにデータのウェブ移行ができなくて困っている」というユースケースを想定しています。そのようなケースであればほぼカスタマイズ不要(見栄えを変更したい場合にカスタマイズが必要になるかも)でウェブ化できます。ノーツデータベースをファイルサーバーとして利用しているようなケースであればピッタリだと思っていますが、そのようなケースがどのくらいあるのかは正直よくわかってないです。

逆に「ノーツをノーツとして使っているんだけど、ライセンスのコストを下げたいからウェブ化したい」というケースにはあまり当てはまらないと思っています。このツールでウェブ化したノーツデータベースは参照可能になりますが、新規作成や既存データの編集はできなくなります。繰り返しになりますが、このようなケースは個人的にはノーツを使い続けるべきケースだと思っています。


というわけで、そんなツールを現在進行形で作っています。このブログエントリのタイトルにもありますが、これは自分のプログラマーとしての「(色々な意味での)挑戦」の意味合いが強いものだと思っています。 とはいえ夢物語を語っているつもりはなく、スクリーンショットがあるように一応稼働できる状態には開発できています。次回は nsf2dxl2web がノーツデータベースをウェブ化する上での仕組みについて紹介する予定です。


(続きはこちらです)
nsf2web2dxl の挑戦(1)
nsf2web2dxl の挑戦(2)
nsf2web2dxl の挑戦(3)
nsf2web2dxl の挑戦(4)
nsf2web2dxl の挑戦(5)

このお盆休みの期間を使って、久しぶりに XSL を再勉強しました。10年くらい前の以前に使っていたころと比べて事情も変わっていたようで、リスキリングという意味でもいい機会だったと思っています。改めて「そもそも XSL とは?」から「なんで XSL をやり直そうと思ったのか」という背景も含め、まとめておきます。実はこの背景部分が少々複雑で、眺めの導入説明になっている点をご了承ください。


【HTML と CSS の関係】
XSL のブログエントリでなんで HTML と CSS ? と感じる人もいると思いますが、実はこれが上述の背景部分に絡んできます。 ウェブのデザインをしたことがある人はわかっていることだと思いますが、ウェブページって、
・表示するデータを HTML で
・その見栄えは CSS で
定義することになっています。極端な言い方をすると HTML 内には見栄えに関連する要素を入れずに(HTML5 以降では見栄えに関する要素は排除される方向です)、見た目はすべて CSS で、というやり方。これはこれでメリット・デメリットある気がしますが、役割分担としてはシンプルで悪くないと感じています。

ただ、自分はこの考え方に少し違和感があります。「見栄えを CSS で」という点はいいのですが、「表示するデータを HTML で」という部分は現実と少し違っているように感じてしまうのでした。

例えばこんな HTML があったとします:
<html>
<head>
<title>成績表</title>
</head>
<body>
<h1>成績表</h1>
<table id="mytable">
<thead>
<tr><th>名前</th><th>国語</th><th>数学</th></tr>
</thead>
<tbody>
<tr><td>佐藤</td><td>50</td><td>90</td></tr>
<tr><td>鈴木</td><td>70</td><td>60</td></tr>
<tr><td>田中</td><td>80</td><td>40</td></tr>
</tbody>
</table>
</body>
</html>

一見なんの変哲もない、<h1> の見出しと成績表が定義された HTML です。これらの見出しや表部分、細かくは全体のフォントや背景色なども含めて具体的にどのような見栄えになるのかは別途 CSS で定義する、というものです。 ここで私が「表示するデータは HTML で定義」していることについて違和感を感じるのは「<title> と <h1> の両方で "成績表" が定義されていること」です。

これは HTML 的にはブラウザウィンドウのタイトル部分(<title>)と、ブラウザ内に表示されるウェブページとしての見出し部分(<h1>)なので別々に定義する必要があるものです(別々に定義しようと思えばできる、という点ではその通り)。一方で「データとして」考えるとどちらも「見出し」のデータであって、「別々に定義するつもりがないのであれば、データとしては1つ」が正しいものです。後者の考え方でウェブページを作ろうとすると、「データを定義するはずの HTML 内で <title> と <h1> の2か所で同じ内容を(2重に)定義している」とも感じます。これはもちろん HTML の仕様ともかかわる問題ではあるのですが、その HTML の仕様のせいでデータを2重管理する必要が生じてしまっているのでした。 

2重管理しないといけないものが「表示するデータを定義するもの」・・・これが私の感じた違和感でした。本来「表示データ」は2重、3重に定義せず正規化されているべきものであって、その内容を表示ページの内容に従って HTML に配置しなおして(ここで2重化されるのは理解できる)、最後に CSS で HTML の見栄えを定義する、という考え方がしっくりくるのでした。 要するに「HTML が表示データの定義」と呼ぶことに抵抗を感じていて、「表示データをウェブページの配置に沿って変換した結果が HTML」と考えるとすっきり理解しやすいのでした:
(表示データの定義(の XML 例))
<?xml version="1.0" encoding="Shift_JIS"?>
<成績表>
  <見出し>成績表</見出し>
  <結果 名前="佐藤" 国語="50" 数学="90"/>
  <結果 名前="鈴木" 国語="70" 数学="60"/>
  <結果 名前="田中" 国語="80" 数学="40"/>    
</成績表>

  ↓(変換)

(表示ウェブページの HTML) <html> <head> <title>成績表</title> </head> <body> <h1>成績表</h1> <table id="mytable"> <thead> <tr><th>名前</th><th>国語</th><th>数学</th></tr> </thead> <tbody> <tr><td>佐藤</td><td>50</td><td>90</td></tr> <tr><td>鈴木</td><td>70</td><td>60</td></tr> <tr><td>田中</td><td>80</td><td>40</td></tr> </tbody> </table> </body> </html>

(※この後 msxsl.exe というツールを使う関係でわざと XML に encoding="Shift_JIS" 指定を加えています。msxsl.exe を使わない場合は encoding 指定なしで(UTF-8 で)構いません)


【XSL とは】
XSL(eXtensible Stylesheet Language) は上述の「表示データをウェブページの配置に沿って変換した結果が HTML」の「変換ルール」に関わるものです。そして実際の変換処理そのものは XSLT(XSL Transform) と呼びます。

具体的に XML と XSL を用意して、XSLT を行ってみます。まず以下のような2つのテキストファイル data.xml と data.xsl を用意します(いずれもシフト JIS エンコードで保存してください):

(data.xml)
<?xml version="1.0" encoding="Shift_JIS"?>
<成績表>
  <見出し>成績表</見出し>
  <結果 名前="佐藤" 国語="50" 数学="90"/>
  <結果 名前="鈴木" 国語="70" 数学="60"/>
  <結果 名前="田中" 国語="80" 数学="40"/>    
</成績表>


(data.xsl)
<?xml version="1.0" encoding="Shift_JIS"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" encoding="Shift_JIS"/>
<xsl:template match="/">
<html>
<head>
<title><xsl:value-of select="成績表/見出し" /></title>
</head>
<body>
<h1><xsl:value-of select="成績表/見出し" /></h1>
<table id="mytable">
<thead>
<tr><th>名前</th><th>国語</th><th>数学</th></tr>
</thead>
<tbody>
<xsl:for-each select="成績表/結果">
<tr>
  <td><xsl:value-of select="@名前" /></td>
  <td><xsl:value-of select="@国語" /></td>
  <td><xsl:value-of select="@数学" /></td>
</tr>
</xsl:for-each>
</tbody>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>



【参照】
XSLTの使い方・入門チュートリアル


data.xml が表示データの定義ファイルで、data.xsl が data.xml を HTML に変換する際の変換ルールを定義しています。<xsl:template match="/"> と </xsl:template> の間で HTML が定義されていて、<xsl:value-of> と <xsl:for-each> を使って表示データ(data.xml)のテキスト値や属性値を HTML に変換しています。

XML と XSL を使って HTML に変換(= XSL Transform)する方法はいくつかありますが、比較的簡単なマイクロソフト製コマンドラインツール msxsl.exe を使った例を紹介します、、が、このツールは便利ではあるのですが、かなり古いものらしく、マイクロソフトのサイトには存在しておらず、インターネットアーカイブ上でしか見つけることができませんでした。というわけでこちらからダウンロードしてください:
http://web.archive.org/web/20140812045521/http://www.microsoft.com/en-us/download/details.aspx?id=21714


ダウンロードできたら Windows 上でコマンドプロンプトを開き、data.xml , data.xsl の存在するフォルダに移動します。そして msxsl.exe にパスを通すか、data.xml, data.xsl と同じフォルダに msxsl.exe をコピーしてください。

準備ができたら以下を実行します:
> msxsl.exe data.xml data.xsl

msxsl.exe は2つのパラメータを指定して XSLT 処理を実行します。最初のパラメータが XML ファイルのパス、2つ目のパラメータが XSL ファイルのパスです。正しく実行できた場合は XSLT の実行結果が画面上に表示されます:
2023082001

※このコマンドプロンプト画面ではシフト JIS でないと文字化けを起こしてしまいます。その理由もあって data.xml と data.xsl をシフト JIS で作ったという背景があるのでした。

個人的には XSLT 処理をプログラミング内で行うこともあるのですが、そこでうまくいかないケースに遭遇した場合、この msxsl.exe を使うとエラー発生時の内容や箇所をエラーメッセージとして表示してくれるので、主にデバッグ目的で今でもよく使っています。


この XSL(T) を使うことで、
・表示するデータは XML で、
・XML を XSL を使って変換した HTML を使って、
・HTML の見栄えは CSS で、
それぞれ役割分担して定義する、ということが可能になります。例えばデータベースから取り出した直後のデータは XML に近い形をしていることが多いので、そこから HTML を生成する際に XSL を使い、細かな見栄えは別途 CSS で定義する、という役割分担が、自分の理解の上でも腹落ちしやすいと考えています。


【ノーツのデータ構造に似ている】
ここまでに紹介してきた XML と XSL の関係というのが、HCL ノーツ/ドミノでいうところの「文書(document)」と「フォーム(form)」の関係に似ていると思っています。ノーツではデータそのものは文書として格納されていて、その見栄えは適用されるフォームによって定義されています。同じ文書でも適用さえるフォームによって見栄えが変わる点も含めて似ているのですが、加えてノーツのデータは DXL(Domino XML Language) という特殊な XML フォーマットでインポート/エクスポートできる機能があるので、XML/XSL との相性も悪くなかったりします。

まあ現実のノーツデータはそこまで単純ではありません。ノーツにはサブフォームや共有フィールドといった設計の再利用の仕組みがあったり、HTML とは異なる独特なリッチテキスト編集/保存機能があったり、細かな所では XSL のテンプレート名称に使ってよい文字とノーツのフォーム/サブフォーム名に使ってよい文字に違いがあったりして、単純に XML/XSL 対応ができるわけではなかったりします。

とはいえ、それでもノーツのデータをノーツ外で取り扱う(これ自体がすごくハードルの高いことだったりします)ことを目指そうとすると、 DXL にエクスポートした上で XML/XSL の仕組みをベースにすることでノーツ外でも取り扱いできるようにするための近道のようには感じています。どこまで実現できるかわからないのですが、個人的にそんなツールの開発を始めていて、いずれどこかで紹介できればと思っています。




 

このページのトップヘ