リスト 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/> 参照。