Watch our 3-minute video to find out how you can learn XSL-FO with a live instructor.
Additional Resources

Leaders, Markers and Page Numbers

In this lesson of the XML tutorial, you will learn...
  1. To create a well-designed table of contents.
  2. To work with leaders.
  3. To work with markers.
  4. To output and reference page numbers and specify page number formats.

The Output

We will be creating a PDF that contains children's stories. The result document is LeadersMarkers/Demos/Stories.pdf. Please take a moment to look it over. You should notice the following:

  1. The document has a nicely-formatted table of contents (shown below). This table of contents is made up of the headings from the source XHTML document: LeadersMarkers/Demos/Stories.html. The page numbers are dynamically determined.
  2. The page numbering in the footer of the table of contents (not shown above) is in Roman numerals.
  3. After the table of contents, the page numbers start over again from 1 and use Arabic numbers.
  4. Each story begins on an odd page.
  5. The titles of the stories are shown in the headers.

Table of Contents

Assume you have an XML document that contains a complete book that is divided into chapters. The table of contents will be created by taking a pass through the entire XML document, grabbing all the chapter titles and outputting those titles with page references. Generally, the title and page reference will be separated by some type of leader. The XSLT document below shows how the table of contents (shown above) was created.

Code Sample: LeadersMarkers/Demos/Stories.xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
 xmlns:fo="http://www.w3.org/1999/XSL/Format">
 <xsl:output method="xml" indent="yes"/>
 
 <xsl:template match="/">
  <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
   <fo:layout-master-set>
   
    <fo:simple-page-master master-name="TOC" 
     page-height="11in" page-width="8.5in" margin=".5in">
     <fo:region-body margin=".5in"/>
     <fo:region-before region-name="TocHead" extent=".5in"/>
     <fo:region-after region-name="TocFoot" extent=".5in"/>
    </fo:simple-page-master>
---- Code Omitted ----
</fo:layout-master-set> <fo:page-sequence master-reference="TOC" format="i"> <fo:static-content flow-name="TocHead"> <fo:block border-bottom-width="thin" border-bottom-style="solid" border-bottom-color="green" font-weight="bold" text-align="outside"> <xsl:text>Table of Contents</xsl:text> </fo:block> </fo:static-content> <fo:static-content flow-name="TocFoot"> <fo:block border-bottom-width="thin" border-bottom-style="solid" border-bottom-color="green" font-weight="bold" text-align="outside"> <fo:page-number/> </fo:block> </fo:static-content> <fo:flow flow-name="xsl-region-body"> <fo:block text-align="center" font-weight="bold" font-size="larger"> <xsl:text>Table of Contents</xsl:text> </fo:block> <xsl:apply-templates mode="TOC"/> </fo:flow> </fo:page-sequence> <fo:page-sequence master-reference="Stories" initial-page-number="1"> <fo:static-content flow-name="oddHead"> <fo:block border-bottom-width="thin" border-bottom-style="solid" border-bottom-color="green" font-weight="bold" text-align="outside"> <fo:retrieve-marker retrieve-class-name="StoryTitle" retrieve-position="first-including-carryover"/> </fo:block> </fo:static-content> <fo:static-content flow-name="evenHead"> <fo:block border-bottom-width="thin" border-bottom-style="solid" border-bottom-color="green" font-weight="bold" text-align="outside"> <fo:retrieve-marker retrieve-class-name="StoryTitle" retrieve-position="first-including-carryover"/> </fo:block> </fo:static-content>
---- Code Omitted ----
</fo:page-sequence> </fo:root> </xsl:template> <xsl:template match="body/div/h2" mode="TOC"> <fo:block font-size="smaller" space-after=".1in" space-before=".15in" text-align-last="justify"> <fo:basic-link internal-destination="{generate-id(.)}"> <xsl:value-of select="."/> <fo:leader leader-pattern="dots"/> <fo:page-number-citation ref-id="{generate-id(.)}"/> </fo:basic-link> </fo:block> </xsl:template> <xsl:template match="body/div/h2" mode="Stories"> <fo:block font-weight="bold" font-size="larger" id="{generate-id(.)}" break-before="odd-page"> <fo:marker marker-class-name="StoryTitle"> <xsl:value-of select="."/> </fo:marker> <xsl:value-of select="."/> </fo:block> </xsl:template>
---- Code Omitted ----
</xsl:stylesheet>

Page Numbering

In the example above, there is a simple-page-master for the table of contents. There's nothing special about this page master. The page-sequence that references it is also pretty standard, with one exception. It has a format attribute, which specifies how page numbers should be formatted. In this case, it takes the value of "i", meaning lowercase Roman numerals will be used. Other options are "I", "A", "a", and "1" (the default).

In the following page-sequence FO, which contains the actual stories, we set the initial-page-number attribute to "1" to force the page count to start over. This page-sequence will use Arabic notation (the default) for page numbers, because the format attribute is left off.

page-number-citation

The page number itself is output with the page-number-citation FO, which uses generate-id() to reference the location at which that node appears in the document.

<fo:page-number-citation ref-id="{generate-id(.)}"/>

Leaders

Leaders are used to separate the story titles from the page numbers. They are created with the <fo:leader> tag as shown below.

<xsl:template match="body/div/h2" mode="TOC">
 <fo:block font-size="smaller" space-after=".1in" 
  space-before=".15in" text-align-last="justify">
  <fo:basic-link internal-destination="{generate-id(.)}">
   <xsl:value-of select="."/>
   <fo:leader leader-pattern="dots"/>
   <fo:page-number-citation ref-id="{generate-id(.)}"/>
  </fo:basic-link>
 </fo:block>
</xsl:template>

To force the page number to be aligned all the way to the right, we set the text-align-last attribute of the block to "justify". For the leader-pattern, we use "dots", which is common for a table of contents. Other options are "rule", "space", and "use-content", which are all shown in the following example.

Code Sample: LeadersMarkers/Demos/Leaders.fo

<?xml version="1.0" encoding="UTF-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
 <fo:layout-master-set>
  <fo:simple-page-master master-name="Leaders" page-height="11in" page-width="8.5in" margin="1in">
   <fo:region-body/>
  </fo:simple-page-master>
 </fo:layout-master-set>
 <fo:page-sequence master-reference="Leaders">
  <fo:flow flow-name="xsl-region-body">
  
   <fo:block font-weight="bold" space-before=".5cm" space-after=".5cm">leader-pattern</fo:block>
   <fo:block space-after=".1in" text-align-last="justify">
    A<fo:leader leader-pattern="dots"/>Z
   </fo:block>
   <fo:block space-after=".1in" text-align-last="justify">
    A<fo:leader leader-pattern="rule"/>Z
   </fo:block>
   <fo:block space-after=".1in" text-align-last="justify">
    A<fo:leader leader-pattern="space"/>Z
   </fo:block>
   <fo:block space-after=".1in" text-align-last="justify">
    A<fo:leader leader-pattern="use-content">*</fo:leader>Z
   </fo:block>
   
   <fo:block font-weight="bold" space-before=".5cm" space-after=".5cm">leader-pattern-width</fo:block>
   <fo:block space-after=".1in" text-align-last="justify">
    A<fo:leader leader-pattern="dots" leader-pattern-width="1cm"/>Z
   </fo:block>
   <fo:block space-after=".1in" text-align-last="justify">
    A<fo:leader leader-pattern="rule" leader-pattern-width="1cm"/>Z
   </fo:block>
   <fo:block space-after=".1in" text-align-last="justify">
    A<fo:leader leader-pattern="use-content" leader-pattern-width="1cm">*</fo:leader>Z
   </fo:block>
   
   <fo:block font-weight="bold" space-before=".5cm" space-after=".5cm">leader-length</fo:block>
   <fo:block space-after=".1in" text-align="center">
    A<fo:leader leader-pattern="dots" leader-length="50%"/>Z
   </fo:block>
   <fo:block space-after=".1in" text-align="center">
    A<fo:leader leader-pattern="rule" leader-length="3in"/>Z
   </fo:block>
   <fo:block space-after=".1in" text-align="center">
    A<fo:leader leader-pattern="space" leader-length="50%"/>Z
   </fo:block>
   <fo:block space-after=".1in" text-align="center">
    A<fo:leader leader-pattern="use-content" leader-length="3in">*</fo:leader>Z
   </fo:block>
   
  </fo:flow>
 </fo:page-sequence>
</fo:root>
Code Explanation

The output is shown below followed by a table showing common leader attributes.

<fo:leader> Attributes
Attribute Description
leader-pattern
  • dots
  • rule
  • space
  • use-content
leader-length the width of the leader
leader-pattern-width the distance between each glyph in the leader
leader-alignment
  • none
  • reference-area
  • page

Markers

Markers are used to add information about the current page to static regions. The two FOs used to create and reference markers are marker and retrieve-marker. Markers are grouped by class name with the marker-class-name attribute of the marker FO. This is the only attribute marker takes.

<xsl:template match="body/div/h2" mode="Stories">
 <fo:block font-weight="bold" font-size="larger" 
  id="{generate-id(.)}" break-before="odd-page">
  <fo:marker marker-class-name="StoryTitle">
   <xsl:value-of select="."/>
  </fo:marker>
  <xsl:value-of select="."/>
 </fo:block>
</xsl:template>

The contents of a marker do not show up in the location of the marker itself. They only appear if the marker is referenced with a retrieve-marker FO.

<fo:static-content flow-name="evenHead">
 <fo:block border-bottom-width="thin" border-bottom-style="solid" 
  border-bottom-color="green" font-weight="bold" text-align="outside">
  <fo:retrieve-marker retrieve-class-name="StoryTitle"
   retrieve-position="first-including-carryover"/>
 </fo:block>
</fo:static-content>

As shown above, retrieve-marker uses the retrieve-class-name attribute to specify which marker class to reference. It uses the retrieve-position attribute to help identify which marker in that class to use. The retrieve-position attribute takes the following values:

  • first-starting-within-page - references the first marker on the current page.
  • first-including-carryover - references the first marker on the current page. If there are no markers on the current page, it references the last marker before the current page.
  • last-starting-within-page - references the last marker on the current page.
  • last-ending-within-page - references the last marker on the current page that is contained in a FO whose full content is also on the current page.

The retrieve-marker FO takes one additional attribute: retrieve-boundary, which is used to specify the domain in which to search for markers. By default, it is limited to the page-sequence, which is almost always what you want; however, you can change it so that it searches the whole document or just the current page.

Exercise: Using Leaders and Markers

Duration: 15 to 20 minutes.

In this exercise, you will practice creating a nicely formatted table of contents for the song lyrics document we have been working on. You will also use markers so that each page in the document has the appropriate song title in the header. The output is shown in LeadersMarkers/Exercises/Lyrics.pdf.

  1. Open LeadersMarkers/Exercises/Lyrics.xsl for editing.
  2. Add code to transform Lyrics.xml to create a FO that will render a PDF like LeadersMarkers/Exercises/Lyrics.pdf.
    • The table of contents should be nicely formatted.
    • Each page in the main document (e.g, after the table of contents), should show the name of the current story in the header.
  3. To test your solution, transform LeadersMarkers/Exercises/Lyrics.xml against LeadersMarkers/Exercises/Lyrics.xsl.

Leaders, Markers and Page Numbers Conclusion

In this lesson of the XML tutorial, you have learned to work with leaders to create nicely formatted tables of contents and with markers to add information about the current page to static regions.

To continue to learn XML go to the top of this page and click on the next lesson in this XML Tutorial's Table of Contents.

Use of http://www.learn-xsl-fo-tutorial.com (Website) implies agreement to the following:

Copyright Information

All pages and graphics on Website are the property of Webucator, Inc. unless otherwise specified.

None of the content on Website may be redistributed or reproduced in any way, shape, or form without written permission from Webucator, Inc.

No Printing or saving of pages or content on Website

This content may not be printed or saved. It is for online use only.


Linking to Website

You may link to any of the pages on Website; however, you may not include the content in a frame or iframe without written permission from Webucator, Inc.


Warranties

Website is provided without warranty of any kind. There are no guarantees that use of the site will not be subject to interruptions. All direct or indirect risk related to use of the site is borne entirely by the user. All code and explanations provided on this site are provided without warranties to correctness, performance, fitness, merchantability, and/or any other warranty (whether expressed or implied).


For individual private use only

You agree not to use this online manual to deliver or receive training. If you are delivering or attending a class that is making use of this online manual, you are in violation of our terms of service. Please report any abuse to courseware@webucator.com. If you would like to deliver or receive training using this manual, please fill out the form at http://www.webucator.com/Contact.cfm