XSLT Cookbook, from O'Reilly. Chapter 8 XML to HTML | 13

XSLT Cookbook, Chapter 8: XML to HTML

Discussion

Frames are useful for splitting a page into logical sections; however, using frames with visible or resizable borders is somewhat passé. Your stylesheet cannot be used for client-side transformation because it outputs many separate HTML files—one for the frameset, one for the left frame that lists salespeople, and a separate page for each salesperson.

The solution demonstrates an example that is dynamic and open-ended in terms of the number of separate pages that might be generated from a single XML file. However, cases in which frames can be used with client-side XSLT processing are more straightforward. Simply create a page containing a frameset where the frames hold separate XML documents, each with their own transformation:

<html>
   <head>
      <title>Frameset</title> 
   </head>
   <frameset rows="100%" cols="25%, 75%" border="0">
      <frame name="leftFrame" src="left.xml" noresize="">
      <frame name="mainFrame" src="main.xml" noresize="">
   </frameset>
   <body bgcolor="#FFFFFF" text="#000000"></body>
</html>

You must reference different XML documents for each frame because there can be only one xml-stylesheet processing instruction per file. However, you can still keep the content in one stylesheet by using an xinclude link and an XSLT template to process it.

left.xml looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="application/xml" href="left.xsl"?>
<xi:include href="salesBySalesperson.xml" 
            xmlns:xi="http://www.w3.org/2001/XInclude"/>

main.xml is similar:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="application/xml" href="main.xsl"?> 
<xi:include href="salesBySalesperson.xml"
            xmlns:xi="http://www.w3.org/2001/XInclude"/>

left.xsl and main.xsl contain a template that processes the xinclude element by using the document function:

<!-- left.xsl -->
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  
<xsl:output method="html"/>
   
<xsl:template match="xi:include" xmlns:xi="http://www.w3.org/2001/XInclude">
  <xsl:for-each select="document(@href,.)"> 
    <xsl:apply-templates/>
  </xsl:for-each>
</xsl:template> 
   
<xsl:template match="salesBySalesperson">
  <html>
   <head>
    <title>Salespeople</title>
   </head>
   <body bgcolor="#FFFFFF" text="#000000">
     <table>
      <tbody>
        <xsl:apply-templates/>
      </tbody>
    </table>
   </body>
  </html>
</xsl:template>
   
<xsl:template match="salesperson">
  <tr>
    <td>
      <a href="{concat('main.xml#',@name)}" target="mainFrame">
      <xsl:value-of select="@name"/></a>
    </td>
  </tr>
</xsl:template>
   
</xsl:stylesheet>
   
<!-- main.xsl -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html"/>
   
<xsl:template match="xi:include" xmlns:xi="http://www.w3.org/2001/XInclude">
  <xsl:for-each select="document(@href)"> 
    <xsl:apply-templates/>
  </xsl:for-each>
</xsl:template> 
   
<xsl:template match="salesBySalesperson">
    <html>
     <head>
      <title>Sales By Salesperson</title>
     </head>
    
     <body bgcolor="#FFFFFF" text="#000000">
     <xsl:apply-templates/>
     </body>
    </html>
</xsl:template>
   
<xsl:template match="salesperson">
     <h1><a name="{@name}"><center>Sales By Salesperson</center></a></h1>
      <h2><xsl:value-of select="@name"/></h2>
      <table border="1" cellpadding="3">
        <tbody >
          <tr>
            <th>SKU</th>
            <th>Sales (in US $)</th>
          </tr>
          <xsl:apply-templates />
        </tbody>
      </table>
      <div style="padding-top:1000"/>
</xsl:template>
   
<xsl:template match="product">
    <tr>
      <td><xsl:value-of select="@sku"/></td>
      <td align="right"><xsl:value-of select="@totalSales"/></td>
    </tr>
    
</xsl:template>
       
</xsl:stylesheet>

In the main.xsl stylesheet, you generate named anchors for each salesperson and separate them by a large amount of whitespace by using <div style="padding-top:1000"/>. In left.xsl, you generate links to the anchors. This generation crudely emulates behavior of the multipage example (Section 8.4.2).

See Also

Jeni Tennison's XSLT and XPath on the Edge (M&T, 2001) includes a detailed discussion of client-side XSLT processing with frames that shows how JavaScripting can create more sophisticated results.


Created: March 27, 2003
Revised: May 5, 2003

URL: http://webreference.com/programming/xslt/cookbook/chap8/2