set1

advertisement
XSL Formatting Objects
XSL-FO
Why XSL-FO? Some History
• The history of HTML shows that, in the
early days, both its designers and its users
were confused about its purpose
• Initially, it was intended for specifying the
structure of documents for the web
– Its tags included <h1> <p> <ol> <ul> <li>
(See http://www.w3.org/History/19921103hypertext/hypertext/WWW/MarkUp/Tags.html)
• These documents were then displayed
using whatever rendering choices were
made by the displaying program
Why XSL-FO? Some History (contd.)
• In the early days, there was some
confusion
• People did not make the distinction
between structure and style
– Even Tim Berners-Lee made the mistake of
writing “Most of the tags are just style tags:
this goes for the headings H1 to H6, the lists
UL and OL with list elements LI, the glossary
DL with elements DT and DD. ”
(See http://lists.w3.org/Archives/Public/www-talk/1991SepOct/0003.html)
Why XSL-FO? Some History (contd.)
• This confusion caused the mistaken introduction of
rendering tags (and rendering attributes) into the
language
– For example: <b> <i> <tt> <font>
• Elimination of this confusion led to the introduction of
Cascading Style Sheets and the deprecation of
rendering tags and attributes
• It is now recognized that there should be a sharp
distinction between the specification of structure and of
rendering
• This distinction was already recognized by the time that
XML was developed
Why XSL-FO? Some History (contd.)
• The structure/rendering distinction is reflected in
the separation between XML and XSL
• XML is used for specifying document structure
• XSL is used for specifying document rendering
• The W3 specification for XSL can be found here
http://www.w3.org/TR/xsl/
Why XSL-FO? Some History (contd.)
• XSLT is able to do only part of the job of rendering XML
documents
• XSLT is for specifying how to analyse the
structure of an XML document in order to
compute the appropriate rendering of the
document
• But XSLT must be complemented by a second
notation in which we can specify the desired
rendering
• We have seen that HTML is sometimes used as
the second notation
• However, XSL Formatting Objects (XSL-FO) is the more
general notation for specifying the desired rendering
Why XSL-FO? Some History (contd.)
• It is common for XSLT to map XML documents
into HTML documents
• This is because HTML has a rendering
semantics
• However, HTML allows us to render XML
documents only as web pages
– using browsers as the rendering engines
• Frequently, we need to render XML as other
kinds of documents, including
– PDF files,
– Image files
• We need another notation which can be used to
specify the rendering of PDF files and images
Why XSL-FO? Some History (contd.)
• XSL has two parts
– XSLT can be used to analyse the structure of an XML
document, in order to generate a document in some
other notation
– XSL-FO is one such other notation
• XSL-FO is designed specifically for the purpose
of describing the layout of documents
– In this sense, its purpose is a little like that of CSS,
– However, XSL-FO is quite different from CSS
• A layout description given in XSL-FO can be
used to generate a growing variety of
documents, including
– PDF files,
– Image files
XSL-FO is an XML application-specific language
• Every XSL-FO specification must be well-formed XML
• For technical reasons, it is not possible to have a
comprehensive DTD for XSL-FO
– However, an unofficial DTD is here
http://www.cs.ucc.ie/j.bowen/usefulResources/fo2000.dtd.html
• Warning: this unofficial DTD was written by somebody
from a company which produces a commercial FO
processor program called XEP
• The unofficial DTD contains some commercial extensions
which are associated with the namespace
http://www.renderx.com/XSL/Extensions
• These extensions are identified in the DTD by use of the
prefix rx:
XSL-FO is an XML application-specific language
• The namespace for XSL-FO is
http://www.w3.org/1999/XSL/Format
• The prefix used is fo
• The root element in XSL-FO has the tag name root
• The declaration for this element in the unofficial DTD is
<!ELEMENT fo:root (fo:layout-master-set,
fo:declarations?,fo:page-sequence+)>
<!ATTLIST fo:root xmlns:fo CDATA #REQUIRED>
• Thus, the root element is of the form
<fo:root
xmlns:fo="http://www.w3.org/1999/XSL/Format">
…
</fo:root>
How do we use XSL-FO?
First, let's revisit how we used
XSLT to view XML files in
browsers
A reminder: viewing XML in a web browser
• The browser requests an
XML document
• The XML document
refers to an XSLT
stylesheet
– The browser then requests
the stylesheet
• The browser's XSLT
Engine generates HTML
from XML+XSLT
• The browser's HTML
engine renders the HTML
in the browser window
Using a browser's XSLT engine to generate HTML from XML ...
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html><head><title>Greetings</title></head>
<body><xsl:apply-templates select="./names/name"/></body></html>
</xsl:template>
<xsl:template match="name">
<p>Hello, <xsl:value-of select="."/>!</p>
</xsl:template>
</xsl:stylesheet>
... Then rendering the HTML with the browser's HTML engine
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html><head><title>Greetings</title></head>
<body><xsl:apply-templates select="./names/name"/></body></html>
</xsl:template>
<xsl:template match="name">
<p>Hello, <xsl:value-of select="."/>!</p>
</xsl:template>
</xsl:stylesheet>
What happens if we try the
same thing with XSL-FO as we
just did with HTML?
Generating XSL-FO from XML
<?xml version="1.0"?>
<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><fo:layout-master-set><fo:simple-page-master master-name="A4-portrait"
page-height="29.7cm" page-width="21.0cm" margin="2cm"><fo:regionbody/></fo:simple-page-master></fo:layout-master-set><fo:page-sequence masterreference="A4-portrait"><fo:flow flow-name="xsl-region-body"><xsl:apply-templates
select="./names/name"/></fo:flow></fo:page-sequence></fo:root>
</xsl:template>
<xsl:template match="name"><fo:block>Hello, <xsl:value-of select="."/>!</fo:block>
</xsl:template>
</xsl:stylesheet>
How is the resultant XSL-FO rendered in the browser?
<?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 margin="2cm" page-width="21.0cm" pageheight="29.7cm" master-name="A4-portrait"><fo:region-body/></fo:simple-pagemaster></fo:layout-master-set><fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block> Hello, Tom! </fo:block>
<fo:block> Hello, Dick! </fo:block>
<fo:block> Hello, Harry! </fo:block>
</fo:flow></fo:page-sequence></fo:root>
How is the resultant XSL-FO rendered in the browser?
• The browser cannot render XSL-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 margin="2cm" page-width="21.0cm" pageheight="29.7cm" master-name="A4-portrait"><fo:region-body/></fo:simple-pagemaster></fo:layout-master-set><fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block> Hello, Tom! </fo:block>
<fo:block> Hello, Dick! </fo:block>
<fo:block> Hello, Harry! </fo:block>
</fo:flow></fo:page-sequence></fo:root>
How is the resultant XSL-FO rendered in the browser?
• The browser cannot render XSL-FO
• The fo: tags are simply ignored
<?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 margin="2cm" page-width="21.0cm" pageheight="29.7cm" master-name="A4-portrait"><fo:region-body/></fo:simple-pagemaster></fo:layout-master-set><fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block> Hello, Tom! </fo:block>
<fo:block> Hello, Dick! </fo:block>
<fo:block> Hello, Harry! </fo:block>
</fo:flow></fo:page-sequence></fo:root>
How is the resultant XSL-FO rendered in the browser?
• The browser cannot render XSL-FO
• The fo: tags are simply ignored
• We just see the included text
<?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 margin="2cm" page-width="21.0cm" pageheight="29.7cm" master-name="A4-portrait"><fo:region-body/></fo:simple-pagemaster></fo:layout-master-set><fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block> Hello, Tom! </fo:block>
<fo:block> Hello, Dick! </fo:block>
<fo:block> Hello, Harry! </fo:block>
</fo:flow></fo:page-sequence></fo:root>
What went wrong?
• The problem is that
web browsers do not
have engines for
rendering XSL-FO
• Instead, web
browsers have
engines for rendering
HTML
So how do we render XSL-FO?
So how do we render XSL-FO?
• We need a different kind
of program
• We need a program
which contains an FO
engine
• These programs are
called FO processors
• Usually they also contain
an XSLT engine
• They can generate
various kinds of output,
including PDF and image
files
Generating XSL-FO from XML and then rendering the XSL-FO
• Apache FOP is a commonly-used FO processor
• fop contains both an XSLT engine and an FO engine
• Example usage on the cs1 server:
cs1> fop -xml names2.xml -xsl names2.xsl -pdf names2.pdf
• This example command tells fop to apply an XSL
stylesheet to an XML document and output a PDF file
• The XML file need/should not contain an xmlstylesheet instruction
Starting to write XSL-FO
First stage of an XSLT stylesheet for generating XSL-FO from XML
<?xml version="1.0"?>
<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:root>
</xsl:template>
</xsl:stylesheet>
Contents of the fo:root element
• Element declaration:
<!ELEMENT fo:root (
fo:layout-master-set,
fo:declarations?,
fo:page-sequence+ )>
• Thus, the minimum contents of an fo:root element are:
• fo:layout-master-set a description of the page layouts
that are used in the document being specified
• fo:page-sequence+ a set of specifications for one or
more sequences of actual pages in the document
Minimum fo:root element
• Example XSL-FO document
<?xml version="1.0"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
…
</fo:layout-master-set>
<fo:page-sequence … >
…
</fo:page-sequence>
</fo:root>
The layout-master-set
• Declaration in the unofficial DTD is
<!ELEMENT fo:layout-master-set
( fo:page-sequence-master*, fo:simple-page-master,
( fo:simple-page-master | fo:page-sequence-master )* ) >
• Thus, the layout-master-set must contain at least one
element of type fo:simple-page-master
• Example XSL-FO document
<?xml version="1.0"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name=“…">
…
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence … >
…
</fo:page-sequence>
</fo:root>
Page sequences refer to page masters
• Each page sequence must refer to a page master
<?xml version="1.0"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="someName">
…
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="someName">
…
</fo:page-sequence>
</fo:root>
How pages are modelled in XSL-FO
• In the XSL-FO page
model, a page in the
document being specified
contains several areas
• The part of the page
where the content will be
placed is called the pagereference-area
• There are four margins
around the pagereference-area
• These margins can be
zero
How pages are modelled in XSL-FO (contd.)
• The page-reference-area can
be divided into five regions
• Only the region-body is
required
• Most content will be placed in
the region-body
• The other regions may or may
not be present
• If the other regions are not
present, the regions-body will
be the same size as the pagereference-area
How pages are modelled in XSL-FO (contd.)
• Unofficial DTD declaration for fo:simple-page-master is
<!ELEMENT fo:simple-page-master
(fo:region-body,fo:region-before?,
fo:region-after?,fo:region-start?,fo:region-end?)>
How pages are modelled in XSL-FO (contd.)
• Unofficial DTD declaration for fo:simple-page-master is
<!ELEMENT fo:simple-page-master
(fo:region-body,fo:region-before?,
fo:region-after?,fo:region-start?,fo:region-end?)>
<!ATTLIST fo:simple-page-master
%margin-properties-CSS;
master-name CDATA #REQUIRED
page-height CDATA #IMPLIED
page-width CDATA #IMPLIED
media-usage CDATA #IMPLIED
size CDATA #IMPLIED
reference-orientation
( 0 | 90 | 180 | 270 | -90 | -180 | -270 | 0deg | 90deg | 180deg | 270deg | -90deg| - 180deg | -270deg | inherit ) #IMPLIED
writing-mode ( lr-tb | rl-tb | tb-rl | lr | rl | tb | inherit ) #IMPLIED >
How pages are modelled in XSL-FO (contd.)
• The definition, in the unofficial DTD, of the CSS-type
margin properties is
How pages are modelled in XSL-FO (contd.)
• The definition, in the unofficial DTD, of the CSS-type
margin properties is
<!ENTITY % margin-properties-CSS "
margin CDATA #IMPLIED
margin-bottom CDATA #IMPLIED
margin-left CDATA #IMPLIED
margin-right CDATA #IMPLIED
margin-top CDATA #IMPLIED
margin-after CDATA #IMPLIED
margin-start CDATA #IMPLIED
margin-end CDATA #IMPLIED
margin-before CDATA #IMPLIED ">
Example XSL-FO document
<?xml version="1.0"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master
master-name="myPageType"
page-height="29.7cm"
page-width="21.0cm"
margin="2cm">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="myPageType">
......
</fo:page-sequence>
</fo:root>
The region-body element
• Declaration in the unofficial DTD is
<!ELEMENT fo:region-body EMPTY>
<!ATTLIST fo:region-body
%region-properties;
%margin-properties-CSS;
column-count CDATA #IMPLIED
column-gap CDATA #IMPLIED
>
The region-body element
• Declaration in the unofficial DTD is
<!ELEMENT fo:region-body EMPTY>
<!ATTLIST fo:region-body
%region-properties;
%margin-properties-CSS;
column-count CDATA #IMPLIED
column-gap CDATA #IMPLIED
>
<!ENTITY % region-properties "
%border-padding-background-properties;
%area-properties;
region-name CDATA #IMPLIED">
<!ENTITY % area-properties " clip CDATA #IMPLIED overflow ( visible |
hidden | scroll | auto | error-if-overflow | inherit ) #IMPLIED display-align
( auto | before | center | after | inherit ) #IMPLIED reference-orientation
( 0 | 90 | 180 | 270 | -90 | -180 | -270 | 0deg | 90deg | 180deg | 270deg |
-90deg | -180deg | -270deg | inherit ) #IMPLIED writing-mode ( lr-tb | rltb | tb-rl | lr | rl | tb | inherit ) #IMPLIED ">
The fo:page-sequence element
• Declaration in the unofficial DTD
<!ELEMENT fo:page-sequence
(fo:title?,
fo:static-content*,
fo:flow)>
<!ATTLIST fo:page-sequence
id CDATA #IMPLIED
master-name CDATA #REQUIRED
initial-page-number CDATA #IMPLIED
force-page-count ( auto | even | odd | end-on-even
| end-on-odd | no-force | inherit) #IMPLIED
format CDATA #IMPLIED
letter-value ( auto | alphabetic | traditional ) #IMPLIED
grouping-separator CDATA #IMPLIED
grouping-size CDATA #IMPLIED
%inheritable-properties; >
• Thus a minimal fo:page-sequence must have a mastername and must contain an fo:flow
The fo:flow element
• Declaration in the unofficial DTD
<!ELEMENT fo:flow ( %blocks; )+ >
<!ATTLIST fo:flow %flow-properties; >
<!ENTITY % blocks " %basic-blocks; | %out-of-lines; | %wrappers; ">
<!ENTITY % flow-properties "
id CDATA #IMPLIED
flow-name CDATA #REQUIRED
%inheritable-properties; ">
<!ENTITY % basic-blocks " fo:block | fo:block-container | fo:tableand-caption | fo:table | fo:list-block ">
• Thus a minimal fo:flow must have a flow-name (which
specifies the region in which its content will be placed)
and must contain at least one blocks entity
• The simplest instance of blocks is an fo:block element
The fo:block element
• Declaration in the unofficial DTD
<!ELEMENT fo:block
( #PCDATA
| fo:initial-property-set
| %basic-inlines;
| %basic-blocks;
| %out-of-lines;
| %wrappers; )* >
<!ATTLIST fo:block %block-properties;>
• The simplest content for an fo:block element is just some
text
Example XSL-FO document
<?xml version="1.0"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master
master-name="myPageType" page-height="29.7cm"
page-width="21.0cm" margin="2.0cm">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="myPageType">
<fo:flow flow-name="xsl-region-body">
<fo:block>Hello world</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
Specifying lengths in XSL-FO
• A length in XSL-FO is written as a real number
followed by a unit qualification
• Section 5.9.13 of the XSL specification
http://www.w3.org/TR/xsl/#d0e5752
lists the allowable units as
•
•
•
•
•
•
•
cm
mm
in
pt (1/72 in)
pc (12 pt)
px
em (size of capital M in current font size)
The fop processor accepts XSL-FO files as input
• Place the text on the
previous slide in a file
called demo.fo
• Then run the
command
fop -fo demo.fo -pdf demo.pdf
• A pdf file will be
generated
The fop processor can output several types of file
• Assume that demo.fo contains the source
code shown on the previous slide
• The command
fop -fo demo.fo -png demo.png
will output the document as png image
• To see the full range of file types that can
be generated, run the command
fop -out list
Using XSLT to generate XSL-FO
• Suppose we have the
XML file shown
• Suppose we want to
generate the XSL-FO for
the PDF document
shown
• Our XSLT program must
– generate the "boiler-plate"
XSL-FO when it finds the
root node
– and generate a sentence
when it finds each country
node
• We will need two
templates
The "boiler-plate" template
<xsl:template match="/">
<fo:root>
<fo:layout-master-set>
<fo:simple-page-master master-name="A4-portrait"
page-height="29.7cm" page-width="21.0cm" margin="2cm">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<xsl:apply-templates select="./countries/country"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
The country template
<xsl:template match="country">
<fo:block>
<xsl:value-of select="."/> is a country.
</fo:block>
</xsl:template>
The complete XSLT stylesheet
<?xml version="1.0"?>
<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>
<fo:layout-master-set>
<fo:simple-page-master master-name="A4-portrait"
page-height="29.7cm" page-width="21.0cm" margin="2cm">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<xsl:apply-templates select="./countries/country"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="country">
<fo:block>
<xsl:value-of select="."/> is a country.
</fo:block>
</xsl:template>
</xsl:stylesheet>
Using FOP
• Assume the XML file is called countries.xml
• Assume the XSLT file is called countries.xsl
• We can generate the PDF file thus
fop -xml countries.xml -xsl countries.xsl -pdf countries.pdf
• We can see the XSL-FO thus
fop -xml countries.xml -xsl countries.xsl -foout countries.fo
The XSL-FO that was generated
<?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 margin="2cm" page-width="21.0cm"
page-height="29.7cm" master-name="A4-portrait">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block>France is a country.</fo:block>
<fo:block>Germany is a country.</fo:block>
<fo:block>Ireland is a country.</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
Block attributes
• In the unofficial DTD, many attributes are defined for
blocks
Block attributes
• In the unofficial DTD, many attributes are defined for
blocks
• We will consider just a a few at this stage
<!ATTLIST fo:block %block-properties;>
<!ENTITY % block-properties "
id CDATA #IMPLIED
%inheritable-properties; ">
<!ENTITY % inheritable-properties "
color CDATA #IMPLIED
relative-align ( before | baseline | inherit ) #IMPLIED
span ( none | all | inherit ) #IMPLIED
%accessibility-properties;
%absolute-or-relative-position-properties;
%border-padding-background-properties;
%border-precedence-properties;
%aural-properties;
%box-size-properties;
%margin-properties-inline;
%area-properties;
%area-alignment-properties-inline;
%character-properties;
%table-properties;
%list-properties;
%float-properties;
%line-related-properties;
%leader-properties;
%keeps-and-breaks-properties-block;
%hyphenation-properties-block;
%visibility-properties;
">
Block attributes
• In the unofficial DTD, many attributes are defined for
blocks
• We will consider just a a few at this stage
<!ATTLIST fo:block %block-properties;>
<!ENTITY % block-properties "
id CDATA #IMPLIED %inheritable-properties; ">
<!ENTITY % inheritable-properties "
color CDATA #IMPLIED
relative-align ( before | baseline | inherit ) #IMPLIED
span ( none | all | inherit ) #IMPLIED
%accessibility-properties;
%absolute-or-relative-position-properties;
%border-padding-background-properties;
%border-precedence-properties;
%aural-properties;
%box-size-properties;
%margin-properties-inline;
%area-properties;
%area-alignment-properties-inline;
%character-properties;
%table-properties;
%list-properties;
%float-properties;
%line-related-properties;
%leader-properties;
%keeps-and-breaks-properties-block;
%hyphenation-properties-block;
%visibility-properties;
">
A diagram of some block sttributes
Block attributes (contd.)
• Like a <p> or a <div> in
HTML, a <block> in XSLFO specifies that some
content should be
displayed in a rectangular
area that is visually
separated by a new line
• Like a CSS area, an XSLFO block area has
attributes that we can
control with CSS-like
expressions
• However, XSL-FO
provides many more
attributes than CSS
• Before surveying all the
attributes, let’s look at an
example use
Example use of block attributes in XSLT
<?xml version="1.0"?>
<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>
<fo:layout-master-set>
<fo:simple-page-master master-name="A4-portrait"
page-height="29.7cm" page-width="21.0cm" margin="2cm">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<xsl:apply-templates select="./countries/country"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="country">
<fo:block border-width="3mm" border-color="red" border-style="solid" space-before="5mm">
<xsl:value-of select="."/> is a country.
</fo:block>
</xsl:template>
</xsl:stylesheet>
Example contd: the XSL-FO generated
<?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 margin="2cm" page-width="21.0cm"
page-height="29.7cm" master-name="A4-portrait">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block space-before="5mm" border-style="solid" border-color="red" border-width="3mm">
France is a country.</fo:block>
<fo:block space-before="5mm" border-style="solid" border-color="red" border-width="3mm">
Germany is a country.</fo:block>
<fo:block space-before="5mm" border-style="solid" border-color="red" border-width="3mm">
Ireland is a country.</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
PDF based on new XSL-FO output
Block area attributes (page 1)
• Block space-before
and space-after
– These specify
minimum, optimum
and maximum
amounts of space that
must be separate a
block from the blocks
just before and after
the current block
– Will be considered in
detail later
Block area attributes (page 2)
• Block Margin
–
–
–
–
–
margin
margin-top
margin-bottom
margin-left
margin-right
Block area attributes (page 3)
• Block Border
– Border style attributes:
• Overall border
– border-style
• Side borders (Absolute Orientation)
–
–
–
–
border-top-style
border-bottom-style
border-left-style
border-right-style
• Sides borders (Orientation relative to writing-mode)
–
–
–
–
border-before-style (sometimes same as border-top)
border-after-style (sometimes same as border-bottom)
border-start-style (sometimes same as border-left)
border-end-style (sometimes same as border-right)
– Possible values
none | dotted | dashed | solid | double | groove | ridge
Block area attributes (page 4)
• Block Border (contd.)
– Border color attributes:
•
•
•
•
•
•
•
•
•
border-color
border-before-color
border-after-color
border-start-color
border-end-color
border-top-color (sometimes same as border-before)
border-bottom-color (sometimes same as border-after)
border-left-color (sometimes same as border-start)
border-right-color (sometimes same as border-end)
– Possible values
• any predefined colour name
• rgb(0-255,0-255,0-255)
Block area attributes (page 5)
• Block Border (contd.)
– Border width attributes:
•
•
•
•
•
•
•
•
•
border-width
border-before-width
border-after-width
border-start-width
border-end-width
border-top-width (sometimes same as border-before)
border-bottom-width (sometimes same as border-after)
border-left-width (sometimes same as border-start)
border-right-width (sometimes same as border-end)
Block area attributes (page 6)
• Block Border (contd.)
– Block Padding
•
•
•
•
•
•
•
•
•
padding
padding-before
padding-after
padding-start
padding-end
padding-top (sometimes same as padding-before)
padding-bottom (sometimes same as padding-after)
padding-left (sometimes same as padding-start)
padding-right (sometimes same as padding-end)
Block area attributes (page 7)
• Block Border (contd.)
– Block Background
•
•
•
•
background-color
background-image
background-repeat
background-attachment (scroll or
fixed)
Specifying versus constraining properties
• Some properties, for example border-color, can specify
an exact value which will appear in the output document
• However, the space-before and space-after properties
can only constrain the set of possible values that will
appear in the output document without being able to
specify the exact value that will appear
– The actual value will depend on the way that the FO engine
handles conflicting constraints
• We will now consider these two properties in some detail
The space-before and
space-after properties
Example XML document
• This is ex.xml. It contains a text element,
which contains ten paragraph elements:
<?xml version="1.0"?>
<text>
<paragraph>
This is a sentence in paragraph1. This is a sentence. ... This is a sentence.
</paragraph>
....
<paragraph>
This is a sentence in paragraph10. This is a sentence. ... This is a sentence.
</paragraph>
</text>
• The next slide contains ex1.xsl, an XSLT
stylesheet for processing this XML
ex1.xsl generates a header block and paragraph blocks
<?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>
<fo:layout-master-set> <fo:simple-page-master master-name="A4-portrait"
page-height="29.7cm" page-width="21.0cm" margin="2cm"><fo:region-body/></fo:simple-page-master> </fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="50pt" border="solid blue 3mm">Some text</fo:block>
<xsl:apply-templates select="./text/paragraph"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="paragraph">
<fo:block border="red solid 3mm"> <xsl:value-of select="."/></fo:block>
</xsl:template>
</xsl:stylesheet>
Result of processing XML with ex1.xsl
•
Result is a two page PDF file
fop -xml ex.xml -xsl ex1.xsl -pdf ex1.pdf
•
•
Notice that the sixth
paragraph is split across the
page boundary
The block specifications do
not require any space
between the blocks
•
Header block specification
<fo:block font-size="50pt"
border="solid blue 3mm">
Some text
</fo:block>
•
Paragraph block specification
<fo:block border="red solid
3mm">
<xsl:value-of select="."/>
</fo:block>
ex2.xsl Preventing paragraph blocks from crossing page boundaries
<?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>
<fo:layout-master-set> <fo:simple-page-master master-name="A4-portrait"
page-height="29.7cm" page-width="21.0cm" margin="2cm"><fo:region-body/></fo:simple-page-master> </fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="50pt" border="solid blue 3mm">Some text</fo:block>
<xsl:apply-templates select="./text/paragraph"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="paragraph">
<fo:block border="red solid 3mm" keep-together.within-page="always">
<xsl:value-of select="."/>
</fo:block>
</xsl:template>
</xsl:stylesheet>
Result of processing XML with ex2.xsl
•
The entire sixth paragraph is now on the second page
The keep-together property
• This property has three components, referring to three different
contexts
– within-line,
– within-column,
– within-page
• Possible values
– auto, which imposes no keep-together requirement
– always, which always keeps the formatting object keep-together
– <some integer>, which imposes a keep-together requirement of
the specified strength, with bigger integers being stronger if there
is ever a conflict
• A description of how conflicts are resolved is given at
http://www.w3.org/TR/xsl/#keepbreak
ex3.xsl Requiring space-before the paragraph blocks
<?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>
<fo:layout-master-set> <fo:simple-page-master master-name="A4-portrait"
page-height="29.7cm" page-width="21.0cm" margin="2cm"><fo:region-body/></fo:simple-page-master> </fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="50pt" border="solid blue 3mm">Some text</fo:block>
<xsl:apply-templates select="./text/paragraph"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="paragraph">
<fo:block border="red solid 3mm" keep-together.within-page="always"
space-before="4cm" >
<xsl:value-of select="."/>
</fo:block>
</xsl:template>
</xsl:stylesheet>
Result of processing XML with ex3.xsl
• The output now occupies 4 pages in PDF
• There is 4 cm of space before each paragraph
– except for a paragraph at the start of a page
• Why is there no 4 cm space before a paragraph at the
start of a page?
Space specifiers
• The space-before property specifies the space required before the
area generated by an XSL-FO object
• The space-after property specifies the space required after the area
generated by an XSL-FO object
• Each space-specifier has five components, with the default values
indicated in parentheses
–
–
–
–
–
minimum (0 pt)
optimum (0 pt)
maximum (0 pt)
conditionality (discard)
precedence (0)
• A space specifier like space-before="4cm" is actually a shorthand for
space-before.minimum="4cm"
space-before.optimum="4cm"
space-before.maximum="4cm"
space-before.conditionality="discard"
space-before.precedence="0"
The conditionality component of space specifiers
• Even if a space-specifier exists for an XSL-FO object, the space
may sometimes not be rendered
• A space specifier is normally used to generate a space between the
area generated by an XSL-FO object and the nearest visible mark
on the page before of after that area
• The nearest visible mark may come from
– the content of a non-empty content rectangle
– a non-zero border
• the border need not belong to the next or previous area
• it could belong to an embracing block
– some padding (because padding may contain background)
• the padding need not belong to the next or previous area
• it could belong to an embracing block
• If the area generated by an XSL-FO object is at the top of a page,
there is no visible mark on the page before the area, so a spacebefore could be discarded
• Similarly, if the area generated is at the bottom of a page, a spaceafter could be discarded
Conditionality component of space specifiers (contd.)
• The conditionality component of a space specifier can have one of
two values:
discard
• this means that the space-before/after is not required if there is no visible
mark on the page before/after the XSL-FO object which has this space
specifier
retain
• this means that the space-before/after must always be generated, even if
there is no visible mark on the page before/after the XSL-FO object which
has this space specifier
ex4.xsl Always requiring space-before the paragraph blocks
<?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>
<fo:layout-master-set> <fo:simple-page-master master-name="A4-portrait"
page-height="29.7cm" page-width="21.0cm" margin="2cm"><fo:region-body/></fo:simple-page-master> </fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="50pt" border="solid blue 3mm">Some text</fo:block>
<xsl:apply-templates select="./text/paragraph"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="paragraph">
<fo:block border="red solid 3mm" keep-together.within-page="always"
space-before="4cm" space-before.conditionality="retain" >
<xsl:value-of select="."/>
</fo:block>
</xsl:template>
</xsl:stylesheet>
Result of processing XML with ex4.xsl
• Now, there is a 4 cm space before each paragraph at
the start of a page
Precedence of space specifiers
• Sometimes, when two boxes follow each other, the first box may
have a space-after and the second box may have a space-after
• The formatting program does not automatically produce both of
these spaces
– the result would almost certainly be too much space between the
boxes
• Instead, the formatting program uses space precedence rules to
decide which space to generate on the page
• The value of the precedence component for a space specifier can
be either
– <some integer>
– or the word force
• By default, the precedence for a space specifier is 0
• The space precedence rules are on the next slide
Space precedence rules
• When two space specifiers are in conflict, the following rules are
used
• If either space precedence is force, the formatting program will
generate a space equal to the sum of all specifiers with a
precedence of force
• Otherwise, the formatting program will use the numeric space
precedences to decide what to do
• If the specifiers have different numeric precedences, the specifier
with the higher precedence is used
• If the specifiers have the same numeric precedence,
– the formatting program will generate a space somewhere in the range
[smaller-minimum, bigger maximum]
– initially, the formatting program will try to generate a space equal to the
bigger-maximum
ex5.xsl A force precedence wins
<?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>
<fo:layout-master-set> <fo:simple-page-master master-name="A4-portrait"
page-height="29.7cm" page-width="21.0cm" margin="2cm"><fo:region-body/></fo:simple-page-master> </fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="50pt" border="solid blue 3mm">Some text</fo:block>
<xsl:apply-templates select="./text/paragraph"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="paragraph">
<fo:block border="red solid 3mm"
space-before="4cm" space-before.precedence="force"
space-after="8cm" space-after.precedence="4" >
<xsl:value-of select="."/>
</fo:block>
</xsl:template>
</xsl:stylesheet>
Result of processing XML with ex5.xsl
• The 4cm spacebefore, with
precedence=force
beats the 8cm
space-after
• There is a 4 cm
space between
each pair of
paragraphs
ex6.xsl Two neighbouring specifiers with precedence=force
<?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>
<fo:layout-master-set> <fo:simple-page-master master-name="A4-portrait"
page-height="29.7cm" page-width="21.0cm" margin="2cm"><fo:region-body/></fo:simple-page-master> </fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="50pt" border="solid blue 3mm">Some text</fo:block>
<xsl:apply-templates select="./text/paragraph"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="paragraph">
<fo:block border="red solid 3mm"
space-before="4cm" space-before.precedence="force"
space-after="8cm" space-after.precedence="force" >
<xsl:value-of select="."/>
</fo:block>
</xsl:template>
</xsl:stylesheet>
Result of processing XML with ex6.xsl
• Both the 4cm
space-before and 8
cm space-after
have
precedence=force
• Each pair of
paragraphs on the
same page are
separated by 12 cm
ex7.xsl Two neighbouring specifiers with different numeric precedences
<?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>
<fo:layout-master-set> <fo:simple-page-master master-name="A4-portrait"
page-height="29.7cm" page-width="21.0cm" margin="2cm"><fo:region-body/></fo:simple-page-master> </fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="50pt" border="solid blue 3mm">Some text</fo:block>
<xsl:apply-templates select="./text/paragraph"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="paragraph">
<fo:block border="red solid 3mm"
space-before="4cm" space-before.precedence="4"
space-after="8cm" space-after.precedence="5" >
<xsl:value-of select="."/>
</fo:block>
</xsl:template>
</xsl:stylesheet>
Result of processing XML with ex7.xsl
• The 4cm space-before,
with precedence=4, is
beaten by the 8 cm
space-after with
precedence=5
• Each pair of paragraphs
on the same page are
separated by 8 cm
ex8.xsl Two neighbouring specifiers with different numeric precedences
<?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>
<fo:layout-master-set> <fo:simple-page-master master-name="A4-portrait"
page-height="29.7cm" page-width="21.0cm" margin="2cm"><fo:region-body/></fo:simple-page-master> </fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="50pt" border="solid blue 3mm">Some text</fo:block>
<xsl:apply-templates select="./text/paragraph"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="paragraph">
<fo:block border="red solid 3mm"
space-before="4cm" space-before.precedence="5"
space-after="8cm" space-after.precedence="4" >
<xsl:value-of select="."/>
</fo:block>
</xsl:template>
</xsl:stylesheet>
Result of processing XML with ex8.xsl
• The 4cm spacebefore, with
precedence=5, beats
by the 8 cm spaceafter with
precedence=4
• Each pair of
paragraphs on the
same page are
separated by 4 cm
ex9.xsl Two neighbouring specifiers with equal numeric precedences
<?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>
<fo:layout-master-set> <fo:simple-page-master master-name="A4-portrait"
page-height="29.7cm" page-width="21.0cm" margin="2cm"><fo:region-body/></fo:simple-page-master> </fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="50pt" border="solid blue 3mm">Some text</fo:block>
<xsl:apply-templates select="./text/paragraph"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="paragraph">
<fo:block border="red solid 3mm"
space-before="4cm" space-before.precedence="4"
space-after="8cm" space-after.precedence="4" >
<xsl:value-of select="."/>
</fo:block>
</xsl:template>
</xsl:stylesheet>
Result of processing XML with ex9.xsl
• Both the 4cm spacebefore and the 8cm
space-after have
precedence=4
• The actual space
must be in the
interval [4,8]
• The larger optimum
is 8cm, so it is tried
• It is possible
everywhere, so it is
used everywhere
A digression: the keep-with-previous and keep-with-next properties
• Each of these properties has three components, referring to three
different contexts
– within-line,
– within-column,
– within-page
• Possible values
– auto, which imposes no keep-with-previous/next requirement
– always, which always keeps the formatting object with the
previous/next object
– <some integer>, which imposes a keep-with-previous/next
requirement of the specified strength, with bigger integers being
stronger if there is ever a conflict
• A description of how conflicts are resolved is given at
http://www.w3.org/TR/xsl/#keepbreak
ex10.xsl Generating a space different from the optimum
<?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>
<fo:layout-master-set> <fo:simple-page-master master-name="A4-portrait"
page-height="29.7cm" page-width="21.0cm" margin="2cm"><fo:region-body/></fo:simple-page-master> </fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="50pt" border="solid blue 3mm">Some text</fo:block>
<xsl:apply-templates select="./text/paragraph"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="paragraph">
<fo:block border="red solid 3mm"
keep-together.within-page="always" keep-with-previous.within-page="5"
space-before="4cm" space-before.precedence="4"
space-after.minimum="5cm" space-after.optimum="12cm" spaceafter.maximum="12cm" space-after.precedence="4" >
<xsl:value-of select="."/>
</fo:block>
</xsl:template>
</xsl:stylesheet>
Result of processing XML with ex10.xsl
•
•
•
•
•
Both the 4cm space-before and
the 5-12cm space-after have
precedence=4
The actual space must be in the
interval [4,12]
The larger optimum is 12cm, so it
is tried everywhere
However, the keep-together and
keep-with-previous requirements
mean that the optimum is possible
only on the last page
On the earlier pages, a smaller
space is generated
ex11.xsl Using a negative space-before to cause overwriting
<?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>
<fo:layout-master-set> <fo:simple-page-master master-name="A4-portrait"
page-height="29.7cm" page-width="21.0cm" margin="2cm"><fo:region-body/></fo:simple-page-master> </fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="50pt" border="solid blue 3mm">Some text</fo:block>
<xsl:apply-templates select="./text/paragraph"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="paragraph">
<fo:block border="red solid 3mm"
space-before="-8mm" >
<xsl:value-of select="."/>
</fo:block>
</xsl:template>
</xsl:stylesheet>
Result of processing XML with ex11.xsl
•
Each paragraph block,
except that for paragraph
8, overwrites part of the
previous block
ex12.xsl Conflict between negative and positive space
<?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>
<fo:layout-master-set> <fo:simple-page-master master-name="A4-portrait"
page-height="29.7cm" page-width="21.0cm" margin="2cm"><fo:region-body/></fo:simple-page-master> </fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="50pt" border="solid blue 3mm">Some text</fo:block>
<xsl:apply-templates select="./text/paragraph"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="paragraph">
<fo:block border="red solid 3mm"
space-before.maximum="-8mm" space-after.optimum="4mm" >
<xsl:value-of select="."/>
</fo:block>
</xsl:template>
</xsl:stylesheet>
Result of processing XML with ex12.xsl
•
•
•
•
•
•
The first paragraph is moved
back 8mm, because there is no
space conflict
However, when a sequence of
two paragraphs are on the same
page, there is a space conflict
For space-before, max=-8mm
forces minimum and optimum to
be -8mm, because they cannot
exceed the maximum
For space-after, opt=4mm forces
the max to be 4mm as well,
because optimum cannot
exceed maximum. Minimum is
the default of 0.
Space generated must be in
range [smaller-min, bigger-max];
that is, in [-8mm,4mm]
The bigger optimum, of 4mm is
tried everywhere and can be
used everywhere
ex13.xsl Another conflict between negative and positive space
<?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>
<fo:layout-master-set> <fo:simple-page-master master-name="A4-portrait"
page-height="29.7cm" page-width="21.0cm" margin="2cm"><fo:region-body/></fo:simple-page-master> </fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="50pt" border="solid blue 3mm">Some text</fo:block>
<xsl:apply-templates select="./text/paragraph"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="paragraph">
<fo:block border="red solid 3mm"
space-before.maximum="-8mm" space-after.optimum="8cm" >
<xsl:value-of select="."/>
</fo:block>
</xsl:template>
</xsl:stylesheet>
Result of processing XML with ex13.xsl
•
•
•
•
•
•
•
The first paragraph is moved
back 8mm, because there is no
space conflict
However, when a sequence of
two paragraphs are on the same
page, there is a space conflict
For space-before, max=-8mm
forces minimum and optimum to
be -8mm, because they cannot
exceed the maximum
For space-after, opt=8cm forces
the max to be 8cm as well,
because optimum cannot
exceed maximum. Minimum is
the default of 0.
Space generated must be in
range [smaller-min, bigger-max];
that is, in [-8mm,8cm]
The bigger optimum, of 8cm is
tried everywhere
However, in all cases on the first
page, a smaller value must be
used
ex14.xsl Another conflict involving negative space
<?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>
<fo:layout-master-set> <fo:simple-page-master master-name="A4-portrait"
page-height="29.7cm" page-width="21.0cm" margin="2cm"><fo:region-body/></fo:simple-page-master> </fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="50pt" border="solid blue 3mm">Some text</fo:block>
<xsl:apply-templates select="./text/paragraph"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="paragraph">
<fo:block border="red solid 3mm"
space-before.maximum="-8mm" space-after.optimum="0mm" >
<xsl:value-of select="."/>
</fo:block>
</xsl:template>
</xsl:stylesheet>
A problem: the result of processing XML with ex14.xsl
•
•
•
•
•
•
•
•
The processing by fop does not agree
with what appears to be the rules
The first paragraph should be moved
back 8mm, because there is no space
conflict
However, when a sequence of two
paragraphs are on the same page,
there is a space conflict
For space-before, max=-8mm should
force minimum and optimum to be 8mm, because they cannot exceed the
maximum
For space-after, opt=0mm should force
the max to be 0mm as well, because
optimum cannot exceed maximum.
Minimum should be default of 0.
Space generated should be in range
[smaller-min, bigger-max]; that is, in [8mm,0mm]
The bigger optimum, of 0mm, should
be tried everywhere
However,
A problem: the result of processing XML with ex14.xsl
•
•
•
•
•
•
•
•
•
The processing by fop does not agree
with what appears to be the rules
The first paragraph should be moved
back 8mm, because there is no space
conflict
However, when a sequence of two
paragraphs are on the same page,
there is a space conflict
For space-before, max=-8mm should
force minimum and optimum to be 8mm, because they cannot exceed the
maximum
For space-after, opt=0mm should force
the max to be 0mm as well, because
optimum cannot exceed maximum.
Minimum should be default of 0.
Space generated should be in range
[smaller-min, bigger-max]; that is, in [8mm,0mm]
The bigger optimum, of 0mm, should
be tried everywhere
However, in all cases, -8mm is used
Why? Dunno?
The Area Model
The Area Model
• Almost everything in XSL-FO can be
regarded as being placed in a rectangular
box on the page
– the page itself is a box
– the regions with the page are boxes
– the blocks within a region are boxes
– each block contains boxes for lines
– lines contain boxes for text and inline areas
• This nesting of boxes is called the Area
Model
Box directions
• Earlier, it was said that
– border-before-color is sometimes the same as border-top-color,
–
–
–
–
border-after-color is sometimes the same as border-bottom-color,
border-start-color is sometimes the same as border-left-color,
border-end-color is sometimes the same as border-right-color,
etc.
• These statements use the word "sometimes", because
whether "before" means the same as "top", and so on,
depends on the directions in which content is being
added to a box
• Content is added to a box using two directions, which
will be illustrated on the next few slides
– the block-progression direction
– the inline-progression direction
Box directions for normal Western text
• In normal Western documents, the block-progression direction is
top-to-bottom, so
– before means the same as top
– after means the same as bottom
Box directions for normal Western text
• In normal Western documents, the inline-progression direction is
left-to-right, so
– start means the same as left
– end means the same as right
Box directions for Semitic languages
• In Semitic languages, the blockprogression direction is the
same as in Western languages:
top-to-bottom
• However, the inline-progression
direction is right-to-left, so
– start means the same as right
– end means the same as left
One set of directions for Japanese
• Japanese can be written in various
ways
One set of directions for Japanese
• Japanese can be written in various
ways
• One possible way is to start at the topright corner and write downwards
– so the inline-progression direction is
top-to-bottom
• so start means the same as top
• so end means the same as bottom
One set of directions for Japanese
• Japanese can be written in various
ways
• One possible way is to start at the topright corner and write downwards
– so the inline-progression direction is
top-to-bottom
• so start means the same as top
• so end means the same as bottom
• And then
One set of directions for Japanese
• Japanese can be written in various
ways
• One possible way is to start at the topright corner and write downwards
– so the inline-progression direction is
top-to-bottom
• so start means the same as top
• so end means the same as bottom
• And then move to the left for the next
column of characters
One set of directions for Japanese
• Japanese can be written in various
ways
• One possible way is to start at the topright corner and write downwards
– so the inline-progression direction is
top-to-bottom
• so start means the same as top
• so end means the same as bottom
• And then move to the left for the next
column of characters
– so the block progression direction is
right-to-left
• so before means the same as right
• so after means the same as left
Writing-mode
• The order in which a language appears on the page is called the
writing-mode
• The writing-mode for English is left-to-right, top-to-bottom (lr-tb)
• Writing mode affects the direction of block-progression and inlineprogression
• We can change these directions by using a style property called
writing-mode
• The values defined in the XSL-FO specification are
lr-tb | rl-tb | tb-rl | tb-lr | bt-lr | bt-rl | lr-bt | rl-bt | lr-alternating-rl-bt | lralternating-rl-tb | lr-inverting-rl-bt | lr-inverting-rl-tb | tb-lr-in-lr-pairs | lr | rl
| tb
• The first letter-pair specifies the inline-progression direction
• The second letter-pair specifies the block-progression direction
• Not all of these writing modes are supported by all XSL-FO engines
– for example, tb-lr gives an error message in Apache FOP
• The next dew slides show some example usage
We can set writing-mode in the simple-page-master tag
<?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 margin="2cm"
page-width="21.0cm" page-height="29.7cm"
master-name="A4-portrait" writing-mode="rl-tb" >
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block>Hello, Tom!</fo:block>
<fo:block>Hello, Dick!</fo:block>
<fo:block>Hello, Harry!</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
Writing-mode example 1
<fo:simple-page-master margin="2cm"
page-width="21.0cm" page-height="29.7cm"
master-name="A4-portrait" writing-mode="rl-tb" >
Writing-mode example 2
<fo:simple-page-master margin="2cm"
page-width="21.0cm" page-height="29.7cm"
master-name="A4-portrait" writing-mode="tb-rl" >
Page regions and
box directions
A reminder: regions of a page
• Earlier, we saw that XSL-FO treats a
page as a collection of regions
• But region-body is the only required
region
• If we want to use the optional regions,
we must define them in the order
specified in this DTD element definition
<!ELEMENT fo:simple-page-master
(fo:region-body,
fo:region-before?,
fo:region-after?,
fo:region-start?,
fo:region-end?
)>
The location of the regions
• The regions do not
always appear on the
page in the positions
show here
• The locations shown here
are simply those that the
regions have in normal
Western documents
Location of the optional regions in normal Western layout
• In normal Western documents, the
writing-mode is lr-tb
• So before/after/start/end have the
meanings shown in this image
Location of the optional regions in normal Western layout
• In normal Western documents, the
writing-mode is lr-tb
• So before/after/start/end have
the meanings shown in this image
Location of the optional regions in normal Western layout
• In normal Western documents, the
writing-mode is lr-tb
• So before/after/start/end have
the meanings shown in this image
<fo:simple-page-master margin="2cm"
page-width="21.0cm"
page-height="29.7cm"
master-name="A4-portrait"
writing-mode="lr-tb" >
<fo:region-body margin="2cm"/>
<fo:region-before extent="1.5cm"
background-color="green" />
<fo:region-after extent="1.5cm"
background-color="brown" />
<fo:region-start extent="1.5cm"
background-color="blue" />
<fo:region-end extent="1.5cm"
background-color="red" />
</fo:simple-page-master>
Location of the optional regions in normal Semitic layout
• In normal Semitic documents, the
writing-mode is rl-tb
• So before and after have the same
meanings as in Western documents
• But the meanings of start and end
are the reverse of their meaning in
Western style documents
Location of the optional regions in normal Semitic layout
• In normal Semitic documents, the
writing-mode is rl-tb
• So before and after have the same
meanings as in Western documents
• But the meanings of start and end
are the reverse of their meaning in
Western style documents
– the blue and red regions are
reversed from the previous slide
Location of the optional regions in normal Semitic layout
• In normal Semitic documents, the
writing-mode is rl-tb
• So before and after have the same
meanings as in Western documents
• But the meanings of start and end
are the reverse of their meaning in
Western style documents
– the blue and red regions are
reversed from the previous slide
<fo:simple-page-master margin="2cm"
page-width="21.0cm" page-height="29.7cm"
master-name="A4-portrait"
writing-mode="rl-tb" >
<fo:region-body margin="2cm"/>
<fo:region-before extent="1.5cm"
background-color="green" />
<fo:region-after extent="1.5cm"
background-color="brown" />
<fo:region-start extent="1.5cm"
background-color="blue" />
<fo:region-end extent="1.5cm"
background-color="red" />
</fo:simple-page-master>
Western versus Semitic layout
• The before (green) and after (brown) regions are in the same place
• But the start (blue) and end (red) regions are reversed
Apache FOP cannot handle optional regions in Japanese layout
• We have seen that Japanese sometimes
uses writing-mode=tb-rl
• Apache FOP seems able to handle the
text placement
• But it does not seem able to handle the
placement of the optional
before/after/start/end regions
<fo:simple-page-master margin="2cm"
page-width="21.0cm" page-height="29.7cm"
master-name="A4-portrait"
writing-mode="tb-rl" >
<fo:region-body margin="2cm"/>
<fo:region-before extent="1.5cm"
background-color="green" />
<fo:region-after extent="1.5cm"
background-color="brown" />
<fo:region-start extent="1.5cm"
background-color="blue" />
<fo:region-end extent="1.5cm"
background-color="red" />
</fo:simple-page-master>
Margins and regions
body-region margins are measured from ...
• When using the optional regions,
it is essential to remember that
margins for the content of
the region-body
are actually measured from
the outside edges of
body-region margins are measured from ...
• When using the optional regions,
it is essential to remember that
margins for the content of
the region-body
are actually measured from
the outside edges of
the page-reference-area
Margins and regions, Example 1
<fo:simple-page-master margin="0cm" …>
<fo:region-body margin="1cm"/>
<fo:region-before extent="0.5cm"
background color="green" />
<fo:region-after extent="0.5cm"
background-color="yellow" />
<fo:region-start extent="0.5cm"
background-color="blue" />
<fo:region-end extent="0.5cm“
background-color=“red" />
Margins and regions, Example 1
<fo:simple-page-master margin="0cm" …>
<fo:region-body margin="1cm"/>
<fo:region-before extent="0.5cm"
background color="green" />
<fo:region-after extent="0.5cm"
background-color="yellow" />
<fo:region-start extent="0.5cm"
background-color="blue" />
<fo:region-end extent="0.5cm“
background-color=“red" />
•
The simple-page-master margin
surrounds the page-reference-area,
which is divided into five regions
Margins and regions, Example 1
<fo:simple-page-master margin="0cm" …>
<fo:region-body margin="1cm"/>
<fo:region-before extent="0.5cm"
background color="green" />
<fo:region-after extent="0.5cm"
background-color="yellow" />
<fo:region-start extent="0.5cm"
background-color="blue" />
<fo:region-end extent="0.5cm“
background-color=“red" />
•
•
The simple-page-master margin
surrounds the page-reference-area,
which is divided into five regions
In this example we have a zero margin
in the simple-page-master
– so, here, the page-reference-area
covers the entire page
Margins and regions, Example 1
<fo:simple-page-master margin="0cm" …>
<fo:region-body margin="1cm"/>
<fo:region-before extent="0.5cm"
background color="green" />
<fo:region-after extent="0.5cm"
background-color="yellow" />
<fo:region-start extent="0.5cm"
background-color="blue" />
<fo:region-end extent="0.5cm“
background-color=“red" />
•
•
•
The simple-page-master margin
surrounds the page-reference-area,
which is divided into five regions
In this example we have a zero margin
in the simple-page-master
– so, here, the page-reference-area
covers the entire page
The margin for the region-body pushes
the content in from the outer edge of the
page-reference-area
Margins and regions, Example 1
<fo:simple-page-master margin="0cm" …>
<fo:region-body margin="1cm"/>
<fo:region-before extent="0.5cm"
background color="green" />
<fo:region-after extent="0.5cm"
background-color="yellow" />
<fo:region-start extent="0.5cm"
background-color="blue" />
<fo:region-end extent="0.5cm“
background-color=“red" />
•
•
•
•
The simple-page-master margin
surrounds the page-reference-area,
which is divided into five regions
In this example we have a zero margin
in the simple-page-master
– so, here, the page-reference-area
covers the entire page
The margin for the region-body pushes
the content in from the outer edge of the
page-reference-area
The reason there is white space above
and to the left of the content is that the
region-body margin is wider than
region-before and region-start
Margins and regions, Example 2
<fo:simple-page-master margin=“2cm" …>
<fo:region-body margin="1cm"/>
<fo:region-before extent="0.5cm
background color="green" />
<fo:region-after extent="0.5cm“
background-color="yellow" />
<fo:region-start extent="0.5cm"
background-color="blue" />
<fo:region-end extent="0.5cm“
background-color=“red" />
Margins and regions, Example 2
<fo:simple-page-master margin=“2cm" …>
<fo:region-body margin="1cm"/>
<fo:region-before extent="0.5cm
background color="green" />
<fo:region-after extent="0.5cm“
background-color="yellow" />
<fo:region-start extent="0.5cm"
background-color="blue" />
<fo:region-end extent="0.5cm“
background-color=“red" />
• The page-reference area is smaller than
the page, because the margin in the
simple-page-master is greater than zero
Margins and regions, Example 2
<fo:simple-page-master margin=“2cm" …>
<fo:region-body margin="1cm"/>
<fo:region-before extent="0.5cm
background color="green" />
<fo:region-after extent="0.5cm“
background-color="yellow" />
<fo:region-start extent="0.5cm"
background-color="blue" />
<fo:region-end extent="0.5cm“
background-color=“red" />
• The page-reference area is smaller than
the page, because the margin in the
simple-page-master is greater than zero
• The content is 3cm inside the edge of
the page because
– the simple-page-master margin is 2cm
– the region-body also has a margin, of
1cm
Margins and regions, Example 3
• Margins for region-body must
exceed the extents of the regionbefore, region-after, region-start and
region-end
• If not, the content of the region-body
will appear in these other regions
<fo:simple-page-master margin=“2cm" …>
<fo:region-body margin="1cm"/>
<fo:region-before extent=“1.5cm
background color="green“ />
<fo:region-after extent=“1.5cm“
background-color="yellow“ />
<fo:region-start extent=“1.5cm"
background-color="blue“ />
<fo:region-end extent=“1.5cm“
background-color=“red“ />
More on writing-mode
Putting writing-mode in a different place
• We have specified writing-mode as an attribute of a simple-pagemaster element
<fo:simple-page-master margin="2cm"
page-width="21.0cm" page-height="29.7cm"
master-name="A4-portrait"
writing-mode="tb-rl" >
• However, instead, we could specify it as an attribute of the regionbody element
<fo:simple-page-master margin="2cm"
page-width="21.0cm" page-height="29.7cm"
master-name="A4-portrait" >
<fo:region-body margin="2cm" writing-mode="tb-rl" />
<fo:region-before extent="1.5cm" background-color="green"/>
<fo:region-after extent="1.5cm" background-color="yellow"/>
<fo:region-start extent="1.5cm" background-color="blue"/>
<fo:region-end extent="1.5cm" background-color="red"/>
</fo:simple-page-master>
Writing-mode for region-body, Example 1
• Notice that setting
writing-mode in the
region-body does not
affect the placement of
the other regions
• unlike setting writingmode in the simple-pagemaster, which did affect
all the regions
<fo:region-body margin="2cm“
writing-mode="rl-tb“ />
<fo:region-before extent="1.5cm"
background-color="green"/>
<fo:region-after extent="1.5cm"
background-color="yellow"/>
<fo:region-start extent="1.5cm"
background-color="blue"/>
<fo:region-end extent="1.5cm"
background-color="red"/>
Writing-mode for region-body, Example 2
<fo:region-body margin="2cm“
writing-mode="tb-rl“ />
<fo:region-before extent="1.5cm"
background-color="green"/>
<fo:region-after extent="1.5cm"
background-color="yellow"/>
<fo:region-start extent="1.5cm"
background-color="blue"/>
<fo:region-end extent="1.5cm"
background-color="red"/>
Where can writing-mode be specified?
• The XSL-FO specification says that a writing-mode can be specified
for the following elements:
fo:simple-page-master,
fo:region-*,
fo:table,
fo:block-container,
fo:inline-container
• However, not all of these element types are supported by all FO
processors
– For example, as of 2010, Apache FOP does not support
fo:inline-container
• However, let's use it in fo:block-container
Using writing-mode in fo:block-container
<?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 margin="2cm"
page-width="21.0cm" page-height="29.7cm" master-name="A4-portrait">
<fo:region-body margin="2cm" writing-mode="lr-tb" /> </fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block-container writing-mode="lr-tb">
<fo:block>Hello, Tom!</fo:block>
<fo:block>Hello, Dick!</fo:block>
</fo:block-container>
<fo:block-container writing-mode="rl-tb">
<fo:block>Hello, Harry!</fo:block>
<fo:block>Hello, Mick!</fo:block>
</fo:block-container>
</fo:flow>
</fo:page-sequence>
</fo:root>
Using writing-mode in fo:block-container
<?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 margin="2cm"
page-width="21.0cm" page-height="29.7cm" master-name="A4-portrait">
<fo:region-body margin="2cm" writing-mode="lr-tb" /> </fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block-container writing-mode="lr-tb">
<fo:block>Hello, Tom!</fo:block>
<fo:block>Hello, Dick!</fo:block>
</fo:block-container>
<fo:block-container writing-mode="rl-tb">
<fo:block>Hello, Harry!</fo:block>
<fo:block>Hello, Mick!</fo:block>
</fo:block-container>
</fo:flow>
</fo:page-sequence>
</fo:root>
We can, of course, specify other attributes in fo:block-container
<?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 margin="2cm"
page-width="21.0cm" page-height="29.7cm" master-name="A4-portrait">
<fo:region-body margin="2cm" writing-mode="lr-tb" /> </fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block-container writing-mode="lr-tb" color="red">
<fo:block>Hello, Tom!</fo:block>
<fo:block>Hello, Dick!</fo:block>
</fo:block-container>
<fo:block-container writing-mode="rl-tb" color="blue">
<fo:block>Hello, Harry!</fo:block>
<fo:block>Hello, Mick!</fo:block>
</fo:block-container>
</fo:flow>
</fo:page-sequence>
</fo:root>
Now we can see why XSL-FO provides before/start/end/after
Now we can see why XSL-FO provides before/start/end/after
•
They let us specify style properties without worrying which writing-mode will
be used
<?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 margin="2cm" page-width="21.0cm" page-height="29.7cm" master-name="A4-portrait"><fo:region-body
margin="2cm" writing-mode="lr-tb" /> </fo:simple-page-master> </fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait"><fo:flow flow-name="xsl-region-body">
<fo:block-container>
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Tom!</fo:block>
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Dick!</fo:block>
</fo:block-container>
<fo:block-container>
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Harry!</fo:block>
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Mick!</fo:block>
</fo:block-container>
</fo:flow></fo:page-sequence></fo:root>
Now we can see why XSL-FO provides before/start/end/after
•
They let us specify style properties without worrying which writing-mode will
be used
<?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 margin="2cm" page-width="21.0cm" page-height="29.7cm" master-name="A4-portrait"><fo:region-body
margin="2cm" writing-mode="lr-tb" /> </fo:simple-page-master> </fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait"><fo:flow flow-name="xsl-region-body">
<fo:block-container>
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Tom!</fo:block>
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Dick!</fo:block>
</fo:block-container>
<fo:block-container>
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Harry!</fo:block>
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Mick!</fo:block>
</fo:block-container>
</fo:flow></fo:page-sequence></fo:root>
Now we can see why XSL-FO provides before/start/end/after
•
•
They let us specify style properties without worrying which writing-mode will
be used
Below, each block is given a border at the start of the text
<?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 margin="2cm" page-width="21.0cm" page-height="29.7cm" master-name="A4-portrait"><fo:region-body
margin="2cm" writing-mode="lr-tb" /> </fo:simple-page-master> </fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait"><fo:flow flow-name="xsl-region-body">
<fo:block-container>
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Tom!</fo:block>
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Dick!</fo:block>
</fo:block-container>
<fo:block-container>
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Harry!</fo:block>
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Mick!</fo:block>
</fo:block-container>
</fo:flow></fo:page-sequence></fo:root>
Now we can see why XSL-FO provides before/start/end/after
•
•
•
They let us specify style properties without worrying which writing-mode will
be used
Below, each block is given a border at the start of the text
In normal Western documents, these borders will be at the left side
<?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 margin="2cm" page-width="21.0cm" page-height="29.7cm" master-name="A4-portrait"><fo:region-body
margin="2cm" writing-mode="lr-tb" /> </fo:simple-page-master> </fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait"><fo:flow flow-name="xsl-region-body">
<fo:block-container>
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Tom!</fo:block>
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Dick!</fo:block>
</fo:block-container>
<fo:block-container>
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Harry!</fo:block>
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Mick!</fo:block>
</fo:block-container>
</fo:flow></fo:page-sequence></fo:root>
In Western documents start borders are at
the left-hand side
But in Semitic documents start borders
should be at the right-hand side
Why before/start/end/after are useful
Why before/start/end/after are useful
• We can specify style in a languageindependent way
<?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 margin="2cm"
page-width="21.0cm" page-height="29.7cm" master-name="A4-portrait">
<fo:region-body margin="2cm" writing-mode="lr-tb" /> </fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait"><fo:flow flow-name="xsl-region-body">
<fo:block-container>
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Tom!</fo:block>
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Dick!</fo:block>
</fo:block-container>
<fo:block-container>
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Harry!</fo:block>
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Mick!</fo:block>
</fo:block-container>
</fo:flow></fo:page-sequence></fo:root>
Why before/start/end/after are useful
• We can specify style in a languageindependent way and then add writing-mode
<?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 margin="2cm"
page-width="21.0cm" page-height="29.7cm" master-name="A4-portrait">
<fo:region-body margin="2cm" writing-mode="lr-tb" /> </fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait"><fo:flow flow-name="xsl-region-body">
<fo:block-container writing-mode="lr-tb">
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Tom!</fo:block>
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Dick!</fo:block>
</fo:block-container>
<fo:block-container writing-mode="rl-tb">
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Harry!</fo:block>
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Mick!</fo:block>
</fo:block-container>
</fo:flow></fo:page-sequence></fo:root>
Why before/start/end/after are useful
• We can specify style in a languageindependent way and then add writing-mode
<?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 margin="2cm"
page-width="21.0cm" page-height="29.7cm" master-name="A4-portrait">
<fo:region-body margin="2cm" writing-mode="lr-tb" /> </fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait"><fo:flow flow-name="xsl-region-body">
<fo:block-container writing-mode="lr-tb">
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Tom!</fo:block>
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Dick!</fo:block>
</fo:block-container>
<fo:block-container writing-mode="rl-tb">
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Harry!</fo:block>
<fo:block border-start-style="solid" border-start-width="3mm">
Hello, Mick!</fo:block>
</fo:block-container>
</fo:flow></fo:page-sequence></fo:root>
Static versus flow content
• The definition of fo:page-sequence in the unofficial DTD is
<!ELEMENT fo:page-sequence
( fo:title?, fo:static-content*, fo:flow ) >
• The fo:title is intended for use in interactive user agents, so is not
useful at present
• The fo:flow defines content which is often longer than would fit on
one page, so it flows along a sequence of pages
• An fo:page-sequence can have several fo:static-content children
• fo:static-content elements are used to define content that appears
in the same place on each page
• usually static content is placed in regions other than the region-body
• for example, static content is often used to define headers and
footers for pages
Consider this two-page document
• Each page has three
regions
– region-body
– region-before (silver)
– region-start (grey/gray)
• The region-body contains
flowing content
• The region-start is empty
• But the region-before has
content
– this content is the same
on all pages
– it is static content
Larger view
Specifying static content
<?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 margin="2cm" page-width="21.0cm" page-height="29.7cm" master-name="A4-portrait">
<fo:region-body margin="3cm"/>
<fo:region-before extent="2cm" background-color="silver"/>
<fo:region-start extent="2cm" background-color="gray"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:static-content flow-name="xsl-region-before">
<fo:block font-size="30pt">Greetings</fo:block>
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block>Hello, Tom!</fo:block>
<fo:block>Hello, Dick!</fo:block><fo:block>Hello, Harry!</fo:block><fo:block>Hello, Mick!</fo:block>
<fo:block>Hello, Mick!</fo:block> .... <fo:block>Hello, Mick!</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
Location-dependent static content: page numbering
<?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 margin="2cm" page-width="21.0cm" page-height="29.7cm" master-name="A4-portrait">
<fo:region-body margin="3cm"/>
<fo:region-before extent="2cm" background-color="silver"/>
<fo:region-after extent="2cm" background-color="silver"/>
<fo:region-start extent="2cm" background-color="gray"/>
</fo:simple-page-master></fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:static-content flow-name="xsl-region-before">
<fo:block font-size="30pt">Greetings</fo:block>
</fo:static-content>
<fo:static-content flow-name="xsl-region-after">
<fo:block font-size="25pt">Page <fo:page-number/></fo:block>
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block>Hello, Tom!</fo:block><fo:block>Hello, Dick!</fo:block><fo:block>Hello, Harry!</fo:block>
<fo:block>Hello, Mick!</fo:block><fo:block>Hello, Mick!</fo:block> .... <fo:block>Hello, Mick!</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
Location-dependent static content: page numbering
Page numbering
• The page-sequence element has several attributes for page numbering
• In the unofficial DTD, this element's attributes are
<!ATTLIST fo:page-sequence
id CDATA #IMPLIED
master-name CDATA #REQUIRED
initial-page-number CDATA #IMPLIED
force-page-count
( auto | even | odd | end-on-even | end-on-odd | no-force | inherit) #IMPLIED
format CDATA #IMPLIED
letter-value ( auto | alphabetic | traditional ) #IMPLIED
grouping-separator CDATA #IMPLIED
grouping-size CDATA #IMPLIED
%inheritable-properties; >
•
•
The attributes coloured red above control the values of the page numbers in the
sequence
The attributes coloured blue above control the appearance of the page numbers,
– by controlling how these numbers are converted into strings
Specifying initial-page number
<?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 margin="2cm" page-width="21.0cm" page-height="29.7cm" master-name="A4-portrait">
<fo:region-body margin="3cm"/>
<fo:region-before extent="2cm" background-color="silver"/>
<fo:region-after extent="2cm" background-color="silver"/>
<fo:region-start extent="2cm" background-color="gray"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait" initial-page-number="999" >
<fo:static-content flow-name="xsl-region-before">
<fo:block font-size="30pt">Greetings</fo:block>
</fo:static-content>
<fo:static-content flow-name="xsl-region-after">
<fo:block font-size="25pt">Page <fo:page-number/></fo:block>
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block>Hello, Tom!</fo:block>
<fo:block>Hello, Dick!</fo:block><fo:block>Hello, Harry!</fo:block><fo:block>Hello, Mick!</fo:block>
<fo:block>Hello, Mick!</fo:block> .... <fo:block>Hello, Mick!</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
Specifying initial-page number (contd.)
<fo:page-sequence master-reference="A4-portrait" initial-page-number="999">
Specifying initial-page number (contd.)
• In the example just shown, we set the initial-page-number to a
specified number
<fo:page-sequence master-reference="A4-portrait" initial-page-number="999">
• However, initial-page-number can also have one of these symbolic
values
auto | auto-odd | auto-even
• The meaning of these depends on whether or not the current pagesequence is the first page-sequence in the document
• They will not be considered at this stage
Specifying the format for page numbers
•
•
format="1" specifies that page numbers should be expressed in decimal
notation and should use the minimum possible number of digits
Example
<fo:page-sequence master-reference="A4-portrait"
initial-page-number="9" format="1" >
Specifying the format for page numbers
•
•
format="1" specifies that page numbers should be expressed in decimal
notation and should use the minimum possible number of digits
Example
<fo:page-sequence master-reference="A4-portrait"
initial-page-number="9" format="1" >
Specifying the format for page numbers (contd.)
•
•
format="0...1" specifies that page numbers should be expressed in decimal
notation and should use at least the number of digits given
Example
<fo:page-sequence master-reference="A4-portrait"
initial-page-number="9" format="001" >
Specifying the format for page numbers (contd.)
•
•
format="0...1" specifies that page numbers should be expressed in decimal
notation and should use at least the number of digits given
Example
<fo:page-sequence master-reference="A4-portrait"
initial-page-number="9" format="001" >
Specifying the format for page numbers (contd.)
•
•
format="i" specifies that page numbers should be expressed in lower-case
Roman numerals
Example
<fo:page-sequence master-reference="A4-portrait"
initial-page-number="9" format="i" >
Specifying the format for page numbers (contd.)
•
•
format="i" specifies that page numbers should be expressed in lower-case
Roman numerals
Example
<fo:page-sequence master-reference="A4-portrait"
initial-page-number="9" format="i" >
Specifying the format for page numbers (contd.)
•
•
format="I" specifies that page numbers should be expressed in upper-case
Roman numerals
Example
<fo:page-sequence master-reference="A4-portrait"
initial-page-number="9" format="I" >
Specifying the format for page numbers (contd.)
•
•
format="I" specifies that page numbers should be expressed in upper-case
Roman numerals
Example
<fo:page-sequence master-reference="A4-portrait"
initial-page-number="9" format="I" >
Specifying the format for page numbers (contd.)
•
•
Roman numerals can, of course, be used for large numbers
Example
<fo:page-sequence master-reference="A4-portrait"
initial-page-number="999" format="I" >
Specifying the format for page numbers (contd.)
•
•
Roman numerals can, of course, be used for large numbers
Example
<fo:page-sequence master-reference="A4-portrait"
initial-page-number="999" format="I" >
Specifying the format for page numbers (contd.)
•
•
format="a" specifies that page numbers should be expressed in lower-case
Latin letters
Example
<fo:page-sequence master-reference="A4-portrait"
initial-page-number="9" format="a" >
Specifying the format for page numbers (contd.)
•
•
format="a" specifies that page numbers should be expressed in lower-case
Latin letters
Example
<fo:page-sequence master-reference="A4-portrait"
initial-page-number="9" format="a" >
Specifying the format for page numbers (contd.)
•
•
format="A" specifies that page numbers should be expressed as upper-case
Latin letters
Example
<fo:page-sequence master-reference="A4-portrait"
initial-page-number="9" format="A" >
Specifying the format for page numbers (contd.)
•
•
format="A" specifies that page numbers should be expressed as upper-case
Latin letters
Example
<fo:page-sequence master-reference="A4-portrait"
initial-page-number="9" format="A" >
Specifying the format for page numbers (contd.)
•
•
Although it is rarely done, Latin letters can be used for large numbers
Example
<fo:page-sequence master-reference="A4-portrait"
initial-page-number="999" format="A" >
Specifying the format for page numbers (contd.)
•
•
Although it is rarely done, Latin letters can be used for large numbers
Example
<fo:page-sequence master-reference="A4-portrait"
initial-page-number="999" format="A" >
Specifying the format for page numbers (contd.)
•
The are three other number formatting attributes that we have not examined yet:
letter-value ( auto | alphabetic | traditional ) #IMPLIED
grouping-separator CDATA #IMPLIED
grouping-size CDATA #IMPLIED
•
•
The meaning of these three attributes is not yet implemented by Apache FOP
So we will not consider them at this stage
Forcing page count
• The force-page-count attribute of a page-sequence element is used to
impose a constraint on the number of pages in a page-sequence
• If this constraint is not satisfied, an additional page will be added to the
end of the sequence
– This page becomes the "last" page of the sequence
• The values that this attribute can have are
•
even - force an even number of pages in this page-sequence
•
odd - force an odd number of pages in this page-sequence
•
end-on-even - force the last page in this page-sequence to be an even page
•
•
•
end-on-odd - force the last page in this page-sequence to be an even page
no-force - do not force either an even or odd number of pages
auto - the meaning of this depends on whether or not the current page-sequence is
the last page-sequence in the document; it will not be considered at this stage
Forcing page count, Example 1
• This document really needs only
two pages
• But it has three pages, ...
• Because we forced the page count
to be odd
<fo:page-sequence
master-reference="A4-portrait"
force-page-count="odd" >
Forcing page count, Example 2
• This document really needs only
two pages
• But it has three pages, ...
• Because we forced the page count
to end on an even number
force-page-count="end-on-even"
• Since there are only two pages of
content, we would still have needed
only two pages
• But we had specified that the first
page number should be 100
<fo:page-sequence
master-reference="A4-portrait"
initial-page-number="100"
force-page-count="end-on-even" >
Accessing the current page number
• The element <fo:page-number> produces an inline-area whose
content is the page-number for the page on which the inline-area is
placed
Accessing the current page number
• The element <fo:page-number> produces some inline text
representing the page-number of the page on which the inline text is
located
<?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 margin="2cm" page-width="21.0cm" page-height="29.7cm" master-name="A4-portrait">
<fo:region-body margin="3cm"/>
<fo:region-before extent="2cm" background-color="silver"/>
<fo:region-after extent="2cm" background-color="silver"/>
<fo:region-start extent="2cm" background-color="gray"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait" initial-page-number="999" >
<fo:static-content flow-name="xsl-region-before"><fo:block font-size="30pt">Greetings</fo:block></fo:static-content>
<fo:static-content flow-name="xsl-region-after"><fo:block font-size="25pt">Page <fo:page-number/></fo:block></fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block>Hello, Tom! This is page <fo:page-number> </fo:block>
<fo:block>Hello, Dick! This is page <fo:page-number> </fo:block>
<fo:block>Hello, Harry! This is page <fo:page-number> </fo:block>
<fo:block>Hello, Mick! This is page <fo:page-number> </fo:block>
<fo:block>Hello, Mick! This is page <fo:page-number> </fo:block>
....
<fo:block>Hello, Mick! This is page <fo:page-number> </fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
Accessing the current page number (contd.)
Accessing the current page number (contd.)
• The text produced by the <fo:page-number> element depends on
the page numbering format that is being used
Accessing the current page number (contd.)
• The text produced by the <fo:page-number> element depends on
the page numbering format that is being used
<?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 margin="2cm" page-width="21.0cm" page-height="29.7cm" master-name="A4-portrait">
<fo:region-body margin="3cm"/>
<fo:region-before extent="2cm" background-color="silver"/>
<fo:region-after extent="2cm" background-color="silver"/>
<fo:region-start extent="2cm" background-color="gray"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait"
initial-page-number="999" format="I" >
<fo:static-content flow-name="xsl-region-before"><fo:block font-size="30pt">Greetings</fo:block></fo:static-content>
<fo:static-content flow-name="xsl-region-after"><fo:block font-size="25pt">Page <fo:page-number/></fo:block></fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block>Hello, Tom! This is page <fo:page-number> </fo:block>
<fo:block>Hello, Dick! This is page <fo:page-number> </fo:block>
<fo:block>Hello, Harry! This is page <fo:page-number> </fo:block>
<fo:block>Hello, Mick! This is page <fo:page-number> </fo:block>
<fo:block>Hello, Mick! This is page <fo:page-number> </fo:block>
....
<fo:block>Hello, Mick! This is page <fo:page-number> </fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
Accessing the current page number (contd.)
Cross-referencing pages
Cross-referencing pages
• The last line of this document refers to the page
containing the first line
Cross-referencing pages
• The last line of this document refers to the page
containing the first line
Cross-referencing pages (contd.)
• The XSL-FO source-code for the document is shown below
• It will be explained on the next slide
<?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 margin="2cm" page-width="21.0cm" page-height="29.7cm" master-name="A4-portrait">
<fo:region-body margin="3cm"/><fo:region-before extent="2cm" background-color="silver"/><fo:region-after extent="2cm" backgroundcolor="silver"/><fo:region-start extent="2cm" background-color="gray"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:static-content flow-name="xsl-region-before"><fo:block font-size="30pt">Greetings</fo:block></fo:static-content>
<fo:static-content flow-name="xsl-region-after"><fo:block font-size="25pt">Page <fo:page-number/></fo:block></fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block id="tomGreeting" >Hello, Tom!</fo:block>
<fo:block>Hello, Dick! </fo:block><fo:block>Hello, Harry! </fo:block><fo:block>Hello, Mick! </fo:block>
<fo:block>Hello, Mick! </fo:block>
....
<fo:block>Hello, Mick! </fo:block>
<fo:block>Hello, Thomas! Are you related to Tom?
(See page <fo:page-number-citation ref-id="tomGreeting"/> ) </fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
Cross-referencing pages (contd.)
•
The important part of the source code is
<fo:block id="tomGreeting"> Hello, Tom! </fo:block>
...
See page <fo:page-number-citation ref-id="tomGreeting"/>
•
•
•
The fo:page-number-citation element generates the cross-reference
This element can be contrasted with the fo:page-number element as
follows
The fo:page-number element produces some inline text representing the
number of the page on which the element itself is located
(more precisely, the page containing the text generated by the element itself)
•
The fo:page-number-citation element produces some inline text
representing the number of the page which contains some other element
(more precisely, the page containing the text generated by the other element)
•
The other element is the element whose id attribute has a value equal to
the value of the ref-id attribute of the fo:page-number-citation element
Using cross-referencing in the page footer (contd.)
•
In the following document, each page has a footer of the form
Page number1 of number2
•
The second number is generated by a cross-reference to the page
containing the last text in the document
Using cross-referencing in the page footer (contd.)
•
In the following document, each page has a footer of the form
Page number1 of number2
•
The second number is generated by a cross-reference to the page
containing the last text in the document
Using cross-referencing in the page footer (contd.)
• The source-code for the document is shown below
<?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 margin="2cm" page-width="21.0cm" page-height="29.7cm" master-name="A4-portrait">
<fo:region-body margin="3cm"/><fo:region-before extent="2cm" background-color="silver"/><fo:region-after extent="2cm" backgroundcolor="silver"/><fo:region-start extent="2cm" background-color="gray"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:static-content flow-name="xsl-region-before"><fo:block font-size="30pt">Greetings</fo:block></fo:static-content>
<fo:static-content flow-name="xsl-region-after">
<fo:block font-size="25pt">
Page <fo:page-number/> of <fo:page-number-citation ref-id="endOfText"/>
</fo:block>
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block>Hello, Tom!</fo:block>
<fo:block>Hello, Dick! </fo:block><fo:block>Hello, Harry! </fo:block><fo:block>Hello, Mick! </fo:block>
<fo:block>Hello, Mick! </fo:block>
....
<fo:block id="endOfText">Hello, Mick!</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
Multiple page masters
Multiple page masters
•
•
•
•
•
•
•
Until now, each document had only one simple-page-master
This is because all our pages were intended to have the same layout
However, frequently, we need to have different page layouts in a single
document
For example, if we are formatting a booklet which will be stapled, ...
... we will need to leave space for the stapling
Left-hand pages will need a bigger margin on the right-hand side
Right-hand pages will need a bigger margin on the left-hand-side
Multiple page masters
•
•
•
•
•
•
•
Until now, each document had only one simple-page-master
This is because all our pages were intended to have the same layout
However, frequently, we need to have different page layouts in a single
document
For example, if we are formatting a booklet which will be stapled, ...
... we will need to leave space for the stapling
Left-hand pages will need a bigger margin on the right-hand side
Right-hand pages will need a bigger margin on the left-hand-side
Multiple page masters (contd.)
• The layout-master-set must contain a simple-page-master for each
type of page payout that we need
• We will also need to specify when each of these simple page
masters should be used
• This is done using a new type of element called a
page-sequence-master
• Elements of this type are declared in the layout-master-set
• Remember that its definition in the unofficial DTD was
<!ELEMENT fo:layout-master-set
( fo:page-sequence-master*, fo:simple-page-master,
( fo:simple-page-master | fo:page-sequence-master )* ) >
•
So our layout-master-set will look something like this
<fo:layout-master-set>
<fo:simple-page-master ...> ... </fo:simple-page-master>
<fo:simple-page-master ...> ... </fo:simple-page-master>
<fo:page-sequence-master ...> ... </fo:page-sequence-master>
</fo:layout-master-set>
Multiple page masters: the leftPage
<fo:layout-master-set>
<fo:simple-page-master master-name="leftPage"
page-width="21.0cm" page-height="29.7cm"
margin-left="1.0cm" margin-right="4.5cm"
margin-top="1.0cm" margin-bottom="1.0cm">
<fo:region-before extent="1cm"/>
<fo:region-after extent="1cm"/>
<fo:region-body margin-top="1.5cm" margin-bottom="1.5cm" background-color="silver"/>
</fo:simple-page-master>
<fo:simple-page-master master-name="rightPage"
page-width="21.0cm" page-height="29.7cm"
margin-left="1.5cm" margin-right="1.0cm"
margin-top="1.0cm" margin-bottom="1.0cm">
<fo:region-before extent="1cm"/>
<fo:region-after extent="1cm"/>
<fo:region-body margin-top="1.5cm" margin-bottom="1.5cm" />
</fo:simple-page-master>
<fo:page-sequence-master master-reference="..."> ... </fo:page-sequence-master>
</fo:layout-master-set>
Multiple page masters: the rightPage
<fo:layout-master-set>
<fo:simple-page-master master-name="leftPage"
page-width="21.0cm" page-height="29.7cm"
margin-left="1.0cm" margin-right="4.5cm"
margin-top="1.0cm" margin-bottom="1.0cm">
<fo:region-body margin-top="1.5cm" margin-bottom="1.5cm" background-color="silver"/>
<fo:region-before extent="1cm"/>
<fo:region-after extent="1cm"/>
</fo:simple-page-master>
<fo:simple-page-master master-name="rightPage"
page-width="21.0cm" page-height="29.7cm"
margin-left="4.5cm" margin-right="1.0cm"
margin-top="1.0cm" margin-bottom="1.0cm">
<fo:region-body margin-top="1.5cm" margin-bottom="1.5cm" background-color="silver"/>
<fo:region-before extent="1cm"/>
<fo:region-after extent="1cm"/>
</fo:simple-page-master>
<fo:page-sequence-master master-reference="contents"> ... </fo:page-sequence-master>
</fo:layout-master-set>
Multiple page masters: the page-sequence-master
<fo:layout-master-set>
<fo:simple-page-master master-name="leftPage"
page-width="21.0cm" page-height="29.7cm"
margin-left="1.0cm" margin-right="4.5cm"
margin-top="1.0cm" margin-bottom="1.0cm">
<fo:region-body margin-top="1.5cm" margin-bottom="1.5cm" background-color="silver"/>
<fo:region-before extent="1cm"/>
<fo:region-after extent="1cm"/>
</fo:simple-page-master>
<fo:simple-page-master master-name="rightPage"
page-width="21.0cm" page-height="29.7cm"
margin-left="4.5cm" margin-right="1.0cm"
margin-top="1.0cm" margin-bottom="1.0cm">
<fo:region-body margin-top="1.5cm" margin-bottom="1.5cm" background-color="silver"/>
<fo:region-before extent="1cm"/>
<fo:region-after extent="1cm"/>
</fo:simple-page-master>
<fo:page-sequence-master master-name="contents"> ... </fo:page-sequence-master>
</fo:layout-master-set>
fo:page-sequence-master
• Its definition in the unofficial DTD is
<!ELEMENT fo:page-sequence-master
( ( fo:single-page-master-reference |
fo:repeatable-page-master-reference |
fo:repeatable-page-master-alternatives )+ ) >
<!ATTLIST fo:page-sequence-master master-name CDATA #REQUIRED >
• The different types of child element for a page-sequence-master serve
different purposes
• We need to specify when to use members of a set of alternative simple
page masters
• So we need to use the child element called
fo:repeatable-page-master-alternatives
fo:repeatable-page-master-alternatives
• The definition of this element in the unofficial DTD is
<!ELEMENT fo:repeatable-page-master-alternatives
( fo:conditional-page-master-reference+ ) >
<!ATTLIST fo:repeatable-page-master-alternatives
maximum-repeats CDATA #IMPLIED >
• We see that it can contain multiple children elements of type
fo:conditional-page-master-reference
• Each of these specifies when to use a particular page master
fo:conditional-page-master-reference
• The definition of this element in the unofficial DTD is slightly wrong
• It should be
<!ELEMENT fo:conditional-page-master-reference EMPTY>
<!ATTLIST fo:conditional-page-master-reference
master-reference CDATA #REQUIRED
page-position ( first | last | rest | any | inherit ) #IMPLIED
odd-or-even ( odd | even | any | inherit ) #IMPLIED
blank-or-not-blank ( blank | not-blank | any | inherit ) #IMPLIED >
• This element specifies when a particular page master (identified by the
master-reference attribute) should be used
• The other attributes describe the conditions that must be satisfied when
the particular page master is used
Example page-sequence-master
• Suppose we want the first page to be a rightPage
• This means we want odd-numbered pages to use the rightPage master
• And even-numbered pages to use the leftPage master
Example page-sequence-master
• Suppose we want the first page to be a rightPage
• This means we want odd-numbered pages to use the rightPage master
• And even-numbered pages to use the leftPage master
<fo:page-sequence-master master-name="booklet">
<fo:repeatable-page-master-alternatives>
<fo:conditional-page-master-reference
master-reference="leftPage"
odd-or-even="even" />
<fo:conditional-page-master-reference
master-reference="rightPage"
odd-or-even="odd" />
</fo:repeatable-page-master-alternatives>
</fo:page-sequence-master>
The page-sequence
• Make the page-sequence refer to the booklet page-sequence-master
<fo:page-sequence master-reference="booklet" initial-page-number="1" format="1" >
<fo:static-content flow-name="xsl-region-before">
<fo:block font-size="20pt">Greetings</fo:block>
</fo:static-content>
<fo:static-content flow-name="xsl-region-after">
<fo:block font-size="20pt">Page <fo:page-number/></fo:block>
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block>Hello, Tom!</fo:block><fo:block>Hello, Dick!</fo:block>
<fo:block>Hello, Harry!</fo:block><fo:block>Hello, Mick!</fo:block>
<fo:block>Hello, Mick!</fo:block> ... <fo:block>Hello, Mick!</fo:block>
</fo:flow>
</fo:page-sequence>
The result
• See that Page 1 is a rightPage and Page 2 is a leftPage
Including images
Including images
• One way of including an image in a document is to use the
fo:external-graphic element
• Its definition in the unofficial DTD is
<!ELEMENT fo:external-graphic EMPTY >
<!ATTLIST fo:external-graphic
%graphic-properties;
src CDATA #IMPLIED >
• The graphic properties are:
<!ENTITY % graphic-properties "
id CDATA #IMPLIED content-type CDATA #IMPLIED
%accessibility-properties;
%relative-position-properties;
%aural-properties;
%border-padding-background-properties;
%margin-properties-inline;
%area-alignment-properties-inline;
%box-size-properties;
%font-properties;
%line-height-properties;
%keeps-and-breaks-properties-atomic;
content-height CDATA #IMPLIED
content-width CDATA #IMPLIED
scaling ( uniform | non-uniform | inherit ) #IMPLIED
scaling-method ( auto | integer-pixels | resample-any-method | inherit ) #IMPLIED
overflow ( visible | hidden | scroll | auto | error-if-overflow | inherit ) #IMPLIED ">
Including images (contd.)
• Example usage
<fo:block text-align="end">
<fo:external-graphic src=“URL-or-path/to/some/image-file“/>
content-width="99px" content-height="109px" />
</fo:block>
Graphic inclusion, example 1
<?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="ordinaryPage"page-width="21.0cm" pageheight="29.7cm“ margin-left="1.0cm" margin-right="2.0cm"margin-top="1.0cm" margin-bottom="2.0cm">
<fo:region-body margin-top="1.5cm" margin-bottom="1.5cm“ background-color="silver" />
<fo:region-before extent="1cm"/><fo:region-after extent="1cm"/></fo:simple-pagemaster></fo:layout-master-set>
<fo:page-sequence master-reference="ordinaryPage“ initial-page-number="1" format="1" >
<fo:static-content flow-name="xsl-region-before"><fo:block font-size="20pt">Greetings</fo:block> </fo:staticcontent>
<fo:static-content flow-name="xsl-region-after"><fo:block font-size="20pt">Page <fo:pagenumber/></fo:block></fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block>
<fo:external-graphic src="man.gif" content-height="150pt" />
</fo:block>
<fo:block>Hello, Tom!</fo:block><fo:block>Hello, Dick!</fo:block>
<fo:block>Hello, Harry!</fo:block><fo:block>Hello, Mick!</fo:block>… <fo:block>Hello, Mick!</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
Graphic inclusion, example 1 (contd.)
• Image in default position, at start/left side of block
Graphic inclusion, example 2
<?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="ordinaryPage"page-width="21.0cm" pageheight="29.7cm“ margin-left="1.0cm" margin-right="2.0cm"margin-top="1.0cm" margin-bottom="2.0cm">
<fo:region-body margin-top="1.5cm" margin-bottom="1.5cm“ background-color="silver" />
<fo:region-before extent="1cm"/><fo:region-after extent="1cm"/></fo:simple-pagemaster></fo:layout-master-set>
<fo:page-sequence master-reference="ordinaryPage“ initial-page-number="1" format="1" >
<fo:static-content flow-name="xsl-region-before"><fo:block font-size="20pt">Greetings</fo:block> </fo:staticcontent>
<fo:static-content flow-name="xsl-region-after"><fo:block font-size="20pt">Page <fo:pagenumber/></fo:block></fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block text-align="end”>
<fo:external-graphic src="man.gif" content-height="150pt" />
</fo:block>
<fo:block>Hello, Tom!</fo:block><fo:block>Hello, Dick!</fo:block>
<fo:block>Hello, Harry!</fo:block><fo:block>Hello, Mick!</fo:block>… <fo:block>Hello, Mick!</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
Graphic inclusion, example 2 (contd.)
• Image aligned to end/right side of block
Images: floating
• The definition of XSL-FO includes various
elements and attributes which are
designed for floating parts of a document
• Unfortunately, these are not implemented
in Apache FOP at present
• So, if you really want to wrap text around
an image you must emulate floating by
using tables or by using negative spacebefore
Graphic inclusion, example 3
<?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="ordinaryPage"page-width="21.0cm" page-height="29.7cm“ margin-left="1.0cm" marginright="2.0cm"margin-top="1.0cm" margin-bottom="2.0cm">
<fo:region-body margin-top="1.5cm" margin-bottom="1.5cm“ background-color="silver" />
<fo:region-before extent="1cm"/><fo:region-after extent="1cm"/></fo:simple-page-master></fo:layout-master-set>
<fo:page-sequence master-reference="ordinaryPage“ initial-page-number="1" format="1" >
<fo:static-content flow-name="xsl-region-before"><fo:block font-size="20pt">Greetings</fo:block> </fo:static-content>
<fo:static-content flow-name="xsl-region-after"><fo:block font-size="20pt">Page <fo:page-number/></fo:block></fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block
text-align="end”>
<fo:external-graphic src="man.gif" content-height=“75pt" />
</fo:block>
<fo:block space-before=“-75pt" margin-right="80pt">
This is a sentence. This is another sentence. This is another sentence.
And this is another sentence. … And this is another sentence.</fo:block>
<fo:block>Hello, Tom!</fo:block>
<fo:block>Hello, Dick!</fo:block>
<fo:block>Hello, Harry!</fo:block>
<fo:block>Hello, Mick!</fo:block>
<fo:block>Hello, Tom!</fo:block><fo:block>Hello, Dick!</fo:block>
<fo:block>Hello, Harry!</fo:block><fo:block>Hello, Mick!</fo:block>… <fo:block>Hello, Mick!</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
Graphic inclusion, example 3 (contd.)
• Negative space-before used to make text blocks “wrap” around
image
Hotlinks
Hotlinks
• Hotlinks can be created by using the fo:basic-link element
• Its specification in the unofficial DTD is
<!ELEMENT fo:basic-link ( %mixed-level; )* >
<!ATTLIST fo:basic-link
%inline-properties;
external-destination CDATA #IMPLIED
internal-destination CDATA #IMPLIED
indicate-destination ( true | false ) #IMPLIED
show-destination ( replace | new ) #IMPLIED
destination-placement-offset CDATA #IMPLIED
target-processing-context CDATA #IMPLIED
target-presentation-context CDATA #IMPLIED
target-stylesheet CDATA #IMPLIED >
• Either the external-destination and internal-destination should be
specified.
– If both are specified, the system may either report an error or
use the internal-destination property
Hotlinks, example 1
<?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="ordinaryPage"page-width="21.0cm" page-height="29.7cm“ margin-left="1.0cm" marginright="2.0cm"margin-top="1.0cm" margin-bottom="2.0cm">
<fo:region-body margin-top="1.5cm" margin-bottom="1.5cm“ background-color="silver" />
<fo:region-before extent="1cm"/><fo:region-after extent="1cm"/></fo:simple-page-master></fo:layout-master-set>
<fo:page-sequence master-reference="ordinaryPage“ initial-page-number="1" format="1" >
<fo:static-content flow-name="xsl-region-before"><fo:block font-size="20pt">Greetings</fo:block> </fo:static-content>
<fo:static-content flow-name="xsl-region-after"><fo:block font-size="20pt">Page <fo:page-number/></fo:block></fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block>
<fo:basic-link internal-destination="endOfText">
Click-here-to-go-to-the-end-of-the-text
</fo:basic-link>
<fo:basic-link external-destination=“url('http://www.ucc.ie')">
Click-here-to-go-to-the-UCC-website
</fo:basic-link>
</fo:block>
<fo:block text-align="end”><fo:external-graphic src="man.gif" content-height=“75pt" /></fo:block>
<fo:block space-before=“-75pt" margin-right="80pt">This is a sentence. This is another sentence. This is another sentence. And this is another sentence. … And this is
another sentence.</fo:block> <fo:block>Hello, Tom!</fo:block>
<fo:block>Hello, Dick!</fo:block><fo:block>Hello, Harry!</fo:block><fo:block>Hello, Mick!</fo:block>
<fo:block>Hello, Tom!</fo:block><fo:block>Hello, Dick!</fo:block>
<fo:block>Hello, Harry!</fo:block><fo:block>Hello, Mick!</fo:block>…
<fo:block id=“endOfText”>Hello, Mick!</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
Hotlinks example 1 (contd.)
• Notice how the areas generated by the fo:basic-link elements
- are inline areas and
- have no decoration
Hotlinks, example 2 – highlighting links
Hotlinks, example 2 – highlighting links
<?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="ordinaryPage"page-width="21.0cm" page-height="29.7cm“ margin-left="1.0cm" marginright="2.0cm"margin-top="1.0cm" margin-bottom="2.0cm">
<fo:region-body margin-top="1.5cm" margin-bottom="1.5cm“ background-color="silver" />
<fo:region-before extent="1cm"/><fo:region-after extent="1cm"/></fo:simple-page-master></fo:layout-master-set>
<fo:page-sequence master-reference="ordinaryPage“ initial-page-number="1" format="1" >
<fo:static-content flow-name="xsl-region-before"><fo:block font-size="20pt">Greetings</fo:block> </fo:static-content>
<fo:static-content flow-name="xsl-region-after"><fo:block font-size="20pt">Page <fo:page-number/></fo:block></fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block>
<fo:basic-link color="blue" text-decoration="underline"
internal-destination="endOfText">
Click here to go to the end of the text
</fo:basic-link>
<fo:basic-link color="blue" text-decoration="underline"
external-destination=“url('http://www.ucc.ie')">
Click here to go to the UCC website
</fo:basic-link>
</fo:block>
<fo:block text-align="end”><fo:external-graphic src="man.gif" content-height=“75pt" /></fo:block>
<fo:block space-before=“-75pt" margin-right="80pt">This is a sentence. This is another sentence. This is another sentence. And this is another sentence. … And this is
another sentence.</fo:block> <fo:block>Hello, Tom!</fo:block>
<fo:block>Hello, Dick!</fo:block><fo:block>Hello, Harry!</fo:block><fo:block>Hello, Mick!</fo:block>
<fo:block>Hello, Tom!</fo:block><fo:block>Hello, Dick!</fo:block>
<fo:block>Hello, Harry!</fo:block><fo:block>Hello, Mick!</fo:block>…
<fo:block id=“endOfText”>Hello, Mick!</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
Hotlinks example 2 (contd.)
• The appearance of links below is like the default in HTML
• However, we can specify a completely different appearance if we
wish
Tables
HTML versus FO tables
• HTML tables have this hierarchy
<table>
<caption>
<colgroup>
<col>
<thead>
<tr>
<th>
<tbody>
<tr>
<td>
<tfoot>
<tr>
<td>
• XSL-FO tables have this hierarchy
<fo:table-and-caption>
<fo:table-caption>
<fo:table>
<fo:table-column>
<fo:table-header>
<fo:table-row>
<fo:table-cell>
<fo:table-body>
<fo:table-row>
<fo:table-cell>
<fo:table-footer>
<fo:table-row>
<fo:table-cell>
Example table
<fo:table table-layout="fixed" border-width="1px" border-style="solid">
<fo:table-column column-width="3cm"/>
<fo:table-column column-width="3cm"/>
<fo:table-column column-width="3cm"/>
<fo:table-header text-align="center" background-color="red">
<fo:table-row>
<fo:table-cell padding="1mm" border-width="1px" border-style="solid"><fo:block font-weight="bold">City</fo:block></fo:table-cell>
<fo:table-cell padding="1mm" border-width="1px" border-style="solid"><fo:block font-weight="bold">Location</fo:block></fo:table-cell>
<fo:table-cell padding="1mm" border-width="1px" border-style="solid"><fo:block font-weight="bold">Population</fo:block></fo:table-cell>
</fo:table-row>
</fo:table-header>
<fo:table-body background-color="blue">
<fo:table-row>
<fo:table-cell padding="1mm" border-width="1px" border-style="solid"><fo:block>Dublin</fo:block></fo:table-cell>
<fo:table-cell padding="1mm" border-width="1px" border-style="solid"><fo:block>East coast</fo:block></fo:table-cell>
<fo:table-cell padding="1mm" border-width="1px" border-style="solid"><fo:block>1,200,00</fo:block></fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell padding="1mm" border-width="1px" border-style="solid"><fo:block>Cork</fo:block></fo:table-cell>
<fo:table-cell padding="1mm" border-width="1px" border-style="solid"><fo:block>South coast</fo:block></fo:table-cell>
<fo:table-cell padding="1mm" border-width="1px" border-style="solid"><fo:block>200,000</fo:block></fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
The result
Table properties
<!ENTITY % table-properties "
border-collapse ( collapse | separate | inherit ) #IMPLIED
border-spacing CDATA #IMPLIED
border-separation CDATA #IMPLIED
border-separation.inline-progression-dimension CDATA #IMPLIED
border-separation.block-progression-dimension CDATA #IMPLIED
caption-side
( before | after | start | end | top | bottom | left | right | inherit ) #IMPLIED
empty-cells ( show | hide | inherit ) #IMPLIED
table-layout ( auto | fixed | inherit ) #IMPLIED
table-omit-header-at-break ( true | false | inherit ) #IMPLIED
table-omit-footer-at-break ( true | false | inherit ) #IMPLIED
">
Lists
Lists
• We create lists using the fo:list-block element
• Its specification in the unofficial DTD
<!ELEMENT fo:list-block ( fo:list-item+ ) >
<!ATTLIST fo:list-block %block-properties;>
• The specification for the fo:list-item is
<!ELEMENT fo:list-item ( fo:list-item-label, fo:list-item-body ) >
<!ATTLIST fo:list-item %block-properties;>
• The specification for the fo:list-item-label is
<!ELEMENT fo:list-item-label ( %blocks; )+ >
<!ATTLIST fo:list-item-label %block-properties;>
• The specification for the fo:list-item-body is
<!ELEMENT fo:list-item-body ( %blocks;)+ >
<!ATTLIST fo:list-item-body %block-properties;>
List, example 1
• Here is a simple list
List, example 1
• Here is a simple list
<fo:list-block>
<fo:list-item>
<fo:list-item-label>
<fo:block>1</fo:block>
</fo:list-item-label>
<fo:list-item-body>
<fo:block>Hello Tom!</fo:block>
</fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label><fo:block>2</fo:block></fo:list-item-label>
<fo:list-item-body><fo:block>Hello Dick!</fo:block></fo:list-item-body>
</fo:list-item>
</fo:list-block>
List, example 1
• Here is a simple list
• However, it is too simple, as the next slide shows
<fo:list-block>
<fo:list-item>
<fo:list-item-label>
<fo:block>1</fo:block>
</fo:list-item-label>
<fo:list-item-body>
<fo:block>Hello Tom!</fo:block>
</fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label><fo:block>2</fo:block></fo:list-item-label>
<fo:list-item-body><fo:block>Hello Dick!</fo:block></fo:list-item-body>
</fo:list-item>
</fo:list-block>
The layout is wrong
The layout is wrong
What's wrong?
• There are some attributes whose values we must
consider
• Before we continue with lists, we should look
again at the attributes that are defined for blocks
Block attributes (revisited)
• Here, again, are the block attributes in the unofficial DTD
<!ATTLIST fo:block %block-properties;>
<!ENTITY % block-properties "
id CDATA #IMPLIED
%inheritable-properties; ">
<!ENTITY % inheritable-properties "
color CDATA #IMPLIED
relative-align ( before | baseline | inherit ) #IMPLIED
span ( none | all | inherit ) #IMPLIED
%accessibility-properties;
%absolute-or-relative-position-properties;
%border-padding-background-properties;
%border-precedence-properties;
%aural-properties;
%box-size-properties;
%margin-properties-inline;
%area-properties;
%area-alignment-properties-inline;
%character-properties;
%table-properties;
%list-properties;
%float-properties;
%line-related-properties;
%leader-properties;
%keeps-and-breaks-properties-block;
%hyphenation-properties-block;
%visibility-properties;
">
margin-properties-inline
<!ENTITY % margin-properties-inline "
%margin-properties-block;
space-start CDATA #IMPLIED
space-start.minimum CDATA #IMPLIED
space-start.optimum CDATA #IMPLIED
space-start.maximum CDATA #IMPLIED
space-start.precedence CDATA #IMPLIED
space-start.conditionality ( retain | discard ) #IMPLIED
space-end CDATA #IMPLIED
space-end.minimum CDATA #IMPLIED
space-end.optimum CDATA #IMPLIED
space-end.maximum CDATA #IMPLIED
space-end.precedence CDATA #IMPLIED
space-end.conditionality ( retain | discard ) #IMPLIED ">
margin-properties-block
<!ENTITY % margin-properties-block "
%margin-properties-CSS;
space-after CDATA #IMPLIED
space-after.minimum CDATA #IMPLIED
space-after.optimum CDATA #IMPLIED
space-after.maximum CDATA #IMPLIED
space-after.precedence CDATA #IMPLIED
space-after.conditionality ( retain | discard ) #IMPLIED
space-before CDATA #IMPLIED
space-before.minimum CDATA #IMPLIED
space-before.optimum CDATA #IMPLIED
space-before.maximum CDATA #IMPLIED
space-before.precedence CDATA #IMPLIED
space-before.conditionality ( retain | discard ) #IMPLIED
start-indent CDATA #IMPLIED
end-indent CDATA #IMPLIED ">
start-indent and end-indent
•
•
The start-indent attribute of a block-area specifies
the distance from
the start-edge of the content-rectangle of the containing reference-area
to
the start-edge of the content-rectangle of the block-area
The end-indent attribute of a block-area specifies
the distance from
the end-edge of the content-rectangle of the containing reference-area
to
the end-edge of the content-rectangle of the block-area
start-indent, example
<?xml version="1.0" encoding="UTF-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>...</fo:layout-master-set>
<fo:page-sequence master-reference="ordinaryPage"
initial-page-number="1" format="1" >
<fo:static-content flow-name="xsl-region-before">
<fo:block font-size="20pt">Greetings</fo:block>
</fo:static-content>
<fo:static-content flow-name="xsl-region-after">
<fo:block font-size="20pt">Page <fo:page-number/>
</fo:block>
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block>
This is an example sentence.
</fo:block>
<fo:block start-indent="1cm">
This is another example sentence.
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
end-indent, example
<?xml version="1.0" encoding="UTF-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>...</fo:layout-master-set>
<fo:page-sequence master-reference="ordinaryPage"
initial-page-number="1" format="1" >
<fo:static-content flow-name="xsl-region-before">
<fo:block font-size="20pt">Greetings</fo:block></fo:static-content>
<fo:static-content flow-name="xsl-region-after">
<fo:block font-size="20pt">Page <fo:page-number/>
</fo:block></fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block>
This is an example paragraph....This
is an example paragraph.
</fo:block>
<fo:block background-color="red"
start-indent="1cm"
end-indent="1cm">
This is yet another example
paragraph. ...This is yet another
example paragraph.
</fo:block>
</fo:flow></fo:page-sequence></fo:root>
Indents for for list item labels and bodies
• The labels and bodies of list item can have
indents
• This gives us four attributes for controlling layout
Example, to motivate producing "definition lists"
•
Suppose we want to render some of its content as an XSL-FO list which
looks like a HTML definition list
Example, to motivate producing "definition lists"
• Consider this XML document
•
Suppose we want to render some of its content as an XSL-FO list which
looks like a HTML definition list
Example, to motivate producing "definition lists"
• Consider this XML document
•
Suppose we want to render some of its content as an XSL-FO list which
looks like a HTML definition list
<towns>
<town>
<name>Dublin</name>
<location>East coast of Ireland</location>
<population>1,200,000</population>
</town>
<town>
<name>Cork</name>
<location>South coast of Ireland</location>
<population>200,000</population>
</town>
</towns>
Example, to motivate producing "definition lists"
• Consider this XML document
•
Suppose we want to render some of its content as an XSL-FO list which
looks like a HTML definition list
<towns>
<town>
<name>Dublin</name>
<location>East coast of Ireland</location>
<population>1,200,000</population>
</town>
<town>
<name>Cork</name>
<location>South coast of Ireland</location>
<population>200,000</population>
</town>
</towns>
Example, using FO lists to produce "definition lists"
<fo:flow flow-name="xsl-region-body">
<fo:block>Dublin</fo:block>
<fo:list-block>
<fo:list-item>
<fo:list-item-label><fo:block> location: </fo:block></fo:list-item-label>
<fo:list-item-body><fo:block> East coast of Ireland </fo:block></fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label><fo:block> population: </fo:block> </fo:list-item-label>
<fo:list-item-body><fo:block> 1,200,000 </fo:block></fo:list-item-body>
</fo:list-item>
</fo:list-block>
<fo:block>Cork</fo:block>
<fo:list-block>
<fo:list-item>
<fo:list-item-label"><fo:block> location: </fo:block></fo:list-item-label>
<fo:list-item-body"><fo:block> South coast of Ireland </fo:block></fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label><fo:block> population: </fo:block></fo:list-item-label>
<fo:list-item-body><fo:block> 200,000 </fo:block></fo:list-item-body>
</fo:list-item>
</fo:list-block>
</fo:flow>
Poor layout
Poor layout
"Definition" lists example (contd.)
• Let's add some background-color, to help see where we are
<fo:flow flow-name="xsl-region-body">
<fo:block>Dublin</fo:block>
<fo:list-block start-indent="1cm" end-indent="1cm" background-color="red" >
<fo:list-item>
<fo:list-item-label><fo:block> location: </fo:block></fo:list-item-label>
<fo:list-item-body><fo:block> East coast of Ireland </fo:block></fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label><fo:block> population: </fo:block> </fo:list-item-label>
<fo:list-item-body><fo:block> 1,200,000 </fo:block></fo:list-item-body>
</fo:list-item>
</fo:list-block>
<fo:block>Cork</fo:block>
<fo:list-block start-indent="1cm" end-indent="1cm" background-color="red" >
<fo:list-item>
<fo:list-item-label"><fo:block> location: </fo:block></fo:list-item-label>
<fo:list-item-body"><fo:block> South coast of Ireland </fo:block></fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label><fo:block> population: </fo:block></fo:list-item-label>
<fo:list-item-body><fo:block> 200,000 </fo:block></fo:list-item-body>
</fo:list-item>
</fo:list-block>
</fo:flow>
"Definition" lists example (contd.)
• Let's add some background-color, to help see where we are
<fo:flow flow-name="xsl-region-body">
<fo:block>Dublin</fo:block>
<fo:list-block start-indent="1cm" end-indent="1cm" background-color="red" >
<fo:list-item>
<fo:list-item-label><fo:block> location: </fo:block></fo:list-item-label>
<fo:list-item-body><fo:block> East coast of Ireland </fo:block></fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label><fo:block> population: </fo:block> </fo:list-item-label>
<fo:list-item-body><fo:block> 1,200,000 </fo:block></fo:list-item-body>
</fo:list-item>
</fo:list-block>
<fo:block>Cork</fo:block>
<fo:list-block start-indent="1cm" end-indent="1cm" background-color="red" >
<fo:list-item>
<fo:list-item-label"><fo:block> location: </fo:block></fo:list-item-label>
<fo:list-item-body"><fo:block> South coast of Ireland </fo:block></fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label><fo:block> population: </fo:block></fo:list-item-label>
<fo:list-item-body><fo:block> 200,000 </fo:block></fo:list-item-body>
</fo:list-item>
</fo:list-block>
</fo:flow>
The red areas are the list-blocks
"Definition" lists example (contd.)
• We can avoid the overlap by giving a start-indent to the bodies
<fo:flow flow-name="xsl-region-body">
<fo:block>Dublin</fo:block>
<fo:list-block start-indent="1cm" end-indent="1cm" background-color="red" >
<fo:list-item>
<fo:list-item-label><fo:block> location: </fo:block></fo:list-item-label>
<fo:list-item-body start-indent="4cm"> <fo:block> East coast of Ireland </fo:block></fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label><fo:block> population: </fo:block> </fo:list-item-label>
<fo:list-item-body start-indent="4cm"><fo:block> 1,200,000 </fo:block></fo:list-item-body>
</fo:list-item>
</fo:list-block>
<fo:block>Cork</fo:block>
<fo:list-block start-indent="1cm" end-indent="1cm" background-color="red" >
<fo:list-item>
<fo:list-item-label"><fo:block> location: </fo:block></fo:list-item-label>
<fo:list-item-body start-indent="4cm"> <fo:block> South coast of Ireland </fo:block></fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label><fo:block> population: </fo:block></fo:list-item-label>
<fo:list-item-body start-indent="4cm"> <fo:block> 200,000 </fo:block></fo:list-item-body>
</fo:list-item>
</fo:list-block>
</fo:flow>
"Definition" lists example (contd.)
• We can avoid the overlap by giving a start-indent to the bodies
<fo:flow flow-name="xsl-region-body">
<fo:block>Dublin</fo:block>
<fo:list-block start-indent="1cm" end-indent="1cm" background-color="red" >
<fo:list-item>
<fo:list-item-label><fo:block> location: </fo:block></fo:list-item-label>
<fo:list-item-body start-indent="2cm"> <fo:block> East coast of Ireland </fo:block></fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label><fo:block> population: </fo:block> </fo:list-item-label>
<fo:list-item-body start-indent="2cm"><fo:block> 1,200,000 </fo:block></fo:list-item-body>
</fo:list-item>
</fo:list-block>
<fo:block>Cork</fo:block>
<fo:list-block start-indent="1cm" end-indent="1cm" background-color="red" >
<fo:list-item>
<fo:list-item-label"><fo:block> location: </fo:block></fo:list-item-label>
<fo:list-item-body start-indent="2cm"> <fo:block> South coast of Ireland </fo:block></fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label><fo:block> population: </fo:block></fo:list-item-label>
<fo:list-item-body start-indent="2cm"> <fo:block> 200,000 </fo:block></fo:list-item-body>
</fo:list-item>
</fo:list-block>
</fo:flow>
A bit better, but not good enough
• Before
• After
"Definition" lists example (contd.)
• To avoid overlap, the bodies need a bigger start-indent
<fo:flow flow-name="xsl-region-body">
<fo:block>Dublin</fo:block>
<fo:list-block start-indent="1cm" end-indent="1cm" background-color="red" >
<fo:list-item>
<fo:list-item-label><fo:block> location: </fo:block></fo:list-item-label>
<fo:list-item-body start-indent="4cm"> <fo:block> East coast of Ireland </fo:block></fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label><fo:block> population: </fo:block> </fo:list-item-label>
<fo:list-item-body start-indent="4cm"><fo:block> 1,200,000 </fo:block></fo:list-item-body>
</fo:list-item>
</fo:list-block>
<fo:block>Cork</fo:block>
<fo:list-block start-indent="1cm" end-indent="1cm" background-color="red" >
<fo:list-item>
<fo:list-item-label"><fo:block> location: </fo:block></fo:list-item-label>
<fo:list-item-body start-indent="4cm"> <fo:block> South coast of Ireland </fo:block></fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label><fo:block> population: </fo:block></fo:list-item-label>
<fo:list-item-body start-indent="4cm"> <fo:block> 200,000 </fo:block></fo:list-item-body>
</fo:list-item>
</fo:list-block>
</fo:flow>
"Definition" lists example (contd.)
• To avoid overlap, the bodies need a bigger start-indent
<fo:flow flow-name="xsl-region-body">
<fo:block>Dublin</fo:block>
<fo:list-block start-indent="1cm" end-indent="1cm" background-color="red" >
<fo:list-item>
<fo:list-item-label><fo:block> location: </fo:block></fo:list-item-label>
<fo:list-item-body start-indent="4cm"> <fo:block> East coast of Ireland </fo:block></fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label><fo:block> population: </fo:block> </fo:list-item-label>
<fo:list-item-body start-indent="4cm"><fo:block> 1,200,000 </fo:block></fo:list-item-body>
</fo:list-item>
</fo:list-block>
<fo:block>Cork</fo:block>
<fo:list-block start-indent="1cm" end-indent="1cm" background-color="red" >
<fo:list-item>
<fo:list-item-label"><fo:block> location: </fo:block></fo:list-item-label>
<fo:list-item-body start-indent="4cm"> <fo:block> South coast of Ireland </fo:block></fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label><fo:block> population: </fo:block></fo:list-item-label>
<fo:list-item-body start-indent="4cm"> <fo:block> 200,000 </fo:block></fo:list-item-body>
</fo:list-item>
</fo:list-block>
</fo:flow>
No overlap, but perhaps the separation is too large?
Controlling layout of list items
• As we have seen, we can control the layout of list items
by specifying the required indents for the labels and
bodies of these items
• But this can require a lot of experimentation, especially
with "definition" lists
• XSL-FO provides two functions to reduce the work
• These are
– label-end(), used to compute the end-indent for labels
– body-start(), used to compute the start-indent for bodies
• Let's try using body-start
"Definition" lists example (contd.)
• Using body-start to set the start-indent for the list item bodies
<fo:flow flow-name="xsl-region-body">
<fo:block>Dublin</fo:block>
<fo:list-block start-indent="1cm" end-indent="1cm" background-color="red" >
<fo:list-item>
<fo:list-item-label><fo:block> location: </fo:block></fo:list-item-label>
<fo:list-item-body start-indent="body-start()"> <fo:block> East coast of Ireland </fo:block></fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label><fo:block> population: </fo:block> </fo:list-item-label>
<fo:list-item-body start-indent="body-start()">
<fo:block> 1,200,000 </fo:block></fo:list-item-body>
</fo:list-item>
</fo:list-block>
<fo:block>Cork</fo:block>
<fo:list-block start-indent="1cm" end-indent="1cm" background-color="red" >
<fo:list-item>
<fo:list-item-label"><fo:block> location: </fo:block></fo:list-item-label>
<fo:list-item-body start-indent="body-start()"> <fo:block> South coast of Ireland </fo:block></fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label><fo:block> population: </fo:block></fo:list-item-label>
<fo:list-item-body start-indent="body-start()"> <fo:block> 200,000 </fo:block></fo:list-item-body>
</fo:list-item>
</fo:list-block>
</fo:flow>
Better than nothing, but not good enough
• We need to use something else as well
Block attributes (revisited)
• Here, again, are the block attributes in the unofficial DTD
<!ATTLIST fo:block %block-properties;>
<!ENTITY % block-properties "
id CDATA #IMPLIED
%inheritable-properties; ">
<!ENTITY % inheritable-properties "
color CDATA #IMPLIED
relative-align ( before | baseline | inherit ) #IMPLIED
span ( none | all | inherit ) #IMPLIED
%accessibility-properties;
%absolute-or-relative-position-properties;
%border-padding-background-properties;
%border-precedence-properties;
%aural-properties;
%box-size-properties;
%margin-properties-inline;
%area-properties;
%area-alignment-properties-inline;
%character-properties;
%table-properties;
%list-properties;
%float-properties;
%line-related-properties;
%leader-properties;
%keeps-and-breaks-properties-block;
%hyphenation-properties-block;
%visibility-properties;
">
list-properties
• Here are the list-property attributes in the unofficial DTD
<!ENTITY % list-properties "
provisional-distance-between-starts CDATA #IMPLIED
provisional-label-separation CDATA #IMPLIED ">
• The values of these attributes are used by label-end() and bodystart()
• The initial value of provisional-label-separation is 6.0pt
• The initial value of provisional-distance-between-starts is 24.0pt
Computing label-end() and body-start()
•
label-end() =
width of the content-rectangle of the reference-area into which the list-block is placed
- (the value of the provisional-distance-between-starts
+ the value of the start-indent
+ start-intrusion-adjustment
- the value of the provisional-label-separation)
of the closest ancestor fo:list-block
•
body-start() =
the value of the start-indent
+ start-intrusion-adjustment
+ the value of the provisional-distance-between-starts
of the closest ancestor fo:list-block
"Definition" lists example (contd.)
• Setting provisional-distance-between-starts
<fo:flow flow-name="xsl-region-body">
<fo:block>Dublin</fo:block>
<fo:list-block start-indent="1cm" end-indent="1cm" background-color="red"
provisional-distance-between-starts="3cm" >
<fo:list-item>
<fo:list-item-label><fo:block> location: </fo:block></fo:list-item-label>
<fo:list-item-body start-indent="body-start()"> <fo:block> East coast of Ireland </fo:block></fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label><fo:block> population: </fo:block> </fo:list-item-label>
<fo:list-item-body start-indent="body-start()"> <fo:block> 1,200,000 </fo:block></fo:list-item-body>
</fo:list-item>
</fo:list-block>
<fo:block>Cork</fo:block>
<fo:list-block start-indent="1cm" end-indent="1cm" background-color="red"
provisional-distance-between-starts="3cm">
<fo:list-item>
<fo:list-item-label"><fo:block> location: </fo:block></fo:list-item-label>
<fo:list-item-body start-indent="body-start()"> <fo:block> South coast of Ireland </fo:block></fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label><fo:block> population: </fo:block></fo:list-item-label>
<fo:list-item-body start-indent="body-start()"> <fo:block> 200,000 </fo:block></fo:list-item-body>
</fo:list-item>
</fo:list-block>
</fo:flow>
The result
This works, but …
• The body-start() function worked but we still had to specify a value
for provisional-distance-between-starts
• The main advantage is that we did not need to specify this value in
each of the list item bodies
– We need to specify it only once for each list-block
• But we still had to decide what the value should be and this required
some experimentation, in order to find a distance which was long
enough to prevent overlap with the longest label
• It would be better if we could automatically compute the required
distance
• We can, indeed, automate the computation
• But it must be done in XSLT, at the time the XSL-FO document is
being generated
A digression, back to XSLT
Computing required provisional-distance-between-starts
for FO list blocks
• We need to compute a distance which will prevent
overlap with the longest list-item-label
• Since list-item-labels are derived from the tag names in
the source XML document, we need to compute the
length of the longest tag name
Example XML document
• Consider this XML document
• Suppose we want to automatically compute the length of the longest
tag name for the child elements of the <town> elements
• The XSLT stylesheet on the next slide will do it
<towns>
<town>
<name>Dublin</name>
<location>East coast of Ireland</location>
<population>1,200,000</population>
</town>
<town>
<name>Cork</name>
<location>South coast of Ireland</location>
<population>200,000</population>
</town>
</towns>
Example XML document
• Consider this XML document
• Suppose we want to automatically compute the length of the longest
tag name for the child elements of the <town> elements
• The XSLT stylesheet on the next slide will do it
<towns>
<town>
<name>Dublin</name>
<location>East coast of Ireland</location>
<population>1,200,000</population>
</town>
<town>
<name>Cork</name>
<location>South coast of Ireland</location>
<population>200,000</population>
</town>
</towns>
Example XML document
• Consider this XML document
• Suppose we want to automatically compute the length of the longest
tag name for the child elements of the <town> elements
• The XSLT stylesheet on the next slide will do it
<towns>
<town>
<name>Dublin</name>
<location>East coast of Ireland</location>
<population>1,200,000</population>
</town>
<town>
<name>Cork</name>
<location>South coast of Ireland</location>
<population>200,000</population>
</town>
</towns>
Example XML document
• Consider this XML document
• Suppose we want to automatically compute the length of the longest
tag name for the child elements of the <town> elements
• The XSLT stylesheet on the next slide will do it
<towns>
<town>
<name>Dublin</name>
<location>East coast of Ireland</location>
<population>1,200,000</population>
</town>
<town>
<name>Cork</name>
<location>South coast of Ireland</location>
<population>200,000</population>
</town>
</towns>
XSL stylesheet to compute longest tagname
<?xml version="1.0"?>
<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>
<!-- We need look at only the first town -->
<xsl:apply-templates select="./towns/town[position()=1]“ />
</fo:root>
</xsl:template>
<!-- Sort the children of the town by descending length of tagname and
output the length of the tagname of the first member of the sorted list -->
<xsl:template match="town">
<xsl:for-each select="./*">
<xsl:sort select="string-length(name())" order="descending"/>
<xsl:if test="position()=1">maxLabelLength=<xsl:value-of select="string-length(name())"/></xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Unfortunately, …
•
•
•
•
Unfortunately, there is a problem
Apache FOP seems to have a bug in it
The stylesheet shown on the previous slide is correct
We can see this if we execute the stylesheet with
another XSLT processor, the Saxon processor
http://saxon.sourceforge.net/
• But Apache FOP does not execute it correctly
• We will see this on the next few slides
Executing the stylesheet with Apache FOP
• Assume the XML document is in a file called towns.xml
• Assume the XSLT stylesheet is in a file called towns.xsl
• Use Apache FOP to place the output in a file called towns.fo
fop -xml towns.xml -xsl towns.xsl -foout towns.fo
• The resultant content in towns.fo is
<?xml version="1.0" encoding="UTF-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">maxLabelLength=8</fo:root>
•
•
•
•
But this is wrong
The longest tagname is population, which is 10 characters long
However, there is nothing wrong with the stylesheet, as we can see if we
execute it with the Saxon processor
The result is shown on the next slide
Executing the stylesheet with Saxon
• Again, assume the XML document is in a file called towns.xml
• Again, assume the XSLT stylesheet is in a file called towns.xsl
• Use Saxon to place the output in a file called towns.fo
java -jar /usr/local/saxon/saxon9he.jar towns.xml towns.xsl > towns.fo
• The resultant content in towns.fo is
<?xml version="1.0" encoding="UTF-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">maxLabelLength=10</fo:root>
•
•
This is correct
The longest tagname is population, which is 10 characters long
Using both Saxon and FOP
• Since there is an error in FOP, we could use Saxon and FOP
together
• We could Saxon to generate an XSL-FO file from an XML file and an
XSLT file
java -jar /usr/local/saxon/saxon9he.jar towns.xml towns.xsl > towns.fo
• We could then use Apache FOP to generate a PDF file from the
XSL-FO file which was created by Saxon
fop -fo towns.fo -pdf towns.pdf
Back to generating XSL-FO
lists
A stylesheet which calculates the max label length
• The next two slides provide an XSLT stylesheet which calculates the
number of characters in the longest tagname
• It then specifies that number of em units as the provisional distance
between starts
• The stylesheet uses three templates
– One template generates the top-level structure of the XSL-FO
document and calls a template which generates the XSL-FO
output for each individual town
– The template which generates the XSL-FO output for an
individual town uses a third template to determine the provisional
distance between starts which should be used in the list block for
the town
– The third template examines the does not consider the <name>
child when trying to determine the length of the longest child tag
– Note that the second and third templates both match <town>
elements, but are distinguished from each other by having
different mode attritbutes
A stylesheet which calculates the max label length
• The next two slides provide an XSLT stylesheet which calculates the
number of characters in the longest tagname
• It then specifies that number of em units as the provisional distance
between starts
• The stylesheet uses three templates
– One template generates the top-level structure of the XSL-FO
document and calls a template which generates the XSL-FO
output for each individual town
– The template which generates the XSL-FO output for an
individual town uses a third template to determine the provisional
distance between starts which should be used in the list block for
the town
– The third template examines the does not consider the <name>
child when trying to determine the length of the longest child tag
– Note that the second and third templates both match <town>
elements, but are distinguished from each other by having
different mode attritbutes
A stylesheet which calculates the max label length
• The next two slides provide an XSLT stylesheet which calculates the
number of characters in the longest tagname
• It then specifies that number of em units as the provisional distance
between starts
• The stylesheet uses three templates
– One template generates the top-level structure of the XSL-FO
document and calls a template which generates the XSL-FO
output for each individual town
– The template which generates the XSL-FO output for an
individual town uses a third template to determine the provisional
distance between starts which should be used in the list block for
the town
– The third template examines the does not consider the <name>
child when trying to determine the length of the longest child tag
– Note that the second and third templates both match <town>
elements, but are distinguished from each other by having
different mode attritbutes
A stylesheet which calculates the max label length
• The next two slides provide an XSLT stylesheet which calculates the
number of characters in the longest tagname
• It then specifies that number of em units as the provisional distance
between starts
• The stylesheet uses three templates
– One template generates the top-level structure of the XSL-FO
document and calls a template which generates the XSL-FO
output for each individual town
– The template which generates the XSL-FO output for an
individual town uses a third template to determine the provisional
distance between starts which should be used in the list block for
the town
– The third template examines the does not consider the <name>
child when trying to determine the length of the longest child tag
– Note that the second and third templates both match <town>
elements, but are distinguished from each other by having
different mode attritbutes
A stylesheet which calculates the max label length
• The next two slides provide an XSLT stylesheet which calculates the
number of characters in the longest tagname
• It then specifies that number of em units as the provisional distance
between starts
• The stylesheet uses three templates
– One template generates the top-level structure of the XSL-FO
document and calls a template which generates the XSL-FO
output for each individual town
– The template which generates the XSL-FO output for an
individual town uses a third template to determine the provisional
distance between starts which should be used in the list block for
the town
– The third template examines the does not consider the <name>
child when trying to determine the length of the longest child tag
– Note that the second and third templates both match <town>
elements, but are distinguished from each other by having
different mode attritbutes
Stylesheet, page 1
<?xml version="1.0"?>
<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="ordinaryPage“ page-width="21.0cm" page-height="29.7cm"
margin-left="4.5cm" margin-right="1.0cm“ margin-top="1.0cm" margin-bottom="1.0cm">
<fo:region-body margin-top="1.5cm" margin-bottom="1.5cm background-color="silver" />
<fo:region-before extent="1cm"/> <fo:region-after extent="1cm"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="ordinaryPage“ initial-page-number="1" format="1" >
<fo:static-content flow-name="xsl-region-before"><fo:block font-size="20pt">Towns</fo:block></fo:static-content>
<fo:static-content flow-name="xsl-region-after"><fo:block font-size="20pt">Page <fo:pagenumber/></fo:block></fo:static-content>
<fo:flow flow-name="xsl-region-body">
<!– process each town using the template for outputFO mode -->
<xsl:apply-templates select="./towns/town" mode="outputFO“ />
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
Stylesheet, page 2
<xsl:template match="town" mode="outputFO" >
<fo:block><xsl:value-of select="name"/></fo:block>
<fo:list-block>
<xsl:attribute name="provisional-distance-between-starts">
<xsl:apply-templates select="." mode="getMaxLabel" />em
</xsl:attribute>
<xsl:for-each select="./*[not(name()='name')]">
<fo:list-item>
<fo:list-item-label> <fo:block> <xsl:value-of select="name()"/>: </fo:block> </fo:list-item-label>
<fo:list-item-body start-indent="body-start()">
<fo:block> <xsl:value-of select="."/> </fo:block>
</fo:list-item-body>
</fo:list-item>
</xsl:for-each>
</fo:list-block>
</xsl:template>
<xsl:template match="town" mode="getMaxLabel" >
<xsl:for-each select="./*[not(name()='name')]">
<xsl:sort select="string-length(name())" order="descending"/>
<xsl:if test="position()=1"><xsl:value-of select="string-length(name())"/></xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
The resultant output
•
•
•
•
Use Saxon to get the XSL-FO output
Use fop to process the XSL-FO into PDF
The result is shown below
The separation is too long because we are using em units and this
produces a length greater than that actually rendered for proportional
fonts, in which different letters have different widths
– Some people have introduced extensions to XSLT processors like Saxon
in order to better estimate the actual rendered length of text
– See, for example,
http://www.innodata-isogen.com/knowledge_center/tools_downloads/saxon_extensions
Another stylesheet which calculates max label length
• The next two slides provide a different XSLT stylesheet which calculates
the number of characters in the longest tagname
• It differs from the previous one in that it assumes that all towns have the
same set of child elements
– so the length of the longest child tagname need be calculated only once, for
the first town
• The stylesheet uses three templates
• One template generates the top-level structure of the XSL-FO document
• This calls another template which examines the first town, to get the
length of the longest child tagname
• Then it calls yet another template which generates the XSL-FO output
for each individual town
• This stylesheet actually generates exactly the same XSL-FO as the
previous one
• The only difference is that it calculates the length of the provisional
distance between starts just once, puts this value in a variable and
passes it as a parameter to the template which processes individual
towns
Another stylesheet which calculates max label length
<?xml version="1.0"?>
<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="ordinaryPage“ page-width="21.0cm" page-height="29.7cm"
margin-left="4.5cm" margin-right="1.0cm“ margin-top="1.0cm" margin-bottom="1.0cm">
<fo:region-body margin-top="1.5cm" margin-bottom="1.5cm background-color="silver" />
<fo:region-before extent="1cm"/> <fo:region-after extent="1cm"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="ordinaryPage“ initial-page-number="1" format="1" >
<fo:static-content flow-name="xsl-region-before"><fo:block font-size="20pt">Towns</fo:block></fo:static-content>
<fo:static-content flow-name="xsl-region-after"><fo:block font-size="20pt">Page <fo:pagenumber/></fo:block></fo:static-content>
<fo:flow flow-name="xsl-region-body">
<xsl:variable name="provisional-distance">
<!-- compute provisional separation between starts by looking at first town -->
<xsl:apply-templates select="./towns/town[position()=1]" mode="getMaxLabel"/>em</xsl:variable>
<xsl:apply-templates select="./towns/town" mode="outputFO">
<xsl:with-param name="provisional" select="$provisional-distance" />
</xsl:apply-templates>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
Another stylesheet which calculates max label length
<xsl:template match="town" mode="outputFO" >
<xsl:param name="provisional-distance"/>
<fo:block><xsl:value-of select="name"/></fo:block>
<fo:list-block>
<xsl:attribute name="provisional-distance-between-starts">
<xsl:value-of select="$provisional-distance"/>
</xsl:attribute>
<xsl:for-each select="./*[not(name()='name')]">
<fo:list-item>
<fo:list-item-label> <fo:block> <xsl:value-of select="name()"/>: </fo:block> </fo:list-item-label>
<fo:list-item-body start-indent="body-start()">
<fo:block> <xsl:value-of select="."/> </fo:block>
</fo:list-item-body>
</fo:list-item>
</xsl:for-each>
</fo:list-block>
</xsl:template>
<xsl:template match="town" mode="getMaxLabel" >
<xsl:for-each select="./*[not(name()='name')]">
<xsl:sort select="string-length(name())" order="descending"/>
<xsl:if test="position()=1"><xsl:value-of select="string-length(name())"/></xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Bulleted lists
"Bulleted" lists example
• Just using body-start; no usage of provisional-distance-between-starts
<fo:flow flow-name="xsl-region-body">
<fo:block>Dublin</fo:block>
<fo:list-block start-indent="1cm" end-indent="1cm" background-color="red">
<fo:list-item>
<fo:list-item-label><fo:block> • </fo:block></fo:list-item-label>
<fo:list-item-body start-indent=" body-start() "> <fo:block>Location: East coast of Ireland </fo:block></fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label><fo:block> • </fo:block> </fo:list-item-label>
<fo:list-item-body start-indent=" body-start() "> <fo:block>Population: 1,200,000 </fo:block></fo:list-item-body>
</fo:list-item>
</fo:list-block>
<fo:block>Cork</fo:block>
<fo:list-block start-indent="1cm" end-indent="1cm" background-color="red">
<fo:list-item>
<fo:list-item-label"><fo:block> • </fo:block></fo:list-item-label>
<fo:list-item-body start-indent=" body-start() "> <fo:block>Location: South coast of Ireland </fo:block></fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label><fo:block> • </fo:block></fo:list-item-label>
<fo:list-item-body start-indent=" body-start() "> <fo:block>Population: 200,000 </fo:block></fo:list-item-body>
</fo:list-item>
</fo:list-block>
</fo:flow>
The result
A useful website
• See
http://www.stylusstudio.com/w3c/xslfo/
Download