7.4.5. 目次生成を含むスタイルシートの例

 最後に、目次の自動生成を含むスタイルシートのサンプルを示します。ここでは目次の生成が主目的ですので、文書の要素は必要最低限のものに簡略化してあります。また、XML 文書も一部を中略してあります。

リスト7.4 [ tinybook.dtd ]

<!ELEMENT book        (title,chapter*)>
<!ELEMENT chapter     (title,section*)>
<!ELEMENT section     (title,subsect*)>
<!ELEMENT subsect     (title)>
<!ELEMENT title       (#PCDATA)>

リスト7.5 [ tinybook.xml ]

<?xml version="1.0"?>
<!DOCTYPE book SYSTEM "tinybook.dtd">
<book>
  <title>Hypertext Transfer Protocol -- HTTP/1.1</title>
  <chapter>
    <title>Introduction</title>
    <section><title>Purpose</title></section>
    <section><title>Requirements</title></section>
    <section><title>Terminology</title></section>
    <section><title>Overall Operation</title></section>
  </chapter></p>
<p>... 中略...</p>
<p>  <chapter>
    <title>Request</title>
    <section>
      <title>Request-Line</title>
      <subsect><title>Method</title></subsect>
      <subsect><title>Request-URI</title></subsect>
    </section>
    <section><title>The Resource Identified by a Request</title></section>
    <section><title>Request Header Fields</title></section>
  </chapter>
  <chapter>
    <title>Response</title>
    <section>
      <title>Status-Line</title>
      <subsect><title>Status Code and Reason Phrase</title></subsect>
    </section>
    <section><title>Response Header Fields</title></section>
  </chapter>
</book>

<!DOCTYPE style-sheet PUBLIC "-//James Clark//DTD DSSSL Style Sheet//EN"></p>
<p><style-sheet>
<style-specification>
<style-specification-body></p>
<p>(declare-characteristic page-number-format
 "UNREGISTERED::James Clark//Characteristic::page-number-format" "1")
(declare-characteristic page-number-restart?
 "UNREGISTERED::James Clark//Characteristic::page-number-restart?" #f)</p>
<p>(define (chapter-number snl)
  (number->string (child-number snl)))</p>
<p>(define (recursive-section-number snl)
  (string-append (chapter-number (parent snl)) "."
                 (number->string (child-number snl))))</p>
<p>(define (recursive-subsect-number snl)
  (string-append (recursive-section-number (parent snl)) "."
                 (number->string (child-number snl))))</p>
<p>(define (table-of-contents)
  (make simple-page-sequence
    page-width: 210mm
    page-height: 297mm
    top-margin: 30mm
    bottom-margin: 40mm
    left-margin: 30mm
    right-margin: 30mm
    footer-margin: 20mm
    center-footer: (page-number-sosofo)
    page-number-format: "i"
    page-number-restart?: #t
    (make paragraph
      font-size: 18pt
      line-spacing: 24pt
      space-after: 15mm
      (literal "Table Of Contents"))
    (make display-group
      (with-mode toc-mode
        (process-matching-children "chapter")))))</p>
<p>(element book
  (make sequence
    (process-matching-children "title")
    (table-of-contents)
    (process-matching-children "chapter")))</p>
<p>(element (book title)
  (make simple-page-sequence
    page-width: 210mm
    page-height: 297mm
    top-margin: 100mm
    bottom-margin: 40mm
    left-margin: 30mm
    right-margin: 30mm
    (make paragraph
      font-size: 24pt
      quadding: ’center
      (process-children))))</p>
<p>(element chapter
  (make simple-page-sequence
    page-width: 210mm
    page-height: 297mm
    top-margin: 30mm
    bottom-margin: 40mm
    left-margin: 30mm
    right-margin: 30mm
    footer-margin: 20mm
    page-number-format: "1"
    page-number-restart?: (first-sibling? (current-node))))</p>
<p>(element (chapter title)
  (make paragraph
    font-size: 18pt
    line-spacing: 24pt
    space-after: 10pt
    (literal (chapter-number (parent (current-node))) " ")
    (process-children)))</p>
<p>(element (section title)
  (make paragraph
    font-size: 14pt
    line-spacing: 18pt
    space-after: 10pt
    (literal (recursive-section-number (parent (current-node))) " ")
    (process-children)))</p>
<p>(element (subsect title)
  (make paragraph
    font-size: 12pt
    line-spacing: 16pt
    space-after: 10pt
    (literal (recursive-subsect-number (parent (current-node))) " ")
    (process-children)))</p>
<p>(mode toc-mode
  (element chapter
    (make display-group
      space-after: 10pt
      (make paragraph
        page-number-format: "1"
        keep-with-next?: #t
        font-weight: ’bold
        font-size: 10pt
        (literal (chapter-number (current-node)) " ")
        (process-matching-children "title")
        (make leader (literal " "))
        (current-node-page-number-sosofo))
      (process-matching-children "section")))
  (element section
    (make display-group
      (make paragraph
        page-number-format: "1"
        font-size: 10pt
        start-indent: 10pt
        (literal (recursive-section-number (current-node)) " ")
        (process-matching-children "title")
        (literal " ")
        (make leader (literal "."))
        (current-node-page-number-sosofo))
      (process-matching-children "subsect")))
  (element subsect
    (make paragraph
      page-number-format: "1"
      font-size: 10pt
      start-indent: 30pt
      (literal (recursive-subsect-number (current-node)) " ")
      (process-matching-children "title")
      (literal " ")
      (make leader (literal "."))
      (current-node-page-number-sosofo)))
  (element title
    (make sequence)))</p>
<p></style-specification-body>
</style-specification>
</style-sheet>

 リスト7.6について、未説明の部分もありますので順を追って説明していきましょう。  まず(declare-characteristic …) の部分ですが、ここではpage-number-formatおよび page-number-restart? という拡張機能(特質)の使用を宣言しています。pagenumber-format は、ページ番号に対してformat-number(p.171)と同様の効果を与える機能、page-number-restart?は論理定数 #t を指定するとページ番号のカウンタをリセットする機能です。これらはDSSSL 標準の機能ではありませんが、DSSSLprint/OpenJadeのいずれでも使用可能です。  この宣言から10 行程度下に、目次のための手続きの宣言があります。これは book タグから呼ばれる手続きです。ここでは本文と区別するためにページ番号のフォーマットを変更しています(引数はformat-number と同様です)。この make 式の末尾では、目次ページのタイトルに続けて実際の目次を表示するために toc-modechapter タグを処理した結果のsosofo を返すよう、手続き with-mode を呼び出しています。  この節で説明したように、この手続き with-mode が返すsosofo は63 行目の(element chapter (make simple-page-sequence …)) によって生成されるsosofoではなく、100 行目から始まるtoc-mode 内のelement コンストラクション・ルールが返すsosofo です。それでは、こちらから先に見てみることにしましょう。  toc-mode には chapter タグ, section タグ, subsect タグおよび title タグのコンストラクション・ルールがあります。title タグ以外の式はほとんど同じですので、ここでは chapter タグについて説明します。  make 式が二重構造になっており、内側のmake paragraph でタイトルを目次用にフォーマットしています。ここで、page-number-format を指定していることに注目してください。このオブジェクトのpage-number-format の値は、フロー・オブジェクト・ツリー上で親にあたる目次ページ(先程の手続きtable-of-contents によって作られるsimple-page-sequence フロー・オブジェクト)の値を継承するため、未指定の場合はローマ数字で表示されます[3](実際にpage-number-format をコメントで無効にしてみるとよくわかるでしょう)。  さて、よく見るとkeep-with-next?:という見なれない特質がありますが、これはフォーマットする際にツリー上の次のフロー・オブジェクトと一続きのものとして扱うかどうかを意味します。この例では、chapter の目次タイトルとsection の目次タイトルがページにまたがるような場合、両方が同じページに収まるように、つまりchapter フロー・オブジェクトが次のページに送られるようになります[4]。  leader フロー・オブジェクトや手続きcurrent-node-page-number-sosofo については先に説明した通りですので、ここではあらためて説明しません。  ぐっと戻って book タグのコンストラクション・ルールに目を移します。これまで文書の先頭要素があるところでは、page-sequence またはsimple-page-sequence を指定していましたが、この例のようにsequence を指定してひとつの文書内で複数種類のpage-sequence/simple-page-sequence を使用することができます。  その他についてはこれまでの応用ですので、あらためて説明するまでもないでしょう。参考までに、リスト7.5の目次ページのフォーマット結果サンプルを掲載しておきます。

図7.4 目次フォーマットサンプル

[3] Jade でフォーマットする場合、特質page-number-format の値は子のsosofo には継承されず、逆に子のsosofo で指定したpage-number-format の指定が親のsosofo に影響するので注意してください(本来は親の環境に影響すべきではないので、バグではないかと思います)。 同様の役割を果たす特質にkeep:などがあります。

<<prev