5.5.2. 表組み例題(1)

 ここからは例題を使って解説を進めていくことにします。まず最初は、table、tablecolumn、table-cell のみを使う例題からはめましょう。
 まず、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>

<<prev      next>>