Page- and Column-level Architecture for XSL
Henry S. Thompson
HCRC Language Technology Group
University of Edinburgh

19 November 1998

1. The issue

The current draft is circumspect (:-) about the mechanism(s) by which page and column layout will interact with formatting objects. This note attempts to illustrate some aspects of a possible resolution of this by setting out to reconstruct the functionality of a moderately complex example derived from a DSSSL example originally produced by James Clark for a tutorial given at SGML '95 by himself, Sharon Adler and Anders Berglund (the original is still available).

What I hope to demonstrate is that with the addition of a means of generating unique IDs, we already have everything we need.

2. The example

There are two aspects of the original example which are relevant to our concerns. One is that it uses a number of different page masters (called page models in DSSSL), the other is that it uses column sets, zones and flow maps. We'll consider these one at a time.

2.1. Page master sequencing

The example uses three separate page sequences, sharing masters across them. One sequence is used for the title page of the whole document, one for the table of contents pages, and one for each chapter. An illustration should help.

Basically we have a single page master, PM1, used for the title page, all the pages of the table of contents, and the first page of each chapter. It also gets used as the page master for the page which is interpolated as a result of the TOC page sequence demanding to start on a verso page. There are two further page masters, PMR and PMV, which are used for the recto and verso non-first pages of chapters.

2.2. Column-set zones and flow maps

DSSSL provides powerful controls for column layout, which I won't go in to in detail here. The relevant point is that it also identifies four zones on each page of columns, as illustrated below (illustration lifted from the DSSSL spec.)

<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl='http://www.w3.org/TR/WD-xsl' xmlns:fo='http://www.w3.org/TR/WD-xsl/FO' result-ns='fo' indent-result='yes'>

<xsl:template match='/'>
 <fo:root>

  <!-- First a trivial sequence for the title page -->
  <fo:page-sequence font-family='serif'>
   <fo:simple-page-master master-name='first'/>
   <fo:queue queue-name='body'>
    <xsl:apply-templates match='/doc/title'>
     <!-- Template for main title here -->
    </xsl:apply-templates>
   </fo:queue>
  </fo:page-sequence>

  <!-- Then simple pages for the table of contents -->
  <!-- This should have a running footer for page numbers . . . -->
  <fo:page-sequence font-family='serif'>
   <fo:simple-page-master master-name='first'/>
   <fo:queue queue-name='body'>
    <fo:block>Table of Contents</fo:block>
    <xsl:apply-templates match='//chap/title|//section/title'>
     <!-- Templates for toc entries for chapter titles and section
          titles go here -->
    </xsl:apply-templates>
   </fo:queue>
  </fo:page-sequence>

  <!-- Now one complex sequence for each chapter -->
  <xsl:for-each match='/doc/chap'>
   <fo:page-sequence>
    <fo:simple-page-master master-name='first'/>
    <fo:simple-page-master master-name='even'/>
    <fo:simple-page-master master-name='odd'/>

    <!-- First queue is for mainline content, goes in body-text zone -->
    <!-- I've added a zones attribute in anticipation of column
         set models -->
    <fo:queue queue-name='body' zones='body-text'>
     <xsl:apply-templates/>
    </fo:queue>

    <!-- Second queue is for figures -->
    <fo:queue queue-name='body' zones='top-float bottom-float'>
     <xsl:apply-templates match='//figure'>
      <xsl:template match='figure'>
       <fo:block>
        <xsl:attribute name='syncid'>
         <xsl:uid match='.'/>
        </xsl:attribute>
        <!-- stuff here to actually lay out the figure and caption -->
       </fo:block>
      </xsl:template>
     </xsl:apply-templates>
    </fo:queue>
    
    <!-- Third queue is for footnotes -->
    <fo:queue queue-name='body' zones='footnote'>
     <xsl:apply-templates match='//footnote'>
      <xsl:template match='footnote'>
       <fo:block>
        <xsl:attribute name='syncid'>
         <xsl:uid match='.'/>
        </xsl:attribute>
        <!-- stuff here to actually lay out the footnote number
             and content -->
       </fo:block>
      </xsl:template>
     </xsl:apply-templates>
    </fo:queue>
    
    <!-- And a queue for a running footer:  note that per the current
         spec this is recycled for every page -->
    <fo:queue queue-name='footer'>
     <fo:block text-align='center'>
      <!-- Page number here, how depends on what we do about
           layout-dependent text -->
     </fo:block>
    </fo:queue>

    <!-- And finally a queue for the running header -->
    <fo:queue queue-name='header'>
     <!-- Note that this won't work, nor is there any way as
          things stand to make it work.  What I want of course is
          no header on the first page of a chapter, then alternating
          chapter and section titles . . . What I'm going to get is a
          three-step sequence of empty, chapter and section, out of
          step once we get to the fourth page of the chapter.
          The DSSSL approach, with header and footer generators
          specified WITHIN the page masters, should be revived,
          I think. -->
     <fo:sequence>
      <xsl:text/>
      <fo:block text-align='start'>
       <!-- Chapter title text here . . .-->
      </fo:block>
      <fo:block text-align='end'>
       <!-- Section title text here . . .-->
      </fo:block>
     </fo:sequence>
    </fo:queue>
   </fo:page-sequence>
  </xsl:for-each>
 </fo:root>
</xsl:template>

<!-- The plan for synchronisation depends on xsl:uid producing
     the SAME uid for a node in the source tree whenever it is
     invoked, with 'syncid' being of type id and 'syncwith' being
     of type idref (see above to see where 'syncid' is set) -->

<xsl:template match='figure'>
 <fo:synchronise max='1'>
  <xsl:attribute name='syncwith'>
   <xsl:uid match='.'/>
  </xsl:attribute>
 </fo:synchronise>
</xsl:template>

<xsl:template>
 <fo:sequence>
  <xsl:attribute name='syncwith'>
   <xsl:uid match='.'/>
  </xsl:attribute>
 </fo:sequence>
</xsl:template>
<!-- Note that if we needed more control over synchronisation,
     we could wrap the above fo:sequence in an fo:synchronise.
     We could require this in all cases, as an alternative to
     allowing a 'syncwith' id on any fo:..., as is implied above. -->
<!-- Templates for all the simple body content go here -->

</xsl:stylesheet>