Blocks and Inlines
- To format blocks of content.
- To format inline text.
- To work with lists.
- To work with whitespace.
Formatting Blocks
Although the output of our Winnie the Pooh story from the previous lesson is readable, it isn't formatted very nicely. In this section, we'll examine how we can use Cascading Style Sheet (CSS) properties to apply formatting to block FOs.
Box Model
Before we look at the specific attributes for formatting blocks, we'll take a look at a diagram that illustrates how width, border, padding and indent attributes all fit together.
The diagram shows two block elements in a block-container, which has a width of one inch. Each block contains a single word.
- Padding is used to create one inch of space between the content and the edge of the box.
- A one-centimeter border is then added to the edge of each block.
- The bottom block is indented half an inch from the left.
Now let's look at some of the attributes of block FOs.
Border
By default, block FOs have no border; however, you can easily add one with the border-style and border-width attributes. You can also change the border color with the border-color attribute. As the table below shows, these properties can be applied to portions of the border as well through the use of more specific attributes.
| Attribute | Values |
|---|---|
| border-width |
|
| border-top-width | Same as border-width. |
| border-bottom-width | Same as border-width. |
| border-left-width | Same as border-width. |
| border-right-width | Same as border-width. |
| border-color | <color> |
| border-top-color | <color> |
| border-bottom-color | <color> |
| border-left-color | <color> |
| border-right-color | <color> |
| border-style |
|
| border-top-style | Same as border-style. |
| border-bottom-style | Same as border-style. |
| border-left-style | Same as border-style. |
| border-right-style | Same as border-style. |
The diagrams below show the output of border-width and border-style attributes.
Space, Indent and Padding
Space attributes are used to separate FOs from other FOs on the page.
Indent attributes are used to indent FOs from the left and right borders of their containers.
Padding attributes are used to separate the content of FOs from the borders or edges of the block.
| Attribute | Values |
|---|---|
| space-before | <length> - A non-negative length |
| space-after | <length> - A non-negative length |
The values of space attributes are not cumulative. Notice that the space between the first two blocks is the same (10px) as the space between the second block, which wants 10px of space between it and the following block, and third block, which wants 10px of space between it and the preceding block.
| Attribute | Values |
|---|---|
| start-indent |
|
| end-indent | Same as start-indent |
Indents can be specified in length (e.g, 30px) or percentage of the containing block (e.g, 50%).
Padding is specified in length and is used to create a buffer between the content and the border or edge of a block.
| Attribute | Values |
|---|---|
| padding | <length> - A non-negative length |
| padding-top | Same as padding |
| padding-bottom | Same as padding |
| padding-left | Same as padding |
| padding-right | Same as padding |
Background
Background attributes are used to set the background properties of a FO.
| Attribute | Values |
|---|---|
| background-color | color |
| background-image | path to image |
| background-position-vertical |
|
| background-position-horizontal |
|
| background-repeat |
|
A Formatting Example
The following example shows how some of these attributes can be applied to our "Hello-World" example.
Code Sample: BlocksAndInlines/Demos/HelloWorld2.fo
<?xml version="1.0" encoding="utf-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="hello" page-height="11in"
page-width="8.5in" margin-top="1in" margin-bottom="1in"
margin-left="1in" margin-right="1in">
<fo:region-body margin-top="1in" margin-bottom=".5in"/>
<fo:region-before extent=".5in" background-color="silver"/>
<fo:region-after extent=".5in" background-color="silver"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="hello">
<fo:static-content flow-name="xsl-region-before">
<fo:block font-size="24pt">Hello World!</fo:block>
</fo:static-content>
<fo:static-content flow-name="xsl-region-after">
<fo:block font-size="24pt" text-align="right">
Page <fo:page-number/> of <fo:page-number-citation ref-id="last-page"/>
</fo:block>
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="36pt" font-weight="bold" text-align="center"
space-before="2in" space-after="1in"
start-indent="1.5in" end-indent="1.5in"
border-color="red" border-style="solid" border-width="1mm"
padding="1cm" background-color="#aaaaff">
Hello World!
</fo:block>
<fo:block background-color="red">
Goodbye!
</fo:block>
<fo:block id="last-page"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
The example above will render as follows.
![]()
Formatting Text
Font and text formatting can be applied at the block level with the following attributes.
| Attribute | Values |
|---|---|
| font-family |
|
| font-size |
|
| font-style |
|
| font-variant |
|
| font-weight |
|
| color |
|
| text-decoration |
|
The example below shows some of these attributes in effect.
Code Sample: BlocksAndInlines/Demos/HelloWorld3.fo
<?xml version="1.0" encoding="utf-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="hello" page-height="11in"
page-width="8.5in" margin-top="1in" margin-bottom="1in"
margin-left="1in" margin-right="1in">
<fo:region-body margin-top="1in" margin-bottom=".5in"/>
<fo:region-before extent=".5in" background-color="silver"/>
<fo:region-after extent=".5in" background-color="silver"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="hello">
<fo:static-content flow-name="xsl-region-before">
<fo:block font-size="24pt">Hello World!</fo:block>
</fo:static-content>
<fo:static-content flow-name="xsl-region-after">
<fo:block font-size="24pt" text-align="right">
Page <fo:page-number/> of <fo:page-number-citation ref-id="last-page"/>
</fo:block>
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="18pt" font-style="italic">
Hello World!
</fo:block>
<fo:block font-size="18pt" font-family="monospace">
Hello World!
</fo:block>
<fo:block font-size="18pt" font-weight="bold">
Hello World!
</fo:block>
<fo:block font-size="18pt" font-variant="small-caps">
Hello World!
</fo:block>
<fo:block font-size="18pt" text-decoration="line-through">
Hello World!
</fo:block>
<fo:block id="last-page"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
The example above will render as follows. Note that only the top left quarter of the page is shown.
![]()
Inline Elements
An inline element is an element that does not cause a block to be created; for example, to apply formatting to text within a block. Inline elements are denoted with the inline tag. The following example illustrates the use of inline.
Code Sample: BlocksAndInlines/Demos/HelloWorldInline.fo
<?xml version="1.0" encoding="utf-8"?> <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">---- Code Omitted ----<fo:page-sequence master-reference="hello"> <fo:static-content flow-name="xsl-region-before"> <fo:block font-size="24pt">Hello <fo:inline font-weight="bold" text-decoration="underline">World!</fo:inline> </fo:block> </fo:static-content>---- Code Omitted ----</fo:page-sequence> </fo:root>
The example above will render as follows. Note that only the top left quarter of the page is shown.
![]()
The same text-formatting attributes shown for block FOs can be used for inline FOs.
Inheritance
Many properties are inherited from parent or ancestor FOs. For example, if you set the font-family in the page-sequence FO, all text in descendant FOs will be in that font family unless it is overridden by a closer ancestor. Generally, properties that you would think should inherit (e.g, font properties, colors, alignment, etc.) do inherit. The example below illustrates inheritance.
Code Sample: BlocksAndInlines/Demos/Inheritance.fo
<?xml version="1.0" encoding="utf-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="page" page-height="11in" page-width="8.5in" margin="1in">
<fo:region-body margin=".5in"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="page" font-size="18pt" font-weight="bold" start-indent="1cm">
<fo:flow flow-name="xsl-region-body">
<fo:block space-after=".5cm">
Hello World!
</fo:block>
<fo:block space-after=".5cm" font-weight="normal" start-indent="0cm">
Hello World!
</fo:block>
<fo:block>
Hello <fo:inline font-weight="normal">World</fo:inline>!
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
The output is shown below:
![]()
wrapper
In some cases, you will have large sections of a printed document that needs to be formatted differently from the main document. The wrapper FO is used to assign values to inheriting properties. It can be used in an inline or block element and does not contain its own direct content.
Code Sample: BlocksAndInlines/Demos/Wrapper.fo
<?xml version="1.0" encoding="utf-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="page" page-height="11in" page-width="8.5in" margin="1in">
<fo:region-body margin=".5in"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="page" font-size="18pt" font-weight="bold" start-indent="1cm">
<fo:flow flow-name="xsl-region-body">
<fo:block space-after=".5cm">
Hello World!
</fo:block>
<fo:wrapper text-decoration="underline">
<fo:block space-after=".5cm" font-weight="normal" start-indent="0cm">
Hello World!
</fo:block>
<fo:block>
<fo:wrapper color="silver">Hello <fo:inline font-weight="normal">World</fo:inline></fo:wrapper>!
</fo:block>
</fo:wrapper>
</fo:flow>
</fo:page-sequence>
</fo:root>
The output is shown below:
![]()
Creating Lists
Lists are created with the list-block FO, which contains one or more list-item FOs. Each list-item FO must contain two child FOs: list-item-label and list-item-body. The syntax is shown below.
<fo:list-block start-indent="20pt">
<fo:list-item>
<fo:list-item-label end-indent="label-end()">
<fo:block font-weight="bold">
<!--bullet character or number-->
</fo:block>
</fo:list-item-label>
<fo:list-item-body start-indent="body-start()">
<fo:block>
<!--list item content-->
</fo:block>
</fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label end-indent="label-end()">
<fo:block font-weight="bold">
<!--bullet character or number-->
</fo:block>
</fo:list-item-label>
<fo:list-item-body start-indent="body-start()">
<fo:block>
<!--list item content-->
</fo:block>
</fo:list-item-body>
</fo:list-item>
</fo:list-block>
Below is a different view of how these tags are nested. The plus sign (+) indicates that list-item can be repeated.
list-block
The list-block FO contains the entire list. It can take many formatting attributes. A common one is start-indent, which can be used to indent the entire list. The list-block FO contains one or more list-item FOs.
list-item
The list-item FOs each contain two child FOs: list-item-label and list-item-body.
list-item-label
The list-item-label FO contains the symbol or character used to label the list; for example, a bullet or a number. It often takes the end-indent attribute with a value of label-end(), indicating that the label should not be indented more than its natural width.
character
The character FO is used to output a character using its character code. For example, the following would output a standard bullet.
<fo:character character="•"/>
list-item-body
The list-item-body FO contains the actual content of the list item. It often takes the start-indent attribute with the value of body-start(), indicating that the body of the list item should start at the beginning of the list-item-body box.
Let's take a look at an example.
Code Sample: BlocksAndInlines/Demos/ShoppingList.fo
<?xml version="1.0" encoding="UTF-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="List" page-height="11in"
page-width="8.5in" margin-top="1in" margin-bottom="1in"
margin-left="1in" margin-right="1in">
<fo:region-body margin-top="1in" margin-bottom=".5in"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="List">
<fo:flow flow-name="xsl-region-body">
<fo:block space-after="24pt" font-weight="bold">
Shopping List
</fo:block>
<fo:list-block start-indent="2in">
<fo:list-item>
<fo:list-item-label end-indent="label-end()">
<fo:block font-weight="bold">
<fo:character character="•"/>
</fo:block>
</fo:list-item-label>
<fo:list-item-body start-indent="body-start()">
<fo:block>Pizza</fo:block>
</fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label end-indent="label-end()">
<fo:block font-weight="bold">
<fo:character character="•"/>
</fo:block>
</fo:list-item-label>
<fo:list-item-body start-indent="body-start()">
<fo:block>Coke</fo:block>
</fo:list-item-body>
</fo:list-item>
</fo:list-block>
</fo:flow>
</fo:page-sequence>
</fo:root>
The example above will render as follows.
![]()
Exercise: Creating a List
In this exercise, you will practice transforming an XML document into a list for output as PDF.
- Open BlocksAndInlines/Exercises/Beatles.xml and examine the code.
- Open BlocksAndInlines/Exercises/Beatles.xsl for editing.
- Notice that the list block has already been started:
<fo:list-block start-indent="20pt"> <xsl:apply-templates/> </fo:list-block>
- At the bottom of the document is a template matching beatle.
- Fill in this template so that a list item is created for each Beatle.
- To test your solution, transform BlocksAndInlines/Exercises/Beatles.xml against BlocksAndInlines/Exercises/Beatles.xsl.
Code Sample: BlocksAndInlines/Exercises/Beatles.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/beatles">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="list" page-height="11in"
page-width="8.5in" margin-top=".5in" margin-bottom=".5in"
margin-left=".5in" margin-right=".5in">
<fo:region-body margin-top="1in" margin-bottom="1in"/>
<fo:region-before extent=".5in"/>
<fo:region-after extent=".5in"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="list">
<fo:static-content flow-name="xsl-region-before" text-align="center">
<fo:block font-size="20pt" font-weight="bold">
The Beatles
</fo:block>
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block space-after="24pt" font-weight="bold">
The Beatles
</fo:block>
<fo:list-block start-indent="20pt">
<xsl:apply-templates/>
</fo:list-block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="beatle">
<!--
Fill in this template so that a list item is created for each Beatle
-->
</xsl:template>
</xsl:stylesheet>
Note that lists can be nested. For an example see BlocksAndInlines/Demos/ShoppingListNested.fo.
Whitespace
There are five attributes that affect how whitespace is handled: linefeed-treatment, white-space-collapse, wrap-option, white-space-treatment, and white-space. The table below shows possible values for these attributes.
| Attribute | Values |
|---|---|
| linefeed-treatment |
|
| white-space-collapse |
|
| wrap-option |
|
| white-space-treatment |
|
| white-space |
|
The white-space attribute is a shorthand for setting values for the other four attributes, as shown below.
- normal
- linefeed-treatment = "treat-as-space"
- white-space-collapse = "true"
- white-space-treatment = "ignore-if-surrounding-linefeed"
- wrap-option = "wrap"
- pre
- linefeed-treatment = "preserve"
- white-space-collapse = "false"
- white-space-treatment = "preserve"
- wrap-option = "no-wrap"
- nowrap
- linefeed-treatment = "treat-as-space"
- white-space-collapse = "true"
- white-space-treatment = "ignore-if-surrounding-linefeed"
- wrap-option = "no-wrap"
The example below shows how these whitespace attributes can be used to maintain linefeeds in output while also allowing long lines to wrap.
Code Sample: BlocksAndInlines/Demos/Poem.xml
<?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="Poem.xsl"?> <Poem> <Title>Casey at the Bat</Title> <Author>Ernest Lawrence Thayer</Author> <Content> The outlook wasn't brilliant for the Mudville nine that day: The score stood four to two, with but one inning more to play, And then when Cooney died at first, and Barrows did the same, A pall-like silence fell upon the patrons of the game. A straggling few got up to go in deep despair. The rest Clung to that hope which springs eternal in the human breast; They thought, "If only Casey could but get a whack at that— We'd put up even money now, with Casey at the bat. But Flynn preceded Casey, as did also Jimmy Blake, And the former was a hoodoo, while the latter was a cake; So upon that stricken multitude grim melancholy sat, For there seemed but little chance of Casey getting to the bat. But Flynn let drive a single, to the wonderment of all, And Blake, the much despisèd, tore the cover off the ball; And when the dust had lifted, and men saw what had occurred, There was Jimmy safe at second and Flynn a-hugging third. Then from five thousand throats and more there rose a lusty yell; It rumbled through the valley, it rattled in the dell; It pounded on the mountain and recoiled upon the flat, For Casey, mighty Casey, was advancing to the bat. There was ease in Casey's manner as he stepped into his place; There was pride in Casey's bearing and a smile lit Casey's face. And when, responding to the cheers, he lightly doffed his hat, No stranger in the crowd could doubt 'twas Casey at the bat. Ten thousand eyes were on him as he rubbed his hands with dirt; Five thousand tongues applauded when he wiped them on his shirt; Then while the writhing pitcher ground the ball into his hip, Defiance flashed in Casey's eye, a sneer curled Casey's lip. And now the leather-covered sphere came hurtling through the air, And Casey stood a-watching it in haughty grandeur there. Close by the sturdy batsman the ball unheeded sped— "That ain't my style," said Casey. "Strike one!" the umpire said. From the benches, black with people, there went up a muffled roar, Like the beating of the storm-waves on a stern and distant shore; "Kill him! Kill the umpire!" shouted someone on the stand; And it's likely they'd have killed him had not Casey raised his hand. With a smile of Christian charity great Casey's visage shone; He stilled the rising tumult; he bade the game go on; He signaled to the pitcher, and once more the dun sphere flew; But Casey still ignored it and the umpire said, "Strike two!" "Fraud!" cried the maddened thousands, and echo answered "Fraud!" But one scornful look from Casey and the audience was awed. They saw his face grow stern and cold, they saw his muscles strain, And they knew that Casey wouldn't let that ball go by again. The sneer is gone from Casey's lip, his teeth are clenched in hate, He pounds with cruel violence his bat upon the plate; And now the pitcher holds the ball, and now he lets it go, And now the air is shattered by the force of Casey's blow. Oh, somewhere in this favoured land the sun is shining bright, The band is playing somewhere, and somewhere hearts are light; And somewhere men are laughing, and somewhere children shout, But there is no joy in Mudville—mighty Casey has struck out. </Content> </Poem>
Code Sample: BlocksAndInlines/Demos/Poem.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<fo:root>
<fo:layout-master-set>
<fo:simple-page-master master-name="Poem" page-height="11in" page-width="8.5in"
margin="1in">
<fo:region-body margin="1in"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="Poem">
<fo:flow flow-name="xsl-region-body">
<fo:block font-weight="bold" font-size="18pt" font-family="Times" id="{generate-id(Title)}" break-before="page">
<xsl:value-of select="//Title"/>
</fo:block>
<fo:block font-size="16pt" font-style="italic" font-family="Times"
margin-bottom=".1in" margin-left=".2in">
- <xsl:value-of select="//Author"/>
</fo:block>
<fo:block linefeed-treatment="preserve" white-space-collapse="false" wrap-option="wrap" white-space-treatment="preserve" font-size="16pt">
<xsl:value-of select="//Content"/>
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>
Blocks and Inlines Conclusion
In this lesson of the XML tutorial, you have learned the basic building blocks of XSL-FO, including block FOs, inline FOs, and list-block FOs. You have also learned how to format these blocks with formatting and whitespace attributes.