13.4. Generating Multiple Output Files Using Saxon, Xalan, or XT

Example 13-4, drawn from the earlier Markup City examples, shows how <xt:document>, <saxon:output>, and Xalan's Redirect extensions can be used in one XSLT stylesheet. We use <xsl:fallback> to make sure the stylesheet can run on systems using any of these processors with almost identical output. Note that even though XT does not support <xsl:fallback> and element-available(), it will find its own recognized extensions in this stylesheet and process them, thus still giving consistent output.

Example 13-4. XML for stylesheets using multiple processors.
<?xml version="1.0"?>
<parkway>
             <thoroughfare>Governor Drive</thoroughfare>
             <thoroughfare name="Whitesburg Drive">
                   <sidestreet name="Bob Wallace Avenue">
                         <block>1st Street</block>
                         <block>2nd Street</block>
                         <block>3rd Street</block>
                   </sidestreet>
                   <sidestreet>Woodridge Street</sidestreet>
             </thoroughfare>
             <thoroughfare name="Bankhead">
                   <sidestreet name="Tollgate Road">
                         <block>First Street</block>
                         <block>Second Street</block>
                         <block>Third Street</block>
                   </sidestreet>
                   <sidestreet>Oak Drive</sidestreet>
             </thoroughfare>
</parkway>

In our example, we might want to chop up the <thoroughfare> elements in Markup City into individual XML data instances for further detailed work. Think of it as separating the city into districts for specific councilpersons to represent. We might want to use Clark's <xt:document> instruction element (or the <saxon:output> element) to do this. The territory to be divvied up consists of the offshoots of <parkway>.

Our goal is to get a single HTML page for each <thoroughfare>. In Example 13-5, we'll use <xt:document> and several LREs to do this (note that we've declared the XT namespace URI properly in the document element).

Example 13-5. Using the <xt:document> extension element.
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      version="1.0"
      xmlns:xt="http://www.jclark.com/xt"
      extension-element-prefixes="xt">

<xsl:output omit-xml-declaration="yes"/>

<xsl:template match="text()"/>

<xsl:template match="thoroughfare">
      <xt:document href="{@name | text()}.html">
      <html>
      <head><title><xsl:value-of select="@name |
text()"/></title></head>
      <body>
      <h2><xsl:value-of select="@name | text()"/></h2>
      <xsl:apply-templates/>
      </body>
      </html>
</xt:document>
</xsl:template>
<xsl:template match="sidestreet">
      <dl>
             <dt>
                   <xsl:value-of select="@name | text()" />
             </dt>
             <dd>
                   <ul>
                         <xsl:apply-templates/>
                   </ul>
             </dd>
</dl>
</xsl:template>

<xsl:template match="block">
      <li>
             <xsl:value-of select="@name | text()" />
      </li>
</xsl:template>

</xsl:stylesheet>

The attribute value template in the href attribute on <xt:document> provides access to the value of either the attribute or the text name of the <thoroughfare>.

The <xt:document> instruction element creates three new HTML files, one for each <thoroughfare>, containing the <sidestreet> and <block> children of each respective <thoroughfare>.

A contingency for this stylesheet would be very difficult if there were no processors that could handle the multiple outputs. In fact, it basically couldn't be done. We could make a contingency for whether a given processor that does multiple outputs is available though, for instance between XT or Saxon. In Example 13-6 we'll use a couple of more XSLT instruction elements, <xsl:when> and <xsl:otherwise>, children of <xsl:choose>.

We basically repeated the entire XT-dependent template, which used <xt:document>, within the context of an <xsl:choose> element. Each <xsl:when> element tests for the availability of an extension element, using the element-available() function. If the element is available, then the instructions under the <xsl:when> element are instantiated. If element-available() returns false for all the <xsl:when> elements, then the <xsl:otherwise> is instantiated. The <xsl:document> function shown here is defined in the XSLT 1.1 WD. Note that, since XT does not support the element-available() function, the stylesheet will fail using XT.

Example 13-6. Using contingencies for extension elements.
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      version="1.0"
      xmlns:xt="http://www.jclark.com/xt"
      xmlns:saxon="http://icl.com/saxon"
      xmlns:lxslt="http://xml.apache.org/xslt"
      xmlns:redirect="org.apache.xalan.xslt.extensions.Redirect"
      extension-element-prefixes="xt saxon lxslt redirect">

<xsl:output omit-xml-declaration="yes"/>

<xsl:template match="text()"/>

<xsl:template match="thoroughfare">
<xsl:choose>
      <xsl:when test="element-available('xt:document')">
            <xt:document href="{@name | text()}.html">
                  <html>
                        <head><title><xsl:value-of select="@name |
text()"/></title></head>
                       <body>
                               <h2><xsl:value-of select="@name |
text()"/></h2>
                               <xsl:apply-templates/>
                       </body>
                 </html>
           </xt:document>
     </xsl:when>
     <xsl:when test="element-available('saxon:output')">
           <saxon:output file="{@name | text()}.html">
                 <!-- use Saxon pre 6.2.2 version and the "file"
                       attribute for saxon:output support -->
                 <html>
                       <head><title><xsl:value-of select="@name |
text()"/></title></head>
                       <body>
                             <h2><xsl:value-of select="@name |
text()"/></h2>
                             <xsl:apply-templates/>
                      </body>
                 </html>
            </saxon:output>
      </xsl:when>
      <xsl:when test="element-available('xsl:document')">
            <xsl:document href="{@name | text()}.html">
                  <html>
                        <head><title><xsl:value-of select="@name |
text()"/></title></head>
                        <body>
                              <h2><xsl:value-of select="@name |
text()"/></h2>
                              <xsl:apply-templates/>
                        </body>
                  </html>
            </xsl:document>
     </xsl:when>

     <xsl:when test="element-available('redirect:write')">
           <redirect:write select="{@name | text()}.html">
                 <html>
                       <head><title><xsl:value-of select="@name |
text()"/></title></head>
                       <body>
                              <h2><xsl:value-of select="@name |
text()"/></h2>
                              <xsl:apply-templates/>
                       </body>
                 </html>
            </redirect:write>
      </xsl:when>
      <xsl:otherwise>
            <h2><xsl:value-of select="@name | text()"/></h2>
      <xsl:apply-templates/>
      </xsl:otherwise>
</xsl:choose>
</xsl:template>

<xsl:template match="sidestreet">
      <dl>
            <dt>
                 <xsl:value-of select="@name | text()" />
            </dt>
            <dd>
                 <ul>
                      <xsl:apply-templates/>
                 </ul>
            </dd>
      </dl>
</xsl:template>
<xsl:template match="block">
      <li>
            <xsl:value-of select="@name | text()" />
      </li>
</xsl:template>

</xsl:stylesheet>

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

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