Before we get into more advanced topics, we'll transform our Hello World document in other ways. We'll look through simple stylesheets that convert our small XML document into the following things:
A Scalable Vector Graphics (SVG) File
A PDF file
A Java program
A Virtual Reality Modeling Language (VRML) file
Our first example will convert our Hello World document into an SVG file:
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" doctype-public="-//W3C//DTD SVG 20001102//EN" doctype-system= "http://www.w3.org/TR/2000/CR-SVG-20001102/DTD/svg-20001102.dtd"/> <xsl:template match="/"> <svg width="8cm" height="4cm"> <g> <defs> <radialGradient id="MyGradient" cx="4cm" cy="2cm" r="3cm" fx="4cm" fy="2cm"> <stop offset="0%" style="stop-color:red"/> <stop offset="50%" style="stop-color:blue"/> <stop offset="100%" style="stop-color:red"/> </radialGradient> </defs> <rect style="fill:url(#MyGradient); stroke:black" x="1cm" y="1cm" width="6cm" height="2cm"/> <text x="4cm" y="2.2cm" text-anchor="middle" style="font-family:Verdana; font-size:24; font-weight:bold; fill:black"> <xsl:apply-templates select="greeting"/> </text> </g> </svg> </xsl:template> <xsl:template match="greeting"> <xsl:value-of select="."/> </xsl:template> </xsl:stylesheet>
As you can see from this stylesheet, most of the code here simply sets up the structure of the SVG document. This is typical of many stylesheets; once you learn what the output format should be, you merely extract content from the XML source document and insert it into the output document at the correct spot. When we transform the Hello World document with this stylesheet, here are the results:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20001102//EN" "http://www.w3.org/TR/2000/CR-SVG-20001102/DTD/svg-20001102.dtd"> <svg height="4cm" width="8cm"> <g> <defs> <radialGradient fy="2cm" fx="4cm" r="3cm" cy="2cm" cx="4cm" id="MyGradient"> <stop style="stop-color:red" offset="0%"/> <stop style="stop-color:blue" offset="50%"/> <stop style="stop-color:red" offset="100%"/> </radialGradient> </defs> <rect height="2cm" width="6cm" y="1cm" x="1cm" style="fill:url(#MyGradient); stroke:black"/> <text style="font-family:Verdana; font-size:24; font-weight:bold; fill:black" text-anchor="middle" y="2.2cm" x="4cm"> Hello, World! </text> </g> </svg>
When rendered in an SVG viewer, our Hello World document looks like Figure 2-2.
This screen capture was made using the Adobe SVG plug-in inside the Internet Explorer browser. You can find the plug-in at http://www.adobe.com/svg/.
We used Xalan to generate the SVG file:
java org.apache.xalan.xslt.Process -in greeting.xml -xsl svg-greeting.xsl -out greeting.svg
To convert the Hello World file into a PDF file, we'll first convert our XML file into formatting objects. The Extensible Stylesheet Language for Formatting Objects (XSL-FO) is an XML vocabulary that describes how content should be rendered. Here is our stylesheet:
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"> <xsl:output method="xml"/> <xsl:template match="/"> <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> <fo:layout-master-set> <fo:simple-page-master margin-right="75pt" margin-left="75pt" page-height="11in" page-width="8.5in" margin-bottom="25pt" margin-top="25pt" master-name="main"> <fo:region-before extent="25pt"/> <fo:region-body margin-top="50pt" margin-bottom="50pt"/> <fo:region-after extent="25pt"/> </fo:simple-page-master> <fo:page-sequence-master master-name="standard"> <fo:repeatable-page-master-alternatives> <fo:conditional-page-master-reference master-name="main" odd-or-even="any"/> </fo:repeatable-page-master-alternatives> </fo:page-sequence-master> </fo:layout-master-set> <fo:page-sequence master-name="standard"> <fo:flow flow-name="xsl-region-body"> <xsl:apply-templates select="greeting"/> </fo:flow> </fo:page-sequence> </fo:root> </xsl:template> <xsl:template match="greeting"> <fo:block line-height="40pt" font-size="36pt" text-align="center"> <xsl:value-of select="."/> </fo:block> </xsl:template> </xsl:stylesheet>
This stylesheet converts our Hello World document into the following XML file:
<?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="main" margin-top="25pt" margin-bottom="25pt" page-width="8.5in" page-height="11in" margin-left="75pt" margin-right="75pt"> <fo:region-before extent="25pt"/> <fo:region-body margin-bottom="50pt" margin-top="50pt"/> <fo:region-after extent="25pt"/> </fo:simple-page-master> <fo:page-sequence-master master-name="standard"> <fo:repeatable-page-master-alternatives> <fo:conditional-page-master-reference odd-or-even="any" master-name="main"/> </fo:repeatable-page-master-alternatives> </fo:page-sequence-master> </fo:layout-master-set> <fo:page-sequence master-name="standard"> <fo:flow flow-name="xsl-region-body"> <fo:block text-align="center" font-size="36pt" line-height="40pt"> Hello, World! </fo:block> </fo:flow> </fo:page-sequence> </fo:root>
We generated this file of formatting objects with this command:
java org.apache.xalan.xslt.Process -in greeting.xml -xsl fo-greeting.xsl -out greeting.fo
This lengthy set of tags uses formatting objects to describe the size of the page, the margins, font sizes, line heights, etc., along with the text extracted from our XML source document. Now that we have the formatting objects, we can use the Apache XML Project's FOP tool. After converting the formatting objects to PDF, the PDF file looks like Figure 2-3.
Here's the command used to convert our file of formatting objects into a PDF file:
java org.apache.fop.apps.CommandLine greeting.fo greeting.pdf
Our last two transformations don't involve XML vocabularies at all; they use XSLT to convert the Hello World document into other formats. Next, we'll transform our XML source document into the source code for a Java program. When the program is compiled and executed, it prints the message from the XML document to the console. Here's our stylesheet:
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <xsl:template match="/"> <xsl:text> public class Greeting { public static void main(String[] argv) { </xsl:text> <xsl:apply-templates select="greeting"/> <xsl:text> } } </xsl:text> </xsl:template> <xsl:template match="greeting"> <xsl:text>System.out.println("</xsl:text> <xsl:value-of select="normalize-space()"/> <xsl:text>");</xsl:text> </xsl:template> </xsl:stylesheet>
(Notice that we used <xsl:output method="text"> to generate text, not markup.) Our stylesheet produces these results:
public class Greeting { public static void main(String[] argv) { System.out.println("Hello, World!"); } }
We generated this Java code with the following command:
java org.apache.xalan.xslt.Process -in greeting.xml -xsl java-greeting.xsl -out Greeting.java
(Notice that the name of the generated file must start with an uppercase letter; Java requires that the name of the file must match the name of the class it contains. Also, this command should be entered on a single line.) When executed, our generated Java program looks like this:
C:\> java Greeting Hello, World!
Although generating Java code from an XML document may seem strange, it is actually a common technique. The FOP tool from the Apache XML Project does this; it defines a number of properties in XML, then generates the Java source code to create class definitions and get and set methods for each of those properties.
For our final transformation, we'll create a VRML file from our XML source document. Here's the stylesheet that does the trick:
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <xsl:template match="/"> <xsl:text>#VRML V2.0 utf8 Shape { geometry ElevationGrid { xDimension 9 zDimension 9 xSpacing 1 zSpacing 1 height [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ] colorPerVertex FALSE color Color { color [ 0 0 0, 1 1 1, 0 0 0, 1 1 1, 0 0 0, 1 1 1, 0 0 0, 1 1 1, 1 1 1, 0 0 0, 1 1 1, 0 0 0, 1 1 1, 0 0 0, 1 1 1, 0 0 0, 0 0 0, 1 1 1, 0 0 0, 1 1 1, 0 0 0, 1 1 1, 0 0 0, 1 1 1, 1 1 1, 0 0 0, 1 1 1, 0 0 0, 1 1 1, 0 0 0, 1 1 1, 0 0 0, 0 0 0, 1 1 1, 0 0 0, 1 1 1, 0 0 0, 1 1 1, 0 0 0, 1 1 1, 1 1 1, 0 0 0, 1 1 1, 0 0 0, 1 1 1, 0 0 0, 1 1 1, 0 0 0, 0 0 0, 1 1 1, 0 0 0, 1 1 1, 0 0 0, 1 1 1, 0 0 0, 1 1 1, 1 1 1, 0 0 0, 1 1 1, 0 0 0, 1 1 1, 0 0 0, 1 1 1, 0 0 0, ] } } } Transform { translation 4.5 1 4 children [ Shape { geometry Text { </xsl:text> <xsl:apply-templates select="greeting"/> <xsl:text> fontStyle FontStyle { justify "MIDDLE" style "BOLD" } } } ] } NavigationInfo { type ["EXAMINE","ANY"] } Viewpoint { position 4 1 10 } </xsl:text> </xsl:template> <xsl:template match="greeting"> <xsl:text>string"</xsl:text> <xsl:value-of select="normalize-space()"/> <xsl:text>"</xsl:text> </xsl:template> </xsl:stylesheet>
We generate our VRML document with the following command:
java org.apache.xalan.xslt.Process -in greeting.xml -xsl vrml-greeting.xsl -out greeting.wrl
As with our earlier stylesheet, our VRML-generating template is mostly boilerplate, with content from the XML source document added at the appropriate point. The <xsl:apply-templates> element is replaced with the value of the <greeting> element. The VRML code here draws a checkerboard, then draws the text from the XML document above it, floating in midair in the center of the document. A couple of views of the VRML version of our XML document are shown in Figure 2-4.
Although we haven't discussed any of the specific vocabularies or file formats we've used here, hopefully you understand that you can transform your XML documents into any useful format you can think of. Through the rest of the book, we'll cover several common tasks you can solve with XSLT, all of which build on the basics we've discussed here.
Copyright © 2002 O'Reilly & Associates. All rights reserved.