まず、DTD(リスト 5.4)と XML 文書(リスト 5.5)を見てみましょう。
リスト 5.4 [ table1.dtd ]
<!ELEMENT score-sheet (header+,score+)> <!ELEMENT header (#PCDATA)> <!ATTLIST header start (YES|NO) "NO"> <!ELEMENT score (#PCDATA)> <!ATTLIST score start (YES|NO) "NO">
リスト 5.5 [ table1.xml ]
<?xml version="1.0"?> <!DOCTYPE score-sheet SYSTEM "table1.dtd"> <score-sheet> <header start="YES">H.Y</header> <header>K.K</header> <header>C.M</header> <score start="YES">89</score> <score>78</score> <score>90</score> <score start="YES">72</score> <score>96</score> <score>86</score> <score start="YES">93</score> <score>88</score> </score-sheet>
これは、ある 3 人の人物の得点表です(何の得点かは適当に想像してください)。得点表を表として表わそうとした場合、score-sheet タグを table フロー・オブジェクト・クラスに、また、header タグと score タグを table-cell フロー・オブジェクト・クラスに対応させることができそうだ、ということがわかると思います。また、この文書の構造からは行の区切りが不明確ですので、table-row フロー・オブジェクト・クラスに対応する要素がないこと、列数はひとまず最大 3 列(つまり、3 つの table-columnフロー・オブジェクトを持つ)と考えられることがわかります。
それではどのようにスタイル指定を行えばよいか、実際に見ていくことにしましょう。まずは、score-sheet タグに対する table フロー・オブジェクト・クラスの指定ですが、これには必須となっている特質はありませんので、とりあえずはすべて初期値任せでも構いません。ここでは表の幅だけを指定することにします。表の幅を指定するには特質 table-width: を使用します。各列の幅がそれぞれ 30mm であるとすると、表の幅は 30mm × 3 = 90mm ですから、指定は次のようになります。
例 5.3
(element score-sheet (make table table-width: 90mm))
次に必要になるのは table-column ですが、文書構造上 score-sheet タグ のすぐ後は header タグとなっており、header タグはこの後 table-cell として指定するわけですから、score-sheet タグと header タグの間に指定する必要があります。ただし、両者の間に位置するタグというのはありませんので、ここでは score-sheet タグの指定にぶらさげる形にします。
例5.4
(element score-sheet (make table table-width: 90mm (make table-column width: 30mm) (make table-column width: 30mm) (make table-column width: 30mm) (process-children)))
table-column の幅は特質 width: で指定します。この指定は、後程説明する特質 n-columns-spanned: に 1 以上の値を指定している場合、または DSSSL プロセッサが table-auto-width 機能を実装している場合を除き必須です。table-auto-width 機能とは表の列幅や表全体の幅を自動的に決定する機能です。一般に、列幅の自動計算は処理が複雑になるため、処理速度の低下につながることに注意してください。これは、表の構造が複雑になるほど顕著になります。
さて、再びスタイル指定の例に目を戻すと、最後の行に (process-children) があることに気付かれることでしょう。ここで、第2章の make 式(p.30)の説明を思い出してください。子要素を処理した結果を返す(process-children) が暗黙のうちに補われるのは、make 式末尾のcontent-expressionが省略されている場合です。先の例では、(maketable-column …) という content-expression があるため、(process-children) は補われません。これは、header タグや score タグが処理されたとき、生成される tablecell フロー・オブジェクトが table フロー・オブジェクトの子にならないことを意味します。組み合わせのルールにも書いたように、table-cell は table の子でなければいけませんので、このままではエラーになります。そのため、ここでは (process-children) を明示的に記述する必要があります。
少し長くなりましたが、table-cell の指定に移ることにしましょう。header タグも score タグも本質的には同じですので、ここでは header タグについて見ていくことにします。先に述べたように、リスト 5.5には table-row に相当するものがありません。そこで、行のはじまり(あるいは終端)を table-cell に指定する必要があります。ある table-cell が行のはじまりであるかどうかは、starts-row?:(終端指定の場合は ends-row?:)で指定します。header タグには start 属性がありますので、これをstarts-row?: の指定に利用することにします。
(define *device-rgb* (color-space "ISO/IEC 10179:1996//Color-Space Family::Device RGB")) (define *Gray80* (color *device-rgb* 0.8 0.8 0.8)) (define (start-cell?) (equal? (attribute-string "start") "YES")) (element header (make table-cell starts-row?: (start-cell?) cell-background?: #t background-color: *Gray80* (make paragraph quadding: ’center)))
start 属性が YES の場合に starts-row?:に #t を指定します。サンプルでは、この判断を (start-cell?) で行っています。(start-cell?) の定義にある equal? は、2つの引数をとり、両者が一致すれば #t を、それ以外は #f を返す手続きです。一般には if などの条件式と組み合わせて使うことが多いのですが、この場合は求める値と equal? の返す結果が一致しているのでそのまま用いています。
background-color: は table-cell の内部を塗り潰す色の指定ですが、これが有効なのは特質 cell-background?: に #t を指定した場合に限られます。table-cell 自体の特質指定はここまでです。
さて、table-cell フロー・オブジェクトが表示する内容ですが、これは表示領域を形成する任意のフロー・オブジェクトになります。つまり、テキストに限らず画像や別の表を table-cell の内容とすることができます。ここでの表示内容はテキストですので、paragraph フロー・オブジェクトを生成するよう指定し、テキストが中央揃えになるようにしています。
これで、リスト 5.5を表として表示することができます。ところで、この例では最上位の score-sheet タグを table フロー・オブジェクト・クラスに割り当てているため、ページシーケンスをどこに指定するかが問題になります。このような場合の指定としては、ページシーケンスの指定を score-sheet タグに含めてしまうか、root 要素に指定するのがよいでしょう。以下、図5.7にフォーマット例を、リスト 5.6にスタイルシートの例を示します。
図 5.7 table1.xml(リスト 5.5)フォーマット例
リスト 5.6 [ table1.dsl ]
<!DOCTYPE style-sheet PUBLIC "-//James Clark//DTD DSSSL Style Sheet//EN"> <style-sheet> <style-specification> <style-specification-body> (define *device-rgb* (color-space "ISO/IEC 10179:1996//Color-Space Family::Device RGB")) (define *gray80* (color *device-rgb* 0.8 0.8 0.8)) (define %column-width% 30mm) (define %table-width% (* %column-width% 3)) (define (start-cell?) (equal? (attribute-string "start") "YES")) (root (make simple-page-sequence page-width: 182mm ; JIS-B5 page-height: 257mm top-margin: 30mm bottom-margin: 20mm left-margin: 30mm right-margin: 30mm)) (element score-sheet (make table table-width: %table-width% (make table-column width: %column-width%) (make table-column width: %column-width%) (make table-column width: %column-width%) (process-children))) (element header (make table-cell starts-row?: (start-cell?) cell-background?: #t background-color: *gray80* (make paragraph quadding: ’center))) (element score (make table-cell starts-row?: (start-cell?) (make paragraph quadding: ’center))) </style-specification-body> </style-specification> </style-sheet>