5.5.3. 表組み例題(2)

 今度は table-row で table-cell をグルーピングする例題です。おそらくもっとも一般的な形態ではないかと思います。この例では DocBook1から抜粋、簡略化した DTD(リスト 5.7)とサンプル文書(リスト 5.8)を用います。

リスト 5.7 [ table2.dtd ]
<!ELEMENT article       (title,table)>
<!ELEMENT title         (#PCDATA)>
<!ELEMENT table         (title?,tgroup)>
<!ELEMENT tgroup        (colspec*,thead?,tfoot?,tbody)>
<!ATTLIST tgroup        cols CDATA #REQUIRED>
<!ELEMENT colspec       EMPTY>
<!ATTLIST colspec       colnum CDATA #IMPLIED
                        colname CDATA #IMPLIED
                        colwidth CDATA #IMPLIED>
<!ELEMENT thead         (row)>
<!ELEMENT tfoot         (row)>
<!ELEMENT tbody         (row+)>
<!ELEMENT row           (entry+)>
<!ELEMENT entry         (#PCDATA)>
<!ATTLIST entry         colname CDATA #IMPLIED
                        namest CDATA #IMPLIED
                        nameend CDATA #IMPLIED
                        align (left|right|center|justify) "left">
リスト 5.8 [ table2.xml ]
<?xml version="1.0"?>
<!DOCTYPE article SYSTEM "table2.dtd">
<article>
  <title>The sample formatting of the table</title>

  <table>
    <title>Mark-up Languages and Style Sheets</title>
    <tgroup cols="5">
      <colspec colname="rowhead" colwidth="20" />
      <colspec colwidth="30" />
      <colspec colwidth="30" />
      <colspec colwidth="30" />
      <colspec colwidth="30" />
  
      <thead>
        <row>
          <entry colname="rowhead"></entry>
          <entry align="center">HTML</entry>
          <entry align="center">XHTML</entry>
          <entry align="center">XML</entry>
          <entry align="center">SGML</entry>
        </row>
      </thead>
      <tbody>
        <row>
          <entry colname="rowhead">CSS</entry>
          <entry align="center">supported</entry>
          <entry align="center">supported</entry>
          <entry align="center">not supported</entry>
          <entry align="center">not supported</entry>
        </row>
        <row>
          <entry colname="rowhead">DSSSL</entry>
          <entry align="center">supported</entry>
          <entry align="center">supported</entry>
          <entry align="center">supported</entry>
          <entry align="center">supported</entry>
        </row>
        <row>
          <entry colname="rowhead">XSL</entry>
          <entry align="center">not supported</entry>
          <entry align="center">supported</entry>
          <entry align="center">supported</entry>
          <entry align="center">not supported</entry>
        </row>
      </tbody>
    </tgroup>
  </table>
</article>

 DTD は先程のリスト 5.4よりも多少混み入っていますが、表の構造としては、むしろこちらの方が素直になっています。文書中の colspec タグは table-column として、row タグは table-row としてフォーマットするのが良さそうだ、と察しがつくことと思います。それでは、この文書に対するスタイルシートの例を見てみることにしましょう。

リスト 5.9 [ table2.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 (rowhead?)
  (equal? (attribute-string "colname") "rowhead"))
(define (cell-align)
  (let ((attr (attribute-string "align")))
    (case attr
      (("right") ’end)
      (("center") ’center)
      (("justify") ’justify)
      (else ’start))))

(element article
  (make simple-page-sequence
    page-width: 210mm
    page-height: 297mm
    top-margin: 30mm
    bottom-margin: 20mm
    left-margin: 30mm
    right-margin: 30mm))

(element (article title)
  (make paragraph
    font-size: 18pt
    line-spacing: 18pt
    quadding: ’center
    space-after: 20mm))

(element table
  (make sequence
    (make paragraph
      font-family-name: "Helvetica"
      space-after: 8pt
      (process-matching-children ’title))
    (make table
      table-border: #t
      (process-matching-children ’tgroup))))

(element colspec
  (make table-column
    width: (* 1mm (string->number
                  (attribute-string "colwidth")))))

(element row
  (make table-row))

(element (thead row entry)
  (make table-cell
    cell-before-column-margin: 2pt
    cell-after-row-margin: 4pt
    cell-after-column-border: (rowhead?)
    cell-after-row-border: #t
    cell-background?: #t
    background-color: *gray80*
    cell-crossed: (if (rowhead?) ’with #f)
    (make paragraph
      quadding: (cell-align))))

(element (tbody row entry)
  (make table-cell
    cell-before-column-margin: 2pt
    cell-after-row-margin: 4pt
    cell-after-column-border: (rowhead?)
    cell-background?: (rowhead?)
    background-color: *gray80*
    (make paragraph
      quadding: (cell-align))))

</style-specification-body>
</style-specification>
</style-sheet>

 table-column の幅ですが、今回は colspec タグの colwidth 属性がありますので、この属性の値を利用することにします。属性の値は attribute-string によって取得しますが、これによって得られた値は文字列ですので、そのままでは特質 width: の指定値として使うことはできません。そこで一度数値に変換する必要があります。string->number は、文字列をそれに相当する数値に変換する手続きです。width: の指定値は length-spec ですから、この数値をさらに加工する必要があります。ここでは、単位元として 1mm をかけることで length-spec へと変換を行なっています。
 次に table-row ですが、このフロー・オブジェクトは単純に table-cell をグループ化するだけのものですので、指定すべき特質などは特にありません。重要なのは、table-rowが table 内の各行として、table-cell を正しくグループ化できる位置で生成されるよう指定することです。
 さて、table や table-cell にも先程の例になかった特質をいくつか用いていますので、そちらも説明しておくことにしましょう。
 まず、table フロー・オブジェクト・クラスの特質 table-border: ですが、これは表の枠線の指定になります。table-border: が取りうる値は論理値または table-borderフロー・オブジェクトになります。単純に線を引くだけの場合は論理値の指定で十分と思われますが、線の太さや形状などを指定する場合には table-border を用います。論理定数 #t の代わりに table-border を用いた例を次に示します。

例 5.6
(make table
  table-border: (make table-border
                  line-thickness: 0.5pt
                  line-repeat: 2
                  line-sep: 0.5pt)
  (process-matching-children ’tgroup))

 この例では、太さ 0.5pt の線を 2 本引くことになりますので、表が二重線で囲まれることになります。table-border の特質は box フロー・オブジェクト・クラスとほぼ同様です。また、この table-border は table-cell の枠線を引く場合にも使用できます。このとき、table と table-cell、あるいは table-cell 同士の枠線が重なりあって、table-borderの指定が衝突する場合があります。ここでは例を示しませんが、このような場合にはtable-border の特質 border-priority: を指定します。border-priority: が大きな値を持つほど、そのフロー・オブジェクトが優先されます。
 次に table-cell の指定ですが、特質 cell-before-column-margin: はセル内部の余白を意味します。余白は列進行方向と行進行方向のそれぞれについて指定することができます。枠線も同様で、cell-after-column-border: などで指定します。この特質の指定値は table の table-border: に同じです。次に特質 cell-crossed: ですが、これはセル内に引く斜線の指定です。指定できる値はシンボル with、against、both のいずれかで、図5.8のようにフォーマットされます。


図 5.8 cell-crossed: の指定

最後に、スタイル指定ではありませんが、paragraph の行揃え指定値の取得に条件式 case を用いていますので、こちらを少し説明しておきます。まず、条件式 case の構文を以下に示します。

(case <キー> <節 1> <節 2> ...)
  • 節は以下の形式をとる
    ((データ 1 ...) <式 1> <式 2> ...)
  • 最後の節は以下の “else 節” を記述することもできる
    (else <式 1> <式 2> ...)

 if がテスト部を 1 つしか持たなかったのに対し、case は複数のテスト節を持ちます。各節は、順にキーとデータが一致するかを調べ、一致した場合は後続の式が評価されます。case 式が返す値は、節の最後に評価された式となります。キーがどの節のデータとも一致しなかった場合、最後に
else 節を記述してこれを処理することができます。リスト 5.9の場合、entry タグの align 属性は値が指定されている場合と未指定の場合とがありますので、指定されている場合の値をテスト節のデータとし、未指定時のデフォルト値である “left”
else 節で返すようにしています。


図 5.9 table2.xml(リスト 5.8)のフォーマット例

[1] DocBook Open Repository <http://docbook.sourceforge.net/> 参照。

<<prev      next>>