XSL-FO 試行錯誤 カレンダーを自動生成したい(構想編)

師走まで間もなくとなり、日中の気温もかなり下がってきました。来年のカレンダーを用意する時期ですね。
ちょっと「XSL-FOでオリジナルのカレンダーを作りたい」なんてこともあるのではないでしょうか。

高々12月分であるのでDTPソフトウェアやXSL-FOの直書きで頑張っても何とかなるかもしれませんが、来年もある程度使い回せるようにしたり、2021年のように直前の変更があるかもしれないことを考えると自動化したいところです。

実現したいカレンダーは次のようなものを想定します。手書きであるため半端なところまでしか日付がありません。

実現したいカレンダーのラフ

今回は構想編ということで、方針や使っていくFO、XSLTのアタリを付けていきましょう。

ページレイアウト

カレンダーを作るにあたって、先ず決めなければいけないことは「どの程度グラフィカルにするか」、具体的にはページレイアウトをどこまで制限するか、ということです。
個別箇所の自由度を上げるとその分だけ自動化できる箇所は少なくなります。

とはいっても、「高々12月分」と書いたように12パターン程度であれば12通りのページレイアウトを用意しても良いでしょう。今回はページレイアウトを1つに定めることにします。

  • ページレイアウトは1つ
  • 毎月1ページで構成

(スケジュール帳を組むのであれば「1月分の中にページ分割はあるか」も考慮しなければなりません。AH XSL Formatterであれば見開き要素が使えるため比較的簡単に対応できます。その場合は、見開きの左右に分割される位置と格子の位置を上手く配置する工夫が必要になりますね。)

ページサイズはA3縦(縦420mm、横297mm)にしましょう。

毎ページ登場する内容

月ごとにページを分けるのであれば、各ページに共通して登場するのは
年でしょうか。来年であれば「2022年」ですね。これはstatic-contentに置くことにします。
また、年度(4月始まり)で設定したい場合、途中で年の表示は変わりますね。このことに備えて、マーカーで取り出した値を使うことにします。

後述するように画像を上半分にページ幅一杯に表示する際、画像の上にstatic-contentを被せて表示することが可能です。AH XSL Formatterではregion表示の優先順位も自由が利きます。

マス目表示を実現するFO

ここは奇をてらわずtableを使っていきます。

カレンダーでは、曜日をカラムのタイトルとして、1週目、2週目、…をrowのまとまりとして、それぞれの日付がセルとして表されます。
常にマス全体を長方形にすることとして、rowの数は5週分にします。

例示した画像のように日付の始まりと曜日の始まりが一致するなら並べるだけなので楽ですが、そうではないためXSLTで自動化することになります。当月の他、その先月または来月の数日間の情報が必要になることも、お手元のカレンダーから想像が付くのではないでしょうか。

元となるカレンダー用のXMLがある場合は、そこにテンプレートを適用するだけで済むでしょう。

日付の位置を調整して自動生成するXSLT

XSLT 2.0からは日付のための関数や型を利用できます。ある日付の曜日を取りたいときはたとえばformat-date('[w1]')とすればxs:integer型ではありますが曜日が取得できます。このことと日付用のduration、そしてmodを組み合わせればカレンダーのマス目が実現できそうです。

休日・祝日(今回は対応しない)

休日、祝日の背景色を変更することについて考えます。日曜を示すカラムが先に決まるため「毎週日曜の背景色を変更する」であればカラムに対して設定したりすれば良いでしょう。問題は祝日です。XSLTの標準ライブラリは日本の祝日対応まではしてくれていません。確実なソースとなると、内閣府のページにあるCSVでしょうか。

「国民の祝日」について – 内閣府

XSLT 2.0以降でCSVをパース可能なようにプログラムを書くこともできますが(<xsl:analyze-string>などを使います)、とりあえず今回は対応しないことにします。

そのほか二十四節気なども同様に、「どこかから日付と紐付いた外部ソースを得る」「XSLTで取り込んで展開する」といった手順になるでしょう。

各月のイラスト、写真の設定方法

話をFOメインに戻します。

ページレイアウトは1つだけにすることを決めました。
AH XSL Formatterではページマスターに背景画像を設定することも可能ですが、
1つのページレイアウトを使い回すのであれば、フローコンテンツとして指定していく形になるでしょう(実はマーカーに画像を指定することも可能ですが、テンプレートの記述量は大して変わりません)。

画像のクリッピングや位置調整については背景画像の方がプロパティ指定の余地が広いため、ブロックコンテナーの背景画像として配置することにします。

画像をページギリギリまで表示したい場合、フローコンテンツを塗り足し領域まで表示させる必要があります。この辺りのTipsは『AH XSL Formatter 拡張仕様使いこなしガイド』に載せていたりします。

次回予告

次回はカレンダーを実現するための関数、テンプレートについて考えていく予定です。

参考資料