Headers and Footers

1. Varying headers across a document
2. Alternating headers and footers
3. Headers with different content
4. Left and right headers aligned to the 'outside'
5. 3 Column Header
6. 3 column headers in XSL-FO
7. Running Header not working (markers)
8. How to align text in a header
9. Align left, centre and right.
10. Retrieve marker
11. Adding a footer with page number

1.

Varying headers across a document

 > I would like to have one header on the first page, and a
 > distinctly different header on the 2nd and subsequent pages.
    

Try something like the appended. It defines 3 simplepage masters, for first, even, and odd, and then makes a composite one which calls on the others if the conditions are right. The key is

"fo:repeatable-page-master-alternatives" 

I am not sure whether FOP implements all this.


        <fo:simple-page-master master-name="firstpage"
                               page-height="297mm" page-width="210mm"
                               margin-top="20mm"  margin-bottom="10mm" 
                               margin-left="25mm" margin-right="20mm">
          <fo:region-body
                          margin-top="0mm" margin-bottom="15mm"
                          margin-left="0mm" margin-right="0mm"/>
          <fo:region-before
		region-name="xsl-region-before-firstpage" 
		extent="10mm"/>
          <fo:region-after 
		region-name="xsl-region-after-firstpage" 
		extent="10mm"/>
        </fo:simple-page-master>
        <!-- layout for the even page -->
        <fo:simple-page-master master-name="evenpage"
                               page-height="297mm" page-width="210mm"
                               margin-top="20mm"  margin-bottom="10mm" 
                               margin-left="25mm" margin-right="20mm">
          <fo:region-body
                          margin-top="0mm" margin-bottom="15mm"
                          margin-left="0mm" margin-right="0mm"/>
          <fo:region-before
		region-name="xsl-region-before-evenpage" 
		extent="10mm"/>
          <fo:region-after 
		region-name="xsl-region-after-evenpage" 
		extent="10mm"/>
        </fo:simple-page-master>
        <!-- layout for the odd page -->
        <fo:simple-page-master master-name="oddpage"
                               page-height="297mm" page-width="210mm"
                               margin-top="20mm"  margin-bottom="10mm" 
                               margin-left="25mm" margin-right="20mm">
          <fo:region-body
                          margin-top="0mm" margin-bottom="15mm"
                          margin-left="0mm" margin-right="0mm"/>
          <fo:region-before
		region-name="xsl-region-before-oddpage" 
		extent="10mm"/>
          <fo:region-after 
		region-name="xsl-region-after-oddpage" 
		extent="10mm"/>
        </fo:simple-page-master>
     <fo:page-sequence-master master-name="twoside">

      <fo:repeatable-page-master-alternatives>
        <fo:conditional-page-master-reference
		master-name="firstpage"
		page-position="first"/>
        <fo:conditional-page-master-reference
		master-name="oddpage"
		odd-or-even="odd"/>
        <fo:conditional-page-master-reference
		master-name="evenpage"
		odd-or-even="even"/>
      </fo:repeatable-page-master-alternatives>
     </fo:page-sequence-master>

2.

Alternating headers and footers

David Carlisle


> The problem is that the page-master fo doesn't allow to especify any content
> (as it must be). Then you only can specify diferent margins for even and odd
> pages and region extents. 
	

No, you can also specify different static contents for the different page masters, something like


<fo:layout-master-set>
<fo:page-sequence-master master-name="pages">
<fo:repeatable-page-master-alternatives>
<fo:conditional-page-master-reference odd-or-even="odd" master-name="right"/>
<fo:conditional-page-master-reference odd-or-even="even" master-name="left"/>
</fo:repeatable-page-master-alternatives>
</fo:page-sequence-master>

<fo:simple-page-master master-name="right" margin-top="16mm"
  margin-bottom="80mm" margin-left="39mm" margin-right="17mm">
<fo:region-body margin-top="0mm" margin-bottom="0mm"/>

<fo:region-after extent="5mm" region-name="xsl-region-after-right"/>

<fo:static-content flow-name="xsl-region-after-right">
<fo:block text-align="justify" font-size="10pt">
<fo:retrieve-marker retrieve-class-name="np-number"/>
<fo:leader rule-thickness="0pt"/>
<fo:page-number format="1"/>
</fo:block>
</fo:static-content>

...

so here in the specification for the "right" pages in the alternating sequence the footer is specified to use the flow named xsl-region-after-right which is defined to do something with some font setup and obtaining some text from a marker and from the page number.

3.

Headers with different content

Arved Sandstrom

Bear in mind that you can have as many fo:static-content's defined as you wish, with arbitrary flow-names. Map the static-content for the first page header to the region-before for the simple-page-master that applies to the first page; map the static-content for the header for all other pages to the region-before for the simple-page-master that applies to all but the first page.

Example:

<fo:layout-master-set>
<!-- layout for the first page -->
<fo:simple-page-master master-name="first"
    page-height="29.7cm"
    page-width="21cm"
    margin-top="1cm"
    margin-bottom="2cm"
    margin-left="2.5cm"
    margin-right="2.5cm">
    <fo:region-body margin-top="3cm"/>
    <fo:region-before region-name="header-first"
        extent="3cm"/>
    <fo:region-after extent="1.5cm"/>
</fo:simple-page-master>

    <!-- layout for the other pages -->
<fo:simple-page-master master-name="rest"
    page-height="29.7cm"
    page-width="21cm"
    margin-top="1cm"
    margin-bottom="2cm"
    margin-left="2.5cm"
    margin-right="2.5cm">
    <fo:region-body margin-top="3cm"/>
    <fo:region-before region-name="header-rest"
        extent="3cm"/>
    <fo:region-after extent="1.5cm"/>
</fo:simple-page-master>

<fo:page-sequence-master master-name="firstAndRest" >
 <fo:repeatable-page-master-alternatives>
  <fo:conditional-page-master-reference master-name="first"
   page-position="first" />
  <fo:conditional-page-master-reference master-name="rest"
   page-position="rest" />
  <!-- recommended fallback procedure -->
  <fo:conditional-page-master-reference master-name="rest" />
 </fo:repeatable-page-master-alternatives>
</fo:page-sequence-master>

  </fo:layout-master-set>
  <!-- end: defines page layout -->

  <!-- actual layout -->
  <fo:page-sequence master-name="firstAndRest">

<fo:static-content flow-name="header-first">
<fo:block>
Blah blah blah
</fo:block>
</fo:static-content>

<fo:static-content flow-name="header-rest">
<fo:block>
Blah blah blah
</fo:block>
</fo:static-content>

4.

Left and right headers aligned to the 'outside'

Jeni Tennison


> The aim is to have every rightPage with an even page number in the
> right-hand position of the page.
>
> While every leftPage should have an odd page number in the 
> left-hand position.
>
> I'm not sure that this is the way you *should* do it, but 
>  this works:

It looks like an easier option is to just have one fo:static-content formatting object for the xsl-region-before and use the text-align property on the block to align the text to the outside (left for left pages, right for right pages):

&lt;fo:static-content flow-name="xsl-region-before">
      &lt;fo:block text-align="outside">&lt;fo:page-number />
         &lt;/fo:block>
    &lt;/fo:static-content>
  

I guess that you only need to use the alternative fo:static-content formatting objects if the odd and even headers have very different content (e.g. the left gives the name of the chapter, the right the name of the subsection, as well as the page number).

5.

3 Column Header

Paul Grosso

I suggest you consider the list FOs in a broader light: see them as more general side-by-side FOs. While the result may not be elegant, true side-by-side FOs aren't going to be a whole lot simpler, since such layout is inherently complicated. Better yet, the list FOs exist and work today.

Specifically, consider the following code to generate left/center/right fields for a header. I've made the three fields of equal width that takes up the entire header width and where the fields butt up against each other, but it's easy to modify if you want to leave some space. (I'm making the simplifying assumption that, with the left/center/right justification of the three fields, there will always be some space anyway.) This code also allows for line wrapping when the field content is too wide to fit into the field on one line. In this example, I've just put some nonsense text into the left and right fields and the page number in the center field, but the field contents can be just about anything.

<fo:static-content flow-name="xsl-region-before">
    <!-- header-width is the width of the full header in picas -->
    <xsl:variable name="header-width" select="36"/>
    <xsl:variable name="header-field-width">
    <xsl:value-of 
 select="$header-width * 0.3333"/><xsl:text>pc</xsl:text>
    </xsl:variable>
    <fo:list-block font-size="8pt" provisional-label-separation="0pt">
        <xsl:attribute name="provisional-distance-between-starts">
            <xsl:value-of select="$header-field-width"/>
        </xsl:attribute>
        <fo:list-item>
            <fo:list-item-label end-indent="label-end()">
                <fo:block text-align="left">
                    <xsl:text>The left header field</xsl:text>
                </fo:block>
            </fo:list-item-label>
            <fo:list-item-body start-indent="body-start()">
                <fo:list-block provisional-label-separation="0pt">
                    <xsl:attribute 
                     name="provisional-distance-between-starts">
                        <xsl:value-of select="$header-field-width"/>
                    </xsl:attribute>
                    <fo:list-item>
                        <fo:list-item-label end-indent="label-end()">
                            <fo:block text-align="center">
                                <fo:page-number/>
                            </fo:block>
                        </fo:list-item-label>
                        <fo:list-item-body start-indent="body-start()">
                            <fo:block text-align="right">
                           <xsl:text>The right header field</xsl:text>
                            </fo:block>
                        </fo:list-item-body>
                    </fo:list-item>
                </fo:list-block>
            </fo:list-item-body>
        </fo:list-item>
    </fo:list-block>
</fo:static-content>
	

6.

3 column headers in XSL-FO

Paul Grosso

The use of "stretchy leaders" works well to push two blocks to the far left and right of a page. While one can also use a couple such leaders to get three fields, the center field will be off-center to the extent that the contents of the left and right fields have different lengths. Hence Ken's reasonable suggestion to use a three column, one row table.

However, I prefer to avoid using tables just to get various side-by-side layouts. We knew when we designed XSL 1.0 that we could not include special case FOs for all possible side-by-side situations.

Therefore, I suggest you consider the list FOs in a broader light: see them as more general side-by-side FOs. While the result may not be elegant, true side-by-side FOs aren't going to be a whole lot simpler, since such layout is inherently complicated. Better yet, the list FOs exist and work today.

Specifically, consider the following code to generate left/center/right fields for a header. I've made the three fields of equal width that takes up the entire header width and where the fields butt up against each other, but it's easy to modify if you want to leave some space. (I'm making the simplifying assumption that, with the left/center/right justification of the three fields, there will always be some space anyway.) This code also allows for line wrapping when the field content is too wide to fit into the field on one line. In this example, I've just put some nonsense text into the left and right fields and the page number in the center field, but the field contents can be just about anything.


<fo:static-content flow-name="xsl-region-before">
    <!-- header-width is the width of the full header in picas -->
    <xsl:variable name="header-width" select="36"/>
    <xsl:variable name="header-field-width">
    <xsl:value-of 
select="$header-width * 0.3333"/><xsl:text>pc</xsl:text>
    </xsl:variable>
    <fo:list-block font-size="8pt" provisional-label-separation="0pt">
        <xsl:attribute name="provisional-distance-between-starts">
            <xsl:value-of select="$header-field-width"/>
        </xsl:attribute>
        <fo:list-item>
            <fo:list-item-label end-indent="label-end()">
                <fo:block text-align="left">
                    <xsl:text>The left header field</xsl:text>
                </fo:block>
            </fo:list-item-label>
            <fo:list-item-body start-indent="body-start()">
                <fo:list-block provisional-label-separation="0pt">
                    <xsl:attribute 
                 name="provisional-distance-between-starts">
                        <xsl:value-of select="$header-field-width"/>
                    </xsl:attribute>
                    <fo:list-item>
                        <fo:list-item-label end-indent="label-end()">
                            <fo:block text-align="center">
                                <fo:page-number/>
                            </fo:block>
                        </fo:list-item-label>
                        <fo:list-item-body start-indent="body-start()">
                            <fo:block text-align="right">
                    <xsl:text>The right header field</xsl:text>
                            </fo:block>
                        </fo:list-item-body>
                    </fo:list-item>
                </fo:list-block>
            </fo:list-item-body>
        </fo:list-item>
    </fo:list-block>
</fo:static-content>

7.

Running Header not working (markers)

Ken Holman


>I have a "running header" contained in the "xsl-region-before".
>...
>              <fo:retrieve-marker retrieve-class-name="sect-head"
>  retrieve-position="first-starting-within-page"
>                                  retrieve-boundary="page" />
>...
>this works fine, and I have a new section title appearing in the page
>header
>whenever section changes. But if the section contains more than 1 page,
>the section
>title will not be repeated on the consecutive pages.

Because of the retrieve-boundary ... use a value of "page-sequence" or "document" instead of page. The default of "page-sequence" would have given you what you needed had you not changed it explicitly to only look for markers found on the page itself.

8.

How to align text in a header

Eliot Kimber



> I'm trying to align the text in the page header. There
> are two pieces of text that need to go to the header:
> chapter name and page number. I do this using markers.
> I want to put both of these pieces of text on the same
> line in the page header. I want to align the chapter
> name to the left and the page number to the right. How
> can I do this?

The trick is to use the text-align-last="justify" value on the block, with an auto-length leader between them. You can also use a table, which is more appropriate if you have multi-line items that need to be pushed to the edges of the header or footer.

<fo:block
     text-align-last="justify">
   <fo:retrieve-marker class="title"/>
   <fo:leader leader-pattern="space"/>
   <fo:page-number/>
</fo:block>

9.

Align left, centre and right.

David Tolpin

> I want to align text left, center and right in one line.
> Something like:
> myname                  nameofmywork               page

> How would I do that, without using a table?

With leaders.

<fo:block
text-align-last="justify"
>myname<fo:leader/>page<fo:leader/>nameofmywork</fo:block>

note however that that puts equal space either side of "nameofmywork" but doesn't centre it unless "myname" and "page" have the same length, you might need to force the widths of the two outer blocks.. or use tables as suggested originally

10.

Retrieve marker

Chris Bowditch


> I think my real challenge is knowing which instance of
> the element to use in the running header.  This element may occur
> several times on a physically rendered page, however it is only
> the content corresponding to the last occurence of this element
> on a physical page that I need to put in the running header of
> the next page.  I don't have a good way to determine which
> occurance of this element is that last one on a rendered
> page, so I don't know which one to set a marker on.  If I set
> a different marker on all occurrences of this element, then I
> still don't know which marker to select for my running header.

This is straight forward to achieve using markers. Simply place all occurences of the element into a fo:marker with the same class name. Then the retrieve marker in static content of the next page should look like:

<fo:retrieve-marker retrieve-class-name="amarker" 
retrieve-boundary="page-sequence" 
retrieve-position="last-starting-within-page"/>

The last element on the previous page will be selected. We use this technique for running page totals without problem.

11.

Adding a footer with page number

Jay Bryant



Here's a simplified version of one of my page definitions:

<fo:simple-page-master master-name="main" 
xsl:use-attribute-sets="pagedef">
  <fo:region-body region-name="main" margin-top="1in" 
margin-bottom="1in"/>
  <fo:region-before region-name="header-main" extent="1in"/>
  <fo:region-after region-name="footer-main" extent="1in"/> </fo:simple-page-master>

Note that the regions have names.

And here's the corresponding flow definition (much simplified, of course):

<fo:page-sequence master-reference="main">
  <fo:static-content flow-name="header-main">
    <fo:block xsl:use-attribute-sets="header">
      <fo:external-graphic src="logo.gif"/>
    </fo:block>
  </fo:static-content>
  <fo:static-content flow-name="footer-main">
    <fo:block xsl:use-attribute-sets="footer">
      <fo:page-number/>
    </fo:block>
  </fo:static-content>
  <fo:flow flow-name="main">
    <!-- Build the document here -->
  </fo:flow>
</fo:page-sequence>

The static-content chunks flow into the before and after regions, and the main flow goes in the usual flow area. In this fashion, you can build a series of different page definitions. I generally use front (for the title page and copyright notices and such), contents (for the table of contents), main (for the body of the book), and back (for the appendixes, glossary, and index). So most of my book definition FO files have 4 page masters and 4 corresponding page-sequence objects, each with static-content ojbects (that match the regions defined in the page masters) for the headers and footers.