XSLT and Formatting Objects

Christopher M. Judd - Judd Solutions, LLC.
http://www.juddsolutions.com


Introduction

XSL

XSLT

XML to XHTML Strategies

Static Web Pages

Dynamic Web Pages

Printable Document

Summary

Resources


Introduction

The Internet and especially the World Wide Web supports a common consumer/producer model. ?Where a producer is an individual or organization that creates information called content and makes it available to consumers.

Figure 1 - Consumer/Producer Model
Historically, the World Wide Web has allowed producers to provide content in the form of HTML for consumers to read using a web browsers such as Microsoft Internet Explorer or Netscape Navigator.  However, with the increased availability of broadband and the advent of affordable mobile Internet enabled devices a new set of consumers have emerged.  Cell phones, PDAs and other business applications are becoming common tools to access information and conduct business 24 hours a day.

The challenge is each consumer has constraints concerning the format of the data.  The constraints maybe determined by the size of the device, bandwidth or parseablity.  Many organizations have unsuccessfully tried using HTML as a one size fits all solution.  Developers often duplicate efforts by writing a separate JSP or Servlet to support each type of consumer.  The problem is HTML is a document format that represents both the content and the style. ?By combining content and style it prevents the reusing of the valuable content.

This paper will demonstrate how to alleviate some duplication of effort by using Extensible Markup Language (XML), the content, and Extensible Stylesheet Language (XSL) to transform XML into a format desirable by specific consumers.  This article assumes the reader is already familiar with XML.  Through the use of a conference website example, this paper will demonstrate how to produce static HTML pages, dynamic HTML pages that can be viewed with a desktop browser or handheld browser as well as printable documentation.  This will be accomplished by using JBuilder's XSL features and Apache's XML Project.

XSL

Extensible Stylesheet Language (XSL) is a language that describes stylesheets for transforming XML documents into other formats with the use of formatters.  The XSL specification includes both XSL Transformation (XSLT), the language for transforming XML documents into other XML documents, and Formatting Objects (FO), for transforming XML documents into a presentation format.  XSL also relies heavily on XPATH for accessing parts of the XML document.  See the resource section for links to the XML, XSL and XPATH specifications.

The transformation process involves feeding a XML document and XSL document through a XSLT processor such as Xalan, an Apache XML subproject (see  resources) to produce a new XML document.  Additionally, if the desired output is a presentation format, FO further processes it with presentation formatters (see figure 2). 

Figure 2 - XSL process

The most common product of an XML transformation is not HTML but XHTML.  HTML is not a XML format.  HTML and XML have a lot in common, tags and attributes.  However there is one major difference between the two.  XML documents must be well formed. This means all tags must have an opening (<a href="http://www.juddsolutions.com">) and closing (</a>) tag.  If the tag is both opened and closed in the same tag it is referred to as an empty tag.  HTML does not have this restriction.  Tags such as the line break, <br> and image, <img> are not required to be closed.  XHTML then is a well formed HTML document.  This is usually done by making otherwise unclosed tags empty tags like <br/> and enclosing all attributes in quotes.

XSL documents are themselves an XML document and must also be well formed.

XSL uses the XPATH specification to locate portions of an XML document.  Most of the path syntax resembles that of a filesystem path.  See table 1 for syntax.  XPATH also includes node set, boolean and numeric operations as well as node set, string, boolean and numeric functions.  See the resources section for more information about XPATH.

XPATH Syntax Description
/ root of XML document
. Current node
.. Parent node
@ Attribute
// Descendants
Table 1 - XPATH syntax 

XSLT

As stated earlier, XSLT is the transformation language used to transform XML documents into other XML documents.  The basic building blocks of XSLT documents are templates.  A template is transformation code that is applied based on a particular XPATH.  Listing 1 shows an example of a template that is applied to the root node of an XML document and transforms it into XHTML.  So for each root node in the XML document (of course there is only one) it is going to begin by including <html> in  the output and end by including </html>.  In between it will access values of nodes, apply other templates and conditional logic to produce the desired XHTML output.

<xsl:template match="/">

<html>
<head>
 <title>
  <xsl:value-of select="$event//event_name" />
  <xsl:if test="$pageTitle">
   - <xsl:apply-templates select="$pageTitle" />
  </xsl:if>
 </title>
 <link rel="stylesheet" type="text/css" href="{$style.src}default.css"/>
 <script language="JavaScript" src="{$scripts.src}default.js" />
</head>
<body>
 <table border="0" cellpadding="0" cellspacing="0" width="800">
  <tr>
   <td rowspan="1" colspan="1" width="142" height="97"><img src="{$img.src}keyboard.jpg" /></td>
   <td rowspan="1" colspan="4" width="658" height="97"><img src="{$img.src}title.jpg" /></td>
  </tr>

  <tr>
   <td rowspan="1" colspan="2" width="432" height="14"><img src="{$img.src}black_bar_1.jpg" /></td>
   <td rowspan="1" colspan="1" width="131" height="14">
     <!-- attendees menu item -->
      <xsl:choose>
        <xsl:when test="$pageMenu='attendees'">
         <img name="attendees" border="0" src="{$img.src}attendees_on.jpg" />
        </xsl:when>
        <xsl:otherwise>
         <a href="{$attendees.url}" onMouseOut="MM_swapImgRestore()" onMouseOver="MM_swapImage('attendees','','{$img.src}attendees_on.jpg',1)">
          <img name="attendees" border="0" src="{$img.src}attendees_off.jpg" />
         </a>
        </xsl:otherwise>
      </xsl:choose>

   </td>
   <td rowspan="1" colspan="1" width="121" height="14">
     <!-- speakers menu item -->
      <xsl:choose>
        <xsl:when test="$pageMenu='speakers'">
         <img name="speakers" border="0" src="{$img.src}speakers_on.jpg" />
        </xsl:when>
        <xsl:otherwise>
         <a href="{$speakers.url}" onMouseOut="MM_swapImgRestore()" onMouseOver="MM_swapImage('speakers','','{$img.src}speakers_on.jpg',1)">
          <img name="speakers" border="0" src="{$img.src}speakers_off.jpg" />
         </a>
        </xsl:otherwise>
      </xsl:choose>

   </td>
   <td rowspan="1" colspan="1" width="116" height="14"><img src="{$img.src}black_bar_2.jpg" /></td>
  </tr>

  <tr>
   <td width="142" colspan="1" bgcolor="#3639A0" valign="top">
    <!-- Context Menu -->
    <xsl:call-template name="doMenu"/>
    <xsl:call-template name="doContact"/>
   </td>

   <td width="658" colspan="4">
    <!-- Content goes here -->
    <xsl:call-template name="doBody"/>
   </td>
  </tr>

  <tr>
   <td rowspan="1" colspan="1" width="142" height="20"><img name="copyright" src="{$img.src}copyright.jpg" /></td>
   <td rowspan="1" colspan="4" width="658" height="20"></td>
  </tr>

  <tr>
   <td rowspan="1" colspan="1" width="142"></td>
   <td rowspan="1" colspan="4" width="658" class="copyright">
    Java and all Java-based trademarks and logos are trademarks or registered
    trademarks of Sun Microsystems, Inc. in the United States and other countries.
   </td>
  </tr>

  <tr>
   <td width="142" height="0"></td>
   <td width="290" height="0"></td>
   <td width="131" height="0"></td>
   <td width="121" height="0"></td>
   <td width="116" height="0"></td>
  </tr>
 </table>

</body>
</html>

<xsl:call-template name="doDump"/>

</xsl:template>
Listing 1 - Template applied to the root of a document for transforming it to XHTML.

Just like a programming language XSLT has the concept of parameters and variables.  Parameters are values identified externally and passed to the translation process along with the XML and XSLT document much like a parameter is passed to the main method of an executable Java class.  Variables are used to temporally store values or nodes.  To access the variable or parameter prefix it with a $ such as $src.name.  In cases where it might run directly into other identifiers use the formal notation of {$} such as {$src.name}.  Listing 2 demonstrates defining a parameter with a default value of javadays.  The parameter is then used to build a file path to an XML document.  The value of the path is stored in the variable of event.xml.  The variable event is assigned the root node of XML document javadays.xml.  It uses the built-in document function to load an external XML document.

<!-- Parameters -->
<xsl:param name="src.name">javadays</xsl:param>

<!-- Global Variables -->

<xsl:variable name="event.xml">../<xsl:value-of select="$src.name" />/include/javadays.xml</xsl:variable>
<xsl:variable name="event" select="document($event.xml)" />
Listing 2 - Example of parameters and variables

XSLT uses the value-of element to access node values in an XML document.  The value-of element uses a select attribute value to locate the specific node using an XPATH.  Listing 3 gets the first descendant of event (which was defined in listing 2) with the name of event_name.  In the grander scheme it is being used to build the page title of the XHTML document.

<xsl:value-of select="$event//event_name" />
Listing 3 - Access event_name node using the value-of element.

While not as robust as Java or other programming languages, XSLT does have the capability to include simple conditional logic.  XSLT supports if  and choose statements.  The choose statement is similar to a case or switch statement.  Listing 4 shows an example that tests if the variable $pageTitle has a value and if so it appends the title with a dash and the value of the variable.  Unfortunately the if statement does not include an else.   The choose statement can be used to represent and if/else construct.  Listing 5 demonstrates using the choose statement like and if/else.  In the example if $pageMenu equals attendees the image is included in an on state else the image is included in a hover state.

<xsl:if test="$pageTitle">
 - <xsl:apply-templates select="$pageTitle" />
</xsl:if>
Listing 4 - Example of an if
<xsl:choose>
 <xsl:when test="$pageMenu='attendees'">
  <img name="attendees" border="0" src="{$img.src}attendees_on.jpg" />
 </xsl:when>
 <xsl:otherwise>
  <a href="{$attendees.url}" onMouseOut="MM_swapImgRestore()" onMouseOver="MM_swapImage('attendees','','{$img.src}attendees_on.jpg',1)">
   <img name="attendees" border="0" src="{$img.src}attendees_off.jpg" />
  </a>
 </xsl:otherwise>
</xsl:choose>
Listing 5 - Example of choose for substitute of missing else

XML to XHTML Strategies

Without developing a strategy, it is really easy to get into bad habits such as creating an XSLT document for each XML document negating the value of using XSLT to begin with.  So, here are some strategies I have developed and learned when transforming XML into XHTML.  

Separating the look and feel from the actual document transformation.  I have learned to create a master.xsl document that contains the look and feel of the website.  Then for each XML document type I create a transformation XSL document that imports the master.xsl.

Take advantage of HTML.  For pages that just contain text and image content use HTML.  There are many good tools that can be used to develop and maintain HTML.  These tool can allow content owners to manage the content rather than a developer.  These tool also include features such as spell checking.  Then create a custom HTML transformation document (Listing 6 - default.xsl) that extracts the body content and possibly uses the meta tags as variable content.  Importing the master.xsl will apply the proper look and feel.  Remember HTML is not a well formed XML document so all tags will need to be closed.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:import href="master.xsl"/>

  <!-- Variables -->
  <xsl:variable name="pageTitle" select="//head/title"/>
  <xsl:variable name="pageGreeting" select="//head/meta[@name='greeting']/@content"/>
  <xsl:variable name="pageMenu" select="//head/meta[@name='menu']/@content"/>

<xsl:template name="doBody">
  <xsl:call-template name="doHeading"/>
  <xsl:copy-of select="//body/*"/>
</xsl:template>

<xsl:template name="doScript">
  <xsl:value-of select="//head/script" />
</xsl:template>

<xsl:template name="doHeading">
  <h2>
  <xsl:choose>
    <xsl:when test="$pageGreeting"><xsl:apply-templates select="$pageGreeting"/></xsl:when>
    <xsl:otherwise><xsl:apply-templates select="$pageTitle"/></xsl:otherwise>
  </xsl:choose>
  </h2>
</xsl:template>

<xsl:template match="head/title|head/greeting">
  <xsl:apply-templates select="*|text()"/>
</xsl:template>

</xsl:stylesheet>
Listing 6 - XSLT to transform HTML documents 
<html>
<head>
  <title>#1 Java conference in Ohio</title>
  <meta name="menu" content="attendees" />
  <meta name="greeting" content="Only Java conference in Ohio." />
</head>

<body>

<table>
  <tr valign="top">
    <td colspan="4">
      Join us for the fourth annual Central Ohio Java Days Conference and Exposition.
      This event, arranged by the Central Ohio Java Users Group (COJUG), is a unique
      two-day, Java-specific, multi-track conference and exhibition, which will
      allow software professionals to focus on various aspects of Java and related
      technology. As in past years, we're expecting participation from technology
      leaders. Expect great leading edge technology presentations, product
      demonstrations, lectures, vendor exhibits, and wonderful networking
      opportunities. The tracks will present core information and the latest in
      eCommerce, Java (including J2SE, J2EE, J2ME), web services, IT management,
      etc. The exhibit hall will provide you with an opportunity to see the
      leading edge companies' solutions.
    </td>
  </tr>
</table>
<p></p>
</body>
</html>
Listing 7 - HTML document example

File paths change often.  Sometimes they are even different between development, testing and production.  I have learned to keep all of my paths in a single controller.xsl document making it easy to locate and make changes them (see listing 8).  Xalan's evaluate extension enables this level of indirection (see listing 9).  This technique is Xalan specific but I have found it invaluable.  

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <!-- Main Menu -->
  <xsl:variable name="attendees.url">index.html</xsl:variable>
  <xsl:variable name="speakers.url">speakers.html</xsl:variable>

  <!-- Attendee Menu -->
  <xsl:variable name="index.url">index.html</xsl:variable>
  <xsl:variable name="speaker.url">http://www.juddsolutions.com</xsl:variable>
  <xsl:variable name="register.url">http://www.cojug.com</xsl:variable>
  <xsl:variable name="sessions.url">http://www.yahoo.com</xsl:variable>

  <!-- Speaker Menu -->
  <xsl:variable name="register.speaker.url">speakers.html</xsl:variable>
  <xsl:variable name="login.speaker.url">speakers.html</xsl:variable>
  <xsl:variable name="submit.speaker.url">speakers.html</xsl:variable>
  <xsl:variable name="edit.speaker.url">speakers.html</xsl:variable>

  <xsl:variable name="img.src">../images/</xsl:variable>
  <xsl:variable name="style.src">style/</xsl:variable>
  <xsl:variable name="scripts.src">scripts/</xsl:variable>

</xsl:stylesheet>
Listing 8 - controller.xsl contains all URLs.
<xsl:variable name="uri"><xsl:value-of select="xalan:evaluate(@href)"/></xsl:variable>
<a href="{$uri}" onMouseOut="MM_swapImgRestore()" onMouseOver="MM_swapImage('{@name}','','{$img.src}menus/{@name}_on.jpg',1)">
 <img name="{@name}" border="0" src="{$img.src}menus/{@name}_off.jpg" />
</a>
Listing 9 - Referencing URLs in the controller.xsl.

Debugging XSLT especially in a dynamic environment can be difficult.  Reviewing the exact XML document transformed can often provide clues to how it was processed.  Including the XML document as a comment within the resulting XHTML document is the best method to grab the dynamic content.  So, at the end of the master.xsl I include a call to a doDump template that reproduces the exact XML document.  Listing 10 shows an example of the doDump template.  If you are familiar with XSLT elements you might wonder why the <xsl:comment> element was not used.  Unfortunately the xsl namespace DTD does not allow the <xsl:copy-of> element to be used inside it.  Instead use the <xsl:text> element disabling escaping and building the <!-- by hand. 

<xsl:template name="doDump">
  <xsl:text disable-output-escaping="yes">&#13;&#10;<!--&#13;&#10;</xsl:text>
    <xsl:copy-of select="/"/>
  <xsl:text disable-output-escaping="yes">&#13;&#10;--></xsl:text>
</xsl:template>
Listing 10 - doDump template

Static Web Pages

XSLT can be used to generate XHTML documents.  Those documents can be generated either statically which produce a file with a html extension or dynamically and immediately returned to the browser that made the request.  When content is not expected to change frequently, performance can be enhanced by generating static web pages.  Additionally, developing a dynamic website does require some level of static testing.

The Professional and Enterprise versions of JBuilder include the Transform View and Transform Trace for testing XSLT transformations.  The Transform View enables a developer to apply the a XSLT stylesheet and see the results in an internal browser on the Transform View tab.  The Transformation View Source tab shows the resulting source that is being interpreted by the internal browser (see figure 3).  By default, a XSLT stylesheet is applied that displays the DOM tree in a collapsible node form (see figure 4).  The real value of the Transformation View is testing your custom XSLT stylesheets.  Add custom XSLT stylesheets using the Add stylesheets button ().  To apply the custom stylesheet select it from the combo box and press the Default stylesheet button ().  You can transform the speakers.xml document by applying the speakers.xsl stylesheet (read the following NOTE).  The XHTML output will be displayed in the internal browser if there are no errors in the XSLT or XML (see figure 5).  The process of viewing an XML document  in Transform View produces a intermediary file with the same name as the XML document followed by _transform.xml.  This document is not needed.  After testing it may be discarded.  Changes can be made either to the XML or XSLT files on their respective source tabs and reviewed again using the Transformation View.  After the changes the view must be refreshed.  While the view does include a refresh button (), it does not appear to fresh from the original source but from the intermediary file.  To force a retransformation toggle the Default stylesheet button () on and off.

NOTE: One disappointment I have with the Transform View is its inability to transform documents that use Xalan extensions. I use Xalan's evaluate expression as described in the XML to XHTML Strategies section of this paper.  For demonstration purposes, I have include a master_without_xalan.xsl for viewing the index.xml file in the Transform View.  To apply the Transform View friendly stylesheet change the speakers.xsl import statement to use master_without_xalan.xsl.  Because of the root the Transform View uses the image path must be changed.  Hence the value of the controller.xsl and xalan evaluate extension.  In controller.xsl change the img.src from images/ to ../images/.

Figure 3 - Output of transformation 

Figure 4 - Default Transform View Stylesheet

 

Figure 5 - Custom stylesheet

JBuilder Professional and Enterprise also includes the XML Transformation Trace which displays the order in which the transformation took place.  Clicking on a node will navigate the editor to the corresponding line.  This feature appears to work fine for simple documents but becomes confused when importing additional stylesheets.  Use the Set trace options button () to configure the XML Transformation Trace.

While the Transformation View is valuable for testing purposes, you don't want to transform each page this way then copy and rename the resulting _transform.html page.  Instead you will want to batch transform the entire set of static documents quickly.  I have found using the Jakarta Ant project (see resources for downloading) ideal for this.  Ant includes a style tag for applying XSLT templates to XML documents.  Listing 11 demonstrates transforming all documents with an html extension with the default.xsl stylesheet that transforms HTML documents into XHTML documents with a common look and feel.

<style basedir="${out.src.dir}"
       destdir="${out.dir}/"
       includes="*.html"
       excludes="include/*.*"
       style="${src.xsl.dir}/default.xsl"
       extension=".html">
   <param name="src.name" expression="${src.name}"/>
 </style>
Listing 11 - Transform XML documents in batch using Jakarta Ant's style tag.

Dynamic Web Pages

Supporting multiple clients can be a challenge.  Just because an HTML page looks good in Microsoft Internet Explorer does not mean it will even be functional on a Palm Pilot.  For example, using a web browser on a Palm Pilot one can read the contents of the index.html page however the rest of the site is inaccessible because the menus are not included.  Fortunately, JBuilder includes the open source publishing framework from the Apache XML project, Cocoon.  Cocoon uses XML and XSLT to publish content in multiple formats to multiple clients.  In reality Cocoon is a servlet that knows how to sniff out the browser's User-Agent and transform XML documents using  Xalan and Xerces.

To use Cocoon choose File | New | XML | Cocoon Web Application.  When prompted for the Cocoon settings click OK.  A cocoon node should be added to the project.   To run Cocoon, right click on the new Cocoon node and select Cocoon Run from the context menu.  This will instantiate an instance of the embedded Tomcat and open the Web View table with the XML document specified in the cocoon.xml file.  The index.xml and index.xsl examples are not very interesting, so we will use the JavaDays XML and XSL documents.  After copying them to the cocoon directory of the project a couple of changes will have to be made.  One change is the doDump reference must be removed from master.xsl.  It appears to not to be a feature in the version of Xalan included with this Cocoon version. In addition, some of the paths may need to be changed.  I also added a servlet mapping for the html pages to be filtered through cocoon (see Listing 12).

<servlet-mapping>
  <servlet-name>org.apache.cocoon.Cocoon</servlet-name>
  <url-pattern>*.html</url-pattern>
</servlet-mapping>
Listing 12 - Servlet mapping that forces Cocoon to process HTML pages.

Cocoon uses processing instructions which tell it the stylesheet to apply.  The processing instructions need added just bellow the initial xml processing tags.  Listing 13 shows the processors of speaker.xml.  Notice the second line, it defines an alternative stylesheet for palm media.  A mapping must be made between User-Agent (browser type) and media type.  To add the palm media type add browser.0 = palm=PalmOS to cocoon.properties and increment the exiting browser numbers.  Now add a master-palm.xsl and other palm style sheets that don't include graphics and use text for the menus.  Other small devices like phones maybe able share these same style sheets or support can be added the same way as with the Palm. 

<?xml-stylesheet href="xsl/speakers.xsl" type="text/xsl"?>
<?xml-stylesheet href="xsl/speakers-palm.xsl" type="text/xsl" media="palm"?>
<?cocoon-process type="xslt"?>
Listing 13 - Example of cocoon processors

Figure 6 - Web page on the Palm.

Printable Document

There are many advantages to using HTML.  HTML is simple, cross platform, an industry standard and there are a large amount of tools available to create and manage it.  On the other hand, HTML becomes a major problem when printing is involved, because HTML is intended to be free formed and interpreted by the consumer.  Printing HTML documents can produce undesirable results by including unnecessary elements such as menus (which are often graphics and waste ink or toner), page breaking in the middle a line or cutting off the right side of a document.  While there are products on the market which enable better printing of HTML documents, most individuals don't have them at their disposal and it requires additional browsing with the specialized printing software.  The W3C recognized this problem and added the concept of Formatting Objects (FO) to the XSL specification.

FO is a robust layout model and a namespace defined in the XSL specification.  The FO namespace includes formatting elements such as header/footers, margins and page breaks making it a better choice for printing then HTML.  FO however does not force the transformation output format.  In theory FO could be used to generate any format that supports formatting elements such as PDF, Postscript and RTF.  In this section FO will be used to generate industry standard PDF documents with the FOP formatter from the Apache XML project (See resources).

The examples included with FOP use the fo file extension convention.  Enabling JBuilder's syntax highlighter for the fo extension requires registering the extension as an XML Transformation Stylesheet.  To register the file extension choose Tools|IDE Options...|File Types.  Select XML Transformation Stylesheets from the list of Recognized file types.  Then add the fo to the list of Associated extensions.

A FO document consists of several layout objects shown in listing 14.  First, note that a FO document is an XML document just as is any XSL document.  FO documents begin and end with a root tag which defines the fo namespace.  Within the root tag there is a layout-master-set node and one or more page-sequence nodes.  The layout-master-set is a named collection of simple-page-master tags.  Each simple-page-master represents a different page layout that can be applied to a page-sequence.  A simple-page-master describes the format of an individual page such as the page height, width and margins.

<?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="content" />
  </fo:layout-master-set>

  <fo:page-sequence master-reference="content">
      <!-- Header --> 
      <fo:static-content flow-name="xsl-region-before" />

    <!-- Footer -->
    <fo:static-content flow-name="xsl-region-after" />

    <fo:flow flow-name="xsl-region-body">
       <!-- Body -->
    </fo:flow>
  </fo:page-sequence>
</fo:root>
Listing 14 - Basic FO document structure

page-sequence (Listing 15) nodes define individual content pages of a document applying a simple-page-master format.  A page-sequence may include a header or footer identified by static-content xsl-region-before or xsl-region-after respectively.  The flow (Listing 16) node contains the body of the page.  The flow node may include block (Listing 16) nodes which are analogous to HTML paragraphs, inline (Listing 17) nodes which are used to format a portion of text within a block, table (Listing 18), list (Listing 19) or external-graphic (Listing 16).

  <!-- defines the layout master -->
  <fo:layout-master-set>
    <fo:simple-page-master master-name="cover"
                           page-height="11in"
                           page-width="8.5in"
                           margin-top="2in"
                           margin-bottom="1in"
                           margin-left="1in"
                           margin-right="1in">
      <fo:region-body margin-top=".5in"/>
    </fo:simple-page-master>
    <fo:simple-page-master master-name="content"
                           page-height="11in"
                           page-width="8.5in"
                           margin-top=".5in"
                           margin-bottom=".5in"
                           margin-left="1in"
                           margin-right="1in">
      <fo:region-body margin-top=".25in"/>
      <fo:region-before extent=".25in"/>
      <fo:region-after extent=".25in"/>
    </fo:simple-page-master>

  </fo:layout-master-set>
Listing 15 - Examples of a cover page layout and the rest of the documents layout
<fo:page-sequence master-reference="cover">
  <fo:flow flow-name="xsl-region-body">
    <fo:block text-align="center">
      <fo:external-graphic src="file:images\actslogo.jpg" height="337.5px" width="259.5px"/>
    </fo:block>
    <fo:block font-family="Helvetica" font-size="36pt" text-align="center" space-before="1in">
       Formatting Objects Example
    </fo:block>
  </fo:flow>
</fo:page-sequence>
Listing 16 - Example of a cover page containing flow block and external-graphic nodes
    <fo:block space-before=".25in">
      Many organizations struggle to effectively maintain and communicate consistent
      information to multiple channels. Examples include browsers, cell phones, email
      and even printed materials. Come learn how XSLT and Formatting Objects can
      simplify this dilemma. We will introduce the syntax and functions necessary
      to transform <fo:inline color="red">XML</fo:inline> data into multiple formats.
      We will demonstrate using XSLT
      and Formatting Objects to create a static website and PDF document.
      The examples will use the Java API for <fo:inline font-family="Courier">XML</fo:inline>
      Processing (<fo:inline font-style="italic">JAXP</fo:inline>) and
      Transformations for XML (<fo:inline font-weight="bold">TRaX
      </fo:inline>) from the Apache XML Project.
    </fo:block>
Listing 17 - Example of block containing inlines
  <fo:table width="100%" space-before=".25in">
    <fo:table-column column-number="1" column-width="150px" />
    <fo:table-column column-number="2" column-width="350px" />
    <fo:table-body>
      <fo:table-row>
        <fo:table-cell column-number="1">
          <fo:block>
            Column 1, Row 1
          </fo:block>
        </fo:table-cell>
        <fo:table-cell column-number="2" text-align="center">
          <fo:block>
            Column 2, Row 1
          </fo:block>
        </fo:table-cell>
      </fo:table-row>
      <fo:table-row>
        <fo:table-cell column-number="1">
          <fo:block>
            Column 1, Row 2
          </fo:block>
        </fo:table-cell>
        <fo:table-cell column-number="2" text-align="center">
          <fo:block>
            Column 2, Row 2
          </fo:block>
        </fo:table-cell>
      </fo:table-row>
    </fo:table-body>
  </fo:table>
Listing 18 - Example of table
  <fo:list-block space-before="0.25em" space-after="0.25em">
    <fo:list-item space-after="0.5em">
      <fo:list-item-label start-indent="1em">
        <fo:block>
          1.
        </fo:block>
      </fo:list-item-label>
    <fo:list-item-body>
      <fo:block>
          item 1
      </fo:block>
    </fo:list-item-body>
    </fo:list-item>
    <fo:list-item space-after="0.5em">
      <fo:list-item-label start-indent="1em">
        <fo:block>
          2.
        </fo:block>
      </fo:list-item-label>
    <fo:list-item-body>
      <fo:block>
          item 2
      </fo:block>
    </fo:list-item-body>
    </fo:list-item>
  </fo:list-block>
Listing 19 - Example of list

The FO document will ultimately be embedded in a XSLT that provides the templates and conditionals.  From experience I have learned it is a good idea to build a fo document first to determine layout elements such as margins and headers are appropriate before including it in a XSLT otherwise it can become very confusing with so many tags. 

<xsl:stylesheet
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:fo="http://www.w3.org/1999/XSL/Format"
                version="1.0">

<xsl:template match="speakers">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">

  <!-- defines the layout master -->
  <fo:layout-master-set>
    <fo:simple-page-master master-name="cover"
                           page-height="11in"
                           page-width="8.5in"
                           margin-top="2in"
                           margin-bottom="1in"
                           margin-left="1in"
                           margin-right="1in">
      <fo:region-body margin-top=".5in"/>
    </fo:simple-page-master>
    <fo:simple-page-master master-name="content"
                           page-height="11in"
                           page-width="8.5in"
                           margin-top=".5in"
                           margin-bottom=".25in"
                           margin-left="1in"
                           margin-right="1in">
      <fo:region-body margin-top="1.5in"/>
      <fo:region-before extent="1.5in"/>
      <fo:region-after extent=".25in"/>
    </fo:simple-page-master>

  </fo:layout-master-set>

  <!-- starts actual layout -->
  <fo:page-sequence master-reference="cover">
    <fo:flow flow-name="xsl-region-body">
      <fo:block text-align="center">
        <fo:external-graphic src="file:..\images\cojug_metal.gif" />
      </fo:block>
      <fo:block font-family="Helvetica" font-size="36pt" text-align="center" space-before="1in">
         Central Ohio Java Days
      </fo:block>
      <fo:block font-family="Helvetica" font-size="30pt" text-align="center" space-before="1in">
         Conference and Exposition
         September 25 & 26, 2001
      </fo:block>
    </fo:flow>
  </fo:page-sequence>

  <fo:page-sequence master-reference="content">

    <fo:static-content flow-name="xsl-region-before">

      <fo:block font-family="Helvetica" font-size="15pt" text-align="right">
         Central Ohio Java Days
      </fo:block>
      <fo:block font-family="Helvetica" font-size="10pt" text-align="right">
         Conference and Exposition
      </fo:block>
      <fo:block font-family="Helvetica" font-size="10pt" text-align="right">
         September 25 & 26, 2001
      </fo:block>
    </fo:static-content>

    <fo:static-content flow-name="xsl-region-after">
      <fo:block font-family="Helvetica" font-size="10pt"
          text-align="center">
          Page <fo:page-number />
      </fo:block>
    </fo:static-content>

    <fo:flow flow-name="xsl-region-body">

     <xsl:apply-templates select="speaker" />

    </fo:flow>

  </fo:page-sequence>

</fo:root>

</xsl:template>

<xsl:template match="speaker">
  <fo:block font-family="Helvetica" font-size="15pt" space-before=".25in">
    <xsl:value-of select="name" />
  </fo:block>
  <fo:block font-family="Helvetica" font-size="10pt">
   <xsl:value-of select="title" />
  </fo:block>
  <fo:block font-family="Helvetica" font-size="10pt">
   <xsl:value-of select="company" />
  </fo:block>
  <fo:block font-family="Helvetica" font-size="8pt" space-before=".25in">
   <xsl:value-of select="bio" />
  </fo:block>
</xsl:template>

</xsl:stylesheet>
Listing 20 - Example of full FO document

Summary

XSL transformation is an extremely powerful technique that can be used for more than just building web pages.  Imagine using XSL to make EJBs more transportable between application servers.  If a standard XML document containing all the necessary deployment information could be defined XSL stylesheets could be used to generate vendor specific deployment descriptors making EJBs even more vendor neutral.  XSL can also simplify the sharing of information between organizations by allowing organizations to maintain independent data structures and just transform the data into individual formats. 

Resources

Download source code

Specifications (www.w3c.org )

Apache XML Project (xml.apache.org)

Apache Jakarta Project (jakarta.apache.org)

Mulberry Technology Inc. Quick Reference General XML/XSL Websites