Integrating XSLT and XSL-FO

Of course, XSL-FO is a part of the XSL Recommendation, and as such, you shouldn't think of it as being entirely separate from other extremely useful aspects of XSL and XSLT. In fact, one of the most powerful applications of XSL-FO involves building the XSL-FO sheets dynamically using XSL Transformations.

In the examples we have used so far in this chapter, we have inserted the data our stylesheets are formatting directly into the stylesheet itself. However, separating content from display is one of the points of a structured markup language such as XML. One way in which we can use an XSL-FO stylesheet while still having our data separate in an XML file is through XSLT.

For example, let's say we had a very simple table, which was simply a list of first and last names:

First Last
John Doe
Jane Doe
Billy Doe

Now, the names from this table should be stored in an instance document that looks something like this:

<people> 
 <name>
  <first>John</first>
  <last>Doe</last>
 </name>
 <name>
  <first>Jane</first>
  <last>Doe</last>
 </name>
 <name>
  <first>Billy</first>
  <last>Doe</last>
 </name>
</people>

Now, we could insert this information directly into an XSL-FO sheet:

<fo:table-body> 
 <fo:table-row>
  <fo:table-cell><fo:block>John</fo:block></fo:table-cell>
  <fo:table-cell><fo:block>Doe</fo:block></fo:table-cell>
 </fo:table-row>
 <fo:table-row>
  <fo:table-cell><fo:block>Jane</fo:block></fo:table-cell>
  <fo:table-cell><fo:block>Doe</fo:block></fo:table-cell>
 </fo:table-row>
 <fo:table-row>
  <fo:table-cell><fo:block>Billy</fo:block></fo:table-cell>
  <fo:table-cell><fo:block>Doe</fo:block></fo:table-cell>
 </fo:table-row>
<fo:table-body>

However, then what happens if we add another name to the XML file? We could cut and paste the new name into the stylesheet, but this can introduce errors, creates more work, and isn't how XML should be used.

Instead, we can build the stylesheet dynamically with XSLT, along the lines of

<xsl:for-each select="name"> 
  <fo:table-body>
  <fo:table-row>
  <fo:table-cell><fo:block>
  <xsl:value-of select="first"/>
  </fo:block></fo:table-cell>
  <fo:table-cell><fo:block>
  <xsl:value-of select="last"/>
  </fo:block></fo:table-cell>
  </fo:table-row>
  </fo:table-body>
</xsl:for-each>

By using XSLT to extract the information for our final document directly from the XML file, we can be confident that anytime the XML file is updated, we can simply create a new document, and the update will be reflected. Let's look at another example.

Let's say the information regarding some customer and product data is stored in an XML document, such as shown in Listing 10.6.

Listing 10.6. The XML Instance Document Containing Company Data
<?xml version="1.0"?>
<widgets-inc>
 <logo>logo.gif</logo>

 <catalog>
  <part number="AB2992">
   <item>Casters</item>
   <price>$19.99</price>
   <stock>Yes</stock>
  </part>

  <part number="CY9932">
   <item>Handle</item>
   <price>$5.99</price>
   <stock>Yes</stock>
  </part>

  <part number="DF9921">
   <item>Drawer</item>
   <price>$9.99</price>
   <stock>Yes</stock>
  </part>

  <part number="XV2201">
   <item>Storage Unit</item>
   <price>$99.99</price>
   <stock>No</stock>
  </part>

  <part number="FG2231">
   <item>Print Manual</item>
   <price>$2.99</price>
   <stock>Yes</stock>
  </part>
</catalog>

 <customers>
  <company>American Manufacturing</company>
  <company>Kyoto Manufacturing Concern</company>
  <company>Midwest Manufacturing</company>
  <company>Joe's Tools</company>
 </customers>
</widgets-inc>
					

The data contained in our .xml shown in Listing 10.6 is a simple XML file. However, it is important to note that the file does not contain any formatting information. The information contained in the .xml file is all data. We can use XSL to apply formatting information to the file, to create a final rendered document. We start with an XSLT stylesheet, which combines the data from the .xml file with the XSL-FO code necessary to render the final document.

For example, to build the list of customers this memo is intended for, we can use the following template:

<xsl:template match="customers"> 
 <xsl:for-each select="company">
  <fo:list-item>
   <fo:list-item-label start-indent="2pt" end-indent="label-end()">
    <fo:block>-</fo:block>
   </fo:list-item-label>
   <fo:list-item-body start-indent="body-start()">
    <fo:block>
     <xsl:value-of select="."/>
    </fo:block>
   </fo:list-item-body>
  </fo:list-item>
 </xsl:for-each>
</xsl:template>

This will cause a separate list item to be created with each <company> instance that is encountered when we process the XSLT sheet. We can do something similar to build the table that contains our part listing:

<xsl:template match="catalog"> 
 <xsl:for-each select="part">
  <fo:table-row background-color="white" color="black">
   <fo:table-cell padding="2pt">
    <fo:block>
     <xsl:value-of select="@number"/>
    </fo:block>
   </fo:table-cell>
   <fo:table-cell padding="2pt">
    <fo:block>
     <xsl:value-of select="item"/>
    </fo:block>
   </fo:table-cell>
   <fo:table-cell padding="2pt">
    <fo:block>
     <xsl:value-of select="price"/>
    </fo:block>
   </fo:table-cell>
   <fo:table-cell padding="2pt">
    <fo:block>
     <xsl:value-of select="stock"/>
    </fo:block>
   </fo:table-cell>
  </fo:table-row>
 </xsl:for-each>
</xsl:template>
					

This will populate our table with the part, and its associated information, for each part that is encountered in our XML document. This way, our table always reflects the content of the XML document. When we pull this information together into a complete XSLT stylesheet, we have the code shown in Listing 10.7.

Listing 10.7. The XSLT Stylesheet Used to Generate the Final XSL-FO Document
<?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 indent="yes"/>
 <xsl:template match="/">

 <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
  <fo:layout-master-set>
   <fo:simple-page-master master-name="Catalog"
       page-width="8.5in" page-height="11.0in"
       margin-top="0.5in" margin-bottom="0.5in"
       margin-left="0.5in" margin-right="0.5in">
    <fo:region-before extent="2.0in"/>
    <fo:region-body margin-top="2.0in" margin-bottom="1.0in"/>
    <fo:region-after  extent="1.0in"/>
   </fo:simple-page-master>
  </fo:layout-master-set>

  <fo:page-sequence master-name="Catalog">
   <fo:static-content flow-name="xsl-region-before">
    <fo:block text-align="center">
     <fo:external-graphic src="logo.gif"/>
    </fo:block>
    <fo:block text-align="center" font-family="sans-serif"
        font-size="18pt" font-weight="bold">
     Widgets, Inc.
    </fo:block>
   </fo:static-content>

   <fo:static-content flow-name="xsl-region-after">
    <fo:block text-align="center" font-family="sans-serif"
        font-size="12pt" font-style="italic">
     Last updated January 1, 2002
    </fo:block>
   </fo:static-content>

   <fo:flow flow-name="xsl-region-body">
    <fo:block font-family="sans-serif" font-size="12pt" padding="1pc">
     Catalog Update Issued to the Following Customers:
    </fo:block>
    <fo:list-block>
     <xsl:apply-templates select="//customers"/>
    </fo:list-block>
    <fo:block padding="1pc">
     Please consult your product manual for part numbers.
    </fo:block>
    <fo:table border-collapse="separate" border-style="solid"
        border-color="black" border-width="1pt">
     <fo:table-column column-width="8pc"/>
     <fo:table-column column-width="12pc"/>
     <fo:table-column column-width="8pc"/>
     <fo:table-column column-width="4pc"/>

     <fo:table-header>
      <fo:table-row background-color="black" color="red">
       <fo:table-cell number-columns-spanned="4" padding="2pt">
         <fo:block>Part Catalog</fo:block>
       </fo:table-cell>
      </fo:table-row>
     </fo:table-header>

     <fo:table-body>
      <fo:table-row background-color="gray" color="white">
       <fo:table-cell padding="2pt"><fo:block>Part Number</fo:block></fo:table-cell>
       <fo:table-cell padding="2pt"><fo:block>Description</fo:block></fo:table-cell>
       <fo:table-cell padding="2pt"><fo:block>Unit Price</fo:block></fo:table-cell>
       <fo:table-cell padding="2pt"><fo:block>In Stock</fo:block></fo:table-cell>
      </fo:table-row>
      <xsl:apply-templates select="//catalog"/>
     </fo:table-body>
    </fo:table>
   </fo:flow>
  </fo:page-sequence>
 </fo:root>
</xsl:template>

  <xsl:template match="customers">
   <xsl:for-each select="company">
    <fo:list-item>
     <fo:list-item-label start-indent="2pt" end-indent="label-end()">
      <fo:block>-</fo:block>
     </fo:list-item-label>
     <fo:list-item-body start-indent="body-start()">
      <fo:block>
       <xsl:value-of select="."/>
      </fo:block>
     </fo:list-item-body>
    </fo:list-item>
   </xsl:for-each>
  </xsl:template>

  <xsl:template match="catalog">
   <xsl:for-each select="part">
   <fo:table-row background-color="white" color="black">
    <fo:table-cell padding="2pt"><fo:block>
      <xsl:value-of select="@number"/>
    </fo:block></fo:table-cell>
    <fo:table-cell padding="2pt"><fo:block>
     <xsl:value-of select="item"/>
    </fo:block></fo:table-cell>
    <fo:table-cell padding="2pt"><fo:block>
     <xsl:value-of select="price"/>
    </fo:block></fo:table-cell>
    <fo:table-cell padding="2pt"><fo:block>
     <xsl:value-of select="stock"/>
    </fo:block></fo:table-cell>
   </fo:table-row>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>
					

Listing 10.8 shows the result of building the stylesheet automatically, which is similar to what we might have coded by hand; however, this is guaranteed to be in sync with the XML document, although the cut-and-paste method could easily introduce errors.

Listing 10.8. The xsl-fo Document That Can Be Used to Render the Final Document
<?xml version="1.0"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
 <fo:layout-master-set>
  <fo:simple-page-master master-name="Catalog"
      page-width="8.5in" page-height="11.0in"
      margin-top="0.5in" margin-bottom="0.5in"
      margin-left="0.5in" margin-right="0.5in">
   <fo:region-before extent="2.0in"/>
   <fo:region-body margin-top="2.0in" margin-bottom="1.0in"/>
   <fo:region-after  extent="1.0in"/>
  </fo:simple-page-master>
 </fo:layout-master-set>

 <fo:page-sequence master-name="Catalog">
  <fo:static-content flow-name="xsl-region-before">
   <fo:block text-align="center">
    <fo:external-graphic src="logo.gif"/>
   </fo:block>
   <fo:block text-align="center" font-family="sans-serif"
       font-size="18pt" font-weight="bold">
    Widgets, Inc.
   </fo:block>
  </fo:static-content>
  <fo:static-content flow-name="xsl-region-after">
   <fo:block text-align="center" font-family="sans-serif"
       font-size="12pt" font-style="italic">
    Last updated January 1, 2002
   </fo:block>
  </fo:static-content>

  <fo:flow flow-name="xsl-region-body">
   <fo:block font-family="sans-serif" font-size="12pt" padding="1pc">
    Catalog Update Issued to the Following Customers:
   </fo:block>
   <fo:list-block>
    <fo:list-item>
     <fo:list-item-label start-indent="2pt" end-indent="label-end()">
      <fo:block>-</fo:block>
     </fo:list-item-label>
     <fo:list-item-body start-indent="body-start()">
      <fo:block>American Manufacturing</fo:block>
     </fo:list-item-body>
    </fo:list-item>

    <fo:list-item>
     <fo:list-item-label start-indent="2pt" end-indent="label-end()">
      <fo:block>-</fo:block>
     </fo:list-item-label>
     <fo:list-item-body start-indent="body-start()">
      <fo:block>Kyoto Manufacturing Concern</fo:block>
     </fo:list-item-body>
    </fo:list-item>

    <fo:list-item>
     <fo:list-item-label start-indent="2pt" end-indent="label-end()">
      <fo:block>-</fo:block>
     </fo:list-item-label>
     <fo:list-item-body start-indent="body-start()">
      <fo:block>Midwest Manufacturing</fo:block>
     </fo:list-item-body>
    </fo:list-item>

    <fo:list-item>
     <fo:list-item-label start-indent="2pt" end-indent="label-end()">
      <fo:block>-</fo:block>
     </fo:list-item-label>
     <fo:list-item-body start-indent="body-start()">
       <fo:block>Joe's Tools</fo:block>
     </fo:list-item-body>
    </fo:list-item>
   </fo:list-block>

   <fo:block padding="1pc">
    Please consult your product manual for part numbers.
   </fo:block>
   <fo:table border-collapse="separate" border-style="solid"
       border-color="black" border-width="1pt">
    <fo:table-column column-width="8pc"/>
    <fo:table-column column-width="12pc"/>
    <fo:table-column column-width="8pc"/>
    <fo:table-column column-width="4pc"/>

    <fo:table-header>
     <fo:table-row background-color="black" color="red">
      <fo:table-cell number-columns-spanned="4" padding="2pt">
       <fo:block>Part Catalog</fo:block>
      </fo:table-cell>
     </fo:table-row>
    </fo:table-header>

    <fo:table-body>
     <fo:table-row background-color="grey" color="white">
      <fo:table-cell padding="2pt"><fo:block>Part Number</fo:block></fo:table-cell>
      <fo:table-cell padding="2pt"><fo:block>Description</fo:block></fo:table-cell>
      <fo:table-cell padding="2pt"><fo:block>Unit Price</fo:block></fo:table-cell>
      <fo:table-cell padding="2pt"><fo:block>In Stock</fo:block></fo:table-cell>
     </fo:table-row>
     <fo:table-row background-color="white" color="black">
      <fo:table-cell padding="4pt"><fo:block>AB2992</fo:block></fo:table-cell>
      <fo:table-cell padding="4pt"><fo:block>Casters</fo:block></fo:table-cell>
      <fo:table-cell padding="4pt"><fo:block>$19.99</fo:block></fo:table-cell>
      <fo:table-cell padding="4pt"><fo:block>Yes</fo:block></fo:table-cell>
     </fo:table-row>
     <fo:table-row background-color="white" color="black">
      <fo:table-cell padding="4pt"><fo:block>CY9932</fo:block></fo:table-cell>
      <fo:table-cell padding="4pt"><fo:block>Handle</fo:block></fo:table-cell>
      <fo:table-cell padding="4pt"><fo:block>$5.99</fo:block></fo:table-cell>
      <fo:table-cell padding="4pt"><fo:block>Yes</fo:block></fo:table-cell>
     </fo:table-row>
     <fo:table-row background-color="white" color="black">
      <fo:table-cell padding="4pt"><fo:block>DF9921</fo:block></fo:table-cell>
      <fo:table-cell padding="4pt"><fo:block>Drawer</fo:block></fo:table-cell>
      <fo:table-cell padding="4pt"><fo:block>$9.99</fo:block></fo:table-cell>
      <fo:table-cell padding="4pt"><fo:block>Yes</fo:block></fo:table-cell>
     </fo:table-row>
     <fo:table-row background-color="white" color="black">
      <fo:table-cell padding="4pt"><fo:block>XV2201</fo:block></fo:table-cell>
      <fo:table-cell padding="4pt"><fo:block>Storage Unit</fo:block></fo:table-cell>
      <fo:table-cell padding="4pt"><fo:block>$99.99</fo:block></fo:table-cell>
      <fo:table-cell padding="4pt"><fo:block>No</fo:block></fo:table-cell>
     </fo:table-row>
     <fo:table-row background-color="white" color="black">
      <fo:table-cell padding="4pt"><fo:block>FG2231</fo:block></fo:table-cell>
      <fo:table-cell padding="4pt"><fo:block>Print Manual</fo:block></fo:table-cell>
      <fo:table-cell padding="4pt"><fo:block>$2.99</fo:block></fo:table-cell>
      <fo:table-cell padding="4pt"><fo:block>Yes</fo:block></fo:table-cell>
     </fo:table-row>
    </fo:table-body>
   </fo:table>
  </fo:flow>
 </fo:page-sequence>

</fo:root>
					

When the .xsl stylesheet is applied to the .xml document, the result is an XSL-FO stylesheet, which can be rendered to produce the final document, as shown in Figure 10.11.

Figure 10.11. The final rendered output based on the .xml and .xsl files.


Depending on the structure of your XML files, and the desired output, you could even further customize the stylesheet—for example, pulling table headers from element or attribute names. The stylesheet can really be built as flexibly as you need.

The ability to utilize other areas of XSL, such as XSLT in conjunction with XSL-FO, is where you really begin to see the benefits of stylesheets. Using XML to create structured documents is the ideal way to separate content from presentation, and with XSLT you can then take that content and automatically generate the presentation files using all the features of XSL.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.183.210