![]() | |||||||||
![]() | ![]() | ![]() | ![]() | ![]() |
|||||
![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
|||
Christopher M. Judd - Judd Solutions, LLC.
http://www.juddsolutions.com
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.
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.
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).

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 |
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>
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)" />
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" />
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>
<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>
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>
<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>
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>
<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>
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"> <!-- </xsl:text>
<xsl:copy-of select="/"/>
<xsl:text disable-output-escaping="yes"> --></xsl:text>
</xsl:template>
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/.



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>
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>
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"?>

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>
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>
<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>
<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>
<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>
<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>
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>
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.
Specifications (www.w3c.org )
Apache Jakarta Project (jakarta.apache.org)
Mulberry Technology Inc. Quick Reference General XML/XSL Websites