XSL-FO 1.0 only defines one kind of master page, the fo:simple-page-master . This represents a standard rectangular page with margins on all four sides. This page master also has a unique name given by a master-name attribute. For example, this element describes a page master named first that represents an 8.5 11-inch page with 1-inch margins on all four sides: <fo:simple-page-master margin-right="1in" margin-left="1in" margin-bottom="1in" margin-top="1in" page-width="8.5in" page-height="11in" master-name="first"> <!-- Separate parts of the page go here --> </fo:simple-page-master> The part of the page inside the margins is divided into five regions : the start region, the end region, the before region, the after region, and the body region. Where these fall on a page depends on the writing direction. In left-to-right , top-to-bottom languages like English, start is on the lefthand side, end is on the righthand side, before is on top, and after is on bottom, as diagramed in Figure 14-2. However, if the text were Hebrew, then the start region would be on the right-hand side of the page, and the end region would be on the lefthand side of the page. If the text were traditional Chinese, then the start would be on top, the end on bottom, the before on the righthand side, and the after on the lefthand side. Other combinations are possible. Figure 14-2. The five regions in a left-to-right, top-to-bottom writing system These regions are represented by fo:region-start , fo:region-end , fo:region-before , fo:region-after , and fo:region-body child elements of the fo:simple-page-master element. You can place different content into each of the five regions. For instance, the after region often contains a page number, and the before region may contain the title of the book or chapter. The body region and the corresponding fo:region-body element are required. The other four are optional. By default, the body region takes up the entire page, and the other four regions have zero area. To specify this simplest page, you add an empty fo:region-body child element to the fo:simple-page-master element like this: <fo:simple-page-master margin-right="1in" margin-left="1in" margin-bottom="1in" margin-top="1in" page-width="8.5in" page-height="11in" master-name="first"> <fo:region-body/> </fo:simple-page-master> However, you can add extent attributes to the four nonbody regions to specify the height of the before and after regions and the width of the start and end regions. Then the region body should have margin properties that are at least as large as the extent of each region to push it out of the way of each nonbody region. Otherwise, content placed in the body will be drawn on top of content placed in the other four regions. For example, this fo:simple-page-master element has 0.5-inch margins on each side, representing the unprintable area on many common printers. The start and end regions are 0.5 inches wide. The before and after regions are 1 inch wide. The body has margins that match the region sizes. <fo:simple-page-master margin-right="0.5in" margin-left="0.5in" margin-bottom="0.5in" margin-top="0.5in" page-width="8.5in" page-height="11in" master-name="first"> <fo:region-before extent="0.5in"/> <fo:region-after extent="0.5in"/> <fo:region-start extent="0.5in"/> <fo:region-end extent="0.5in"/> <fo:region-body margin-top="1.0in" margin-bottom="1.0in " margin-left="0.5in" margin-right="0.5in"/> </fo:simple-page-master> Most of the time, the details of the layout-master set are fixed in the stylesheet. For example, here's the revised XSLT template that includes a full fo:layout-master-set : <xsl:template match="/"> <fo:root> <fo:layout-master-set> <fo:simple-page-master margin-right="1in" margin-left="1in" margin-bottom="1in" margin-top="1in" page-width="8.5in" page-height="11in" master-name="first"> <fo:region-body/> </fo:simple-page-master> </fo:layout-master-set> <fo:page-sequence master-reference="first"> <!-- data to place on the page --> </fo:page-sequence> </fo:root> </xsl:template> 14.3.1 Flowing Content into the Pages Next, add an fo:flow child to the fo:page-sequence where the actual text of the transformed document appears. This element has a flow-name attribute specifying which region of the page its content will flow into. Possible values include xsl-region-body , xsl-region-start , xsl-region-end , xsl-region-before , and xsl-region-after . The formatter instantiates a page based on the page master named by the fo:page-sequence 's master-reference attribute, fills one of its regions with content from the fo:flow element until the page is full, then instantiates a second page, fills it with more content from the fo:flow , instantiates a third page, and continues this process until it's used up all the data in the fo:flow . The fo:flow element must contain block-level formatting object elements. The most basic of these is fo:block . Others include fo:block-container , fo: list-block , fo:table , and fo:table-and-caption . We'll begin with the most basic, fo:block . A fo:block can contain a combination of raw text and formatting objects, such as fo:external-graphic , fo:inline , fo: page-number , fo:footnote , and even other fo:block elements. For the moment, we'll restrict ourselves to simple text. For example, here's a basic fo:flow for the recipe: <fo:flow flow-name="xsl-region-body"> <fo:block>Southern Corn Bread</fo:block> <fo:block>1 cup flour</fo:block> <fo:block>4 tablespoons Royal Baking Powder</fo:block> <fo:block> 1 / 2 teaspoon salt</fo:block> <fo:block>1 cup corn meal</fo:block> <fo:block>1 1 / 2 cups whole milk</fo:block> <fo:block>4 tablespoons melted butter</fo:block> <fo:block>Sift flour, baking powder, sugar & salt together. Add 1 cup corn meal. Beat egg in cup and add beaten egg and 1 1 / 2 cups whole milk to make a batter. Stir well. Add melted shortening and beat until light and thoroughly mixed. Pour into greased shallow pan or greased muffin rings. Bake in hot oven at 425 F for 25 minutes! Cut into squares if cooked in shallow pan.</fo:block> <fo:block>After my mother-in-law Marjorie Anderson died, Beth and I found this recipe written on the "extra recipes" page in a local cookbook in her cupboard. This was published by the The Episcopal Churchwomen, Church of Ascension, Mt. Sterling, Kentucky.</fo:block> </fo:flow> Here's an XSLT template that produces the content of this fo:flow element (modulo insignificant whitespace) from Example 14-1 through judicious use of the default template rules: <xsl:template match="dishingredientdirectionsstory"> <fo:block><xsl:apply-templates/></fo:block> </xsl:template> 14.3.2 Generating the Finished Document We now have the minimum set of pieces needed to put together a full XSL-FO document. Example 14-2 is an XSLT stylesheet that transforms documents like Example 14-1 into XSL Formatting Objects documents. Example 14-2. An XSLT to XSL-FO transform <?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:template match="/"> <fo:root> <fo:layout-master-set> <fo:simple-page-master margin-right="1in" margin-left="1in" margin-bottom="1in" margin-top="1in" page-width="8.5in" page-height="11in" master-name="first"> <fo:region-body/> </fo:simple-page-master> </fo:layout-master-set> <fo:page-sequence master-reference="first"> <fo:flow flow-name="xsl-region-body"> <xsl:apply-templates/> </fo:flow> </fo:page-sequence> </fo:root> </xsl:template> <xsl:template match="dishingredientdirectionsstory"> <fo:block><xsl:apply-templates/></fo:block> </xsl:template> </xsl:stylesheet> Example 14-3 shows the complete XSL-FO document produced by running the cornbread recipe through an XSLT engine, such as Xalan, with this stylesheet. The whitespace is a little off because of the way XSLT treats whitespace in the transform document. However, this won't be significant when the document is rendered. Example 14-3. An XSL-FO document describing a recipe for cornbread <?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-right="1in" margin-left="1in" margin-bottom="1in" margin-top="1in" page-width="8.5in" page-height="11in" master-name="first"><fo:region-body/></fo:simple-page-master> </fo:layout-master-set><fo:page-sequence master-reference="first"> <fo:flow flow-name="xsl-region-body"> <fo:block>Southern Corn Bread</fo:block> <fo:block> 1 cup flour </fo:block> <fo:block> 4 tablespoons Royal Baking Powder </fo:block> <fo:block> 1 / 2 teaspoon salt </fo:block> <fo:block> 1 cup corn meal </fo:block> <fo:block> 1 1 / 2 cups whole milk </fo:block> <fo:block> 4 tablespoons melted butter </fo:block> <fo:block> Sift flour, baking powder, sugar & salt together. Add 1 cup corn meal. Beat egg in cup and add beaten egg and 1 1 / 2 cups whole milk to make a batter. Stir well. Add melted shortening and beat until light and thoroughly mixed. Pour into greased shallow pan or greased muffin rings. Bake in hot oven at 425 F for 25 minutes. Cut into squares if cooked in shallow pan. </fo:block> <fo:block> After my mother-in-law Marjorie Anderson died, Beth and I found this recipe written on the "extra recipes" page in a local cookbook in her cupboard. This was published by the The Episcopal Churchwomen, Church of Ascension, Mt. Sterling, Kentucky. </fo:block> </fo:flow></fo:page-sequence></fo:root> The final step in this process is to convert the formatting objects document into some other format that can be viewed on screen or on paper. This requires running a formatting program such as the Apache XML Project's open source FOP (http://xml.apache.org/fop/). FOP is a Java program. At the time of this writing, it has some significant holes in its coverage, but it is making progress. It includes shell scripts for DOS and Windows that set up the classpath and launch the Java program. For example, on Windows, this command line transforms the file cornbread.fo into a PDF document: C:\> fop -fo cornbread.fo -pdf cornbread.pdf FOP can also transform XSL-FO documents into plain text, raw PostScript, a PCL file, SVG slides, or display it on the screen using the Java 2D API. This command produces the window shown in Figure 14-3. Figure 14-3. The XSL-FO recipe document in FOP's AWT preview There are several other programs for working with XSL-FO documents: -
RenderX's XEP (http://xep.xattic.com) is a payware Java XSL-FO-to-PDF converter program much like FOP. -
Sebastian Rahtz's PassiveTEX (http://www.hcu.ox.ac.uk/TEI/Software/ passivetex /) is an open source collection of TeX macros for converting XSL-FO documents to TeX. A reasonably modern TeX distribution is required. -
The Antenna House XSL Formatter (http://www.antennahouse.com) is a payware Windows program that can print and display XSL-FO documents using the Windows GDI. -
IBM's XSL Formatting Objects Composer (http://www.alphaworks.ibm.com/tech/xfc) is a free-as-in-beer Java program that implements a "substantial portion" of XSL Formatting Objects 1.0. It can display XSL-FO documents on the screen or convert them to PDF. |