5.5.4. 表組み例題(3)― 行・列の結合

 次に行や列の結合について考えて見ます。先のリスト 5.8では、同じ行内の entry タグに同一のテキストが連続している場合があります。そこで、同一テキストが連続する場合にこれを一つの列として記述することにしてみましょう。この変更を行なったのがリスト 5.10です 。

リスト 5.10 [ table3.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 colname="html" colwidth="30" />
      <colspec colname="xhtml" colwidth="30" />
      <colspec colname="xml" colwidth="30" />
      <colspec colname="sgml" 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 namest="html"
                 nameend="xhtml" align="center">supported</entry>
          <entry namest="xml"
                 nameend="sgml" align="center">not supported</entry>
        </row>
        <row>
          <entry colname="rowhead">DSSSL</entry>
          <entry namest="html"
                 nameend="sgml" align="center">supported</entry>
        </row>
        <row>
          <entry colname="rowhead">XSL</entry>
          <entry align="center">not supported</entry>
          <entry namest="xhtml"
                 nameend="xml" align="center">supported</entry>
          <entry align="center">not supported</entry>
        </row>
      </tbody>
    </tgroup>
  </table>
</article>

 entry タグの namest 属性および nameend 属性は、セルがどの列に始まってどの列で終わるかを示す属性です。つまり、これらの属性で指定された範囲の列を結合して表示することになります。それでは、この文書に対するスタイルシートをリスト5.11に示します。なお、長くなりますので先程のリスト 5.9から変更のあった部分のみの抜粋とします。

リスト 5.11 [ table3.dsl(抜粋)]
(define (colname-to-colnum name)
  (case name
    (("html") 1)
    (("xhtml") 2)
    (("xml") 3)
    (("sgml") 4)
    (else 0)))

(define (spancols)
  (let ((stnum (colname-to-colnum (attribute-string "namest")))
        (endnum (colname-to-colnum (attribute-string "nameend"))))
    (if (or (equal? stnum 0) (equal? endnum 0))
        0 (- endnum stnum))))

(element (tbody row entry)
  (make table-cell
    cell-before-column-margin: 2pt
    cell-after-row-margin: 4pt
    cell-before-row-border: #t
    cell-after-column-border: #t
    cell-background?: (rowhead?)
    n-columns-spanned: (+ 1 (spancols))
    background-color: *gray80*
    (make paragraph
      quadding: (cell-align))))

 列の結合数は、table-cell フロー・オブジェクト・クラスの n-columns-spanned: に指定します。entry タグの namest 属性などから直接結合数を求めることはできませんので、列名を一旦数値に置き替えて計算することにします。これを行なっているのが (colname-to-column) です。本来であれば、動的な変更に対応できるよう assoc(association list)などを使用するのがよいと思いますが、少々複雑になりますので、ここでは case 式を使って固定的に値を決定しています。
 さて、 namestnameend を数値に変換したところで、これらの差をとって結合数がいくつになるかを計算しなくてはいけません。しかし、 namestnameend は必ず指定されているとは限りませんので、この場合も考慮する必要があります。リスト5.11では、これらの属性が指定されていなかった場合の変換数値を 0 とし、 namestnameend のいずれかが 0 であった場合は差を求めずに 0 を返すようにしています。この条件判断には or を利用します。 or の構文は次の通りです。

(or <式 1> <式 2>)

 手続き or は、式1 と式2 の評価結果のいずれかが真である場合に論理定数 #t> を返します[2]。リスト 5.11の例では、stnumendnum のいずれかが 0 であった場合に #t> となり、if 式が 0 を返します。そうでなければ、endnum から stnum を引いた値を返します。この結果は table-cell の n-columns-spanned: で参照しますが、endnum から stnum を単純に引いた値では、求める連結数よりも 1 少い値になってしまいますので、指定値に 1 を加算するようになっています(namestnameend が未指定だった場合に spancol が 0 を返すのはそのためでもあります)。
 ここでは例を示しませんが、table-column にも特質 n-columns-spanned: があります。なお、先に述べたように table-column にこの特質を指定した場合は width: の指定が無効になります。また、列ではなく行を結合する場合は n-columns-spanned: の代わりに特質 n-rows-spanned: を用います(この特質を持つのは table-cell のみです)。例題などを参考に色々試してみるとよいのではないでしょうか。

[2]これに対し式 1 と式 2 の両方が真の場合のみ #t を返す and 手続きもあります。

<<prev      next>>