LISTING 1 FOPExample2.xsl

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   xmlns:fo="http://www.w3.org/1999/XSL/Format"
   version="1.0">

   <xsl:attribute-set name="h1">
     <xsl:attribute name="font-size">24pt</xsl:attribute>
     <xsl:attribute name="font-weight">bold</xsl:attribute>
     <xsl:attribute name="space-after">10pt</xsl:attribute>
   </xsl:attribute-set>

   <xsl:attribute-set name="table.data">
     <xsl:attribute name="table-layout">fixed</xsl:attribute>
     <xsl:attribute name="space-before">10pt</xsl:attribute>
     <xsl:attribute name="space-after">10pt</xsl:attribute>
   </xsl:attribute-set>

   <xsl:attribute-set name="table.data.th">
     <xsl:attribute name="background-color">#CCCCCC</xsl:attribute>
     <xsl:attribute name="border-style">solid</xsl:attribute>
     <xsl:attribute name="border-width">1pt</xsl:attribute>
     <xsl:attribute name="padding-start">0.3em</xsl:attribute>
     <xsl:attribute name="padding-end">0.2em</xsl:attribute>
     <xsl:attribute name="padding-before">2pt</xsl:attribute>
     <xsl:attribute name="padding-after">2pt</xsl:attribute>
     <xsl:attribute name="font-weight">bold</xsl:attribute>
     <xsl:attribute name="font-size">14pt</xsl:attribute>
   </xsl:attribute-set>

   <xsl:attribute-set name="table.data.td">
     <xsl:attribute name="border-style">solid</xsl:attribute>
     <xsl:attribute name="border-width">1pt</xsl:attribute>
     <xsl:attribute name="padding-start">0.3em</xsl:attribute>
     <xsl:attribute name="padding-end">0.2em</xsl:attribute>
     <xsl:attribute name="padding-before">2pt</xsl:attribute>
     <xsl:attribute name="padding-after">2pt</xsl:attribute>
  </xsl:attribute-set>

   <xsl:attribute-set name="list.item">
     <xsl:attribute name="space-before">0.4em</xsl:attribute>
     <xsl:attribute name="space-after">0.4em</xsl:attribute>
     <xsl:attribute name="relative-align">baseline</xsl:attribute>
   </xsl:attribute-set>


   <xsl:template match="/project">

      <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">

         <!-- defines page layout -->
         <fo:layout-master-set>
            <!-- layout for the first page -->
            <fo:simple-page-master
               master-name="only"
               page-height="8.5in"
               page-width="11in"
               margin-top="1cm"
               margin-bottom="2cm"
               margin-left="2.5cm" 
               margin-right="2.5cm">
               <fo:region-body margin-top="1.5cm"/>
               <fo:region-before extent="1.5cm"/>
               <fo:region-after extent="1.5cm"/>
            </fo:simple-page-master>
         </fo:layout-master-set>
         <!-- end: defines page layout -->

         <!-- actual layout -->
         <fo:page-sequence master-reference="only" initial-page-number="1">

            <!-- usage of page layout -->
            <!-- header -->
            <fo:static-content flow-name="xsl-region-before">
               <fo:block
                  text-align="end"
                  font-size="10pt" 
                  font-family="serif"
                  line-height="14pt" >
                  Customer List - p. <fo:page-number/>
               </fo:block>
            </fo:static-content>

            <fo:flow flow-name="xsl-region-body">

                <fo:block>
                  <xsl:apply-templates/>
                </fo:block>

            </fo:flow>
         </fo:page-sequence>
      </fo:root>
   </xsl:template>

   <!-- ==========================
   Basic HTML elements Begin here
   =============================== -->

   <!-- HTML tag <h1/> -->
   <xsl:template match="h1">
      <fo:block
	  xsl:use-attribute-sets="h1"><xsl:apply-templates/></fo:block>
   </xsl:template>

   <!-- paragraph <p/> -->
   <xsl:template match="p">
      <fo:block text-indent="1em" space-before="2pt" space-after="12pt">
         <!-- align attribute -->
         <xsl:if test="@align">
            <xsl:attribute name="text-align">
               <xsl:value-of select="@align"/>
            </xsl:attribute>
         </xsl:if>
         <xsl:apply-templates/>
      </fo:block>
   </xsl:template>

   <!-- Break <br/> -->
   <xsl:template match="br">
      <fo:block><xsl:text>
</xsl:text></fo:block>
   </xsl:template>

   <!-- Bold <strong/>-->
   <xsl:template match="b|strong">
      <fo:inline font-weight="bold"><xsl:apply-templates/></fo:inline>
   </xsl:template>

   <!-- Underline <u/> -->
   <xsl:template match="u">
      <fo:inline
	  text-decoration="underline"><xsl:apply-templates/></fo:inline>
   </xsl:template>

   <!-- Italic <em/> -->
   <xsl:template match="i|em">
      <fo:inline font-style="italic"><xsl:apply-templates/></fo:inline>
   </xsl:template>

   <!-- Strike-Through <strike/> -->
   <xsl:template match="strike">
      <fo:inline
	  text-decoration="line-through"><xsl:apply-templates/></fo:inline>
   </xsl:template>

   <!-- Forces Page Break <pagebreak/> -->
   <xsl:template match="pagebreak">
      <fo:block break-before="page"/>
   </xsl:template>

   <!-- HTML anchor tag, allows local anchor and external href -->
  <xsl:template match="a">
    <xsl:choose>
       <!-- If this is a named anchor, create an empty block with id -->
      <xsl:when test="@name">
        <xsl:if test="not(name(following-sibling::*[1]) = 'h1')">
          <fo:block line-height="0pt" space-after="0pt"
		   font-size="0pt" id="{@name}"/>
        </xsl:if>
      </xsl:when>
      <xsl:when test="@href">
        <fo:basic-link color="blue">
          <xsl:choose>
             <!-- if href starts with # then local anchor -->
            <xsl:when test="starts-with(@href, '#')">
              <xsl:attribute name="internal-destination">
                <xsl:value-of select="substring(@href, 2)"/>
              </xsl:attribute>
            </xsl:when>
            <!-- else, external hyperlink -->
            <xsl:otherwise>
              <xsl:attribute name="external-destination">
                <xsl:value-of select="@href"/>
              </xsl:attribute>
            </xsl:otherwise>
          </xsl:choose>
          <xsl:apply-templates select="*|text()"/>
        </fo:basic-link>
        <xsl:if test="starts-with(@href, '#')">
          <xsl:text> on page </xsl:text>
          <fo:page-number-citation ref-id="{substring(@href, 2)}"/>
        </xsl:if>
      </xsl:when>
    </xsl:choose>
  </xsl:template>

   <!-- Basic HTML image tag, allows height and width -->
  <xsl:template match="img">
     <fo:block space-after="12pt">
       <fo:external-graphic src="{@src}">
         <xsl:if test="@width">
           <xsl:attribute name="width">
             <xsl:choose>
               <xsl:when test="contains(@width, 'px')">
                 <xsl:value-of select="@width"/>
               </xsl:when>
               <xsl:otherwise>
                 <xsl:value-of select="concat(@width, 'px')"/>
               </xsl:otherwise>
             </xsl:choose>
           </xsl:attribute>
         </xsl:if>
         <xsl:if test="@height">
           <xsl:attribute name="height">
             <xsl:choose>
               <xsl:when test="contains(@height, 'px')">
                 <xsl:value-of select="@height"/>
               </xsl:when>
               <xsl:otherwise>
                 <xsl:value-of select="concat(@height, 'px')"/>
               </xsl:otherwise>
             </xsl:choose>
           </xsl:attribute>
         </xsl:if>
       </fo:external-graphic>
     </fo:block>
  </xsl:template>

   <!-- =======================
   HTML Tables begin here
   ============================ -->

   <!-- table tag -->
   <xsl:template match="table">
      <fo:table xsl:use-attribute-sets="table.data">
         <xsl:if test="@layout">
            <xsl:attribute name="table-layout">
               <xsl:value-of select="@layout"/>
            </xsl:attribute>
         </xsl:if>
         <xsl:if test="@width">
            <xsl:attribute name="inline-progression-dimension">
               <xsl:value-of select="@width"/>
            </xsl:attribute>
         </xsl:if>
         <xsl:for-each select="tr[1]/th|tr[1]/td">
            <fo:table-column>
               <xsl:if test="@colspan">
                  <xsl:attribute name="number-columns-repeated">
                     <xsl:value-of select="@colspan"/>
                  </xsl:attribute>
               </xsl:if>
               <xsl:attribute name="column-width">
                  <xsl:value-of select="floor(@width div 72)"/>in
               </xsl:attribute>
            </fo:table-column>
         </xsl:for-each>
         <fo:table-body>
            <xsl:apply-templates/>
         </fo:table-body>
    </fo:table>
   </xsl:template>

   <!-- Table Row -->
   <xsl:template match="tr">
      <fo:table-row>
         <xsl:apply-templates/>
      </fo:table-row>
   </xsl:template>

   <!-- HTML table tag <th> -->
   <xsl:template match="th">
      <fo:table-cell xsl:use-attribute-sets="table.data.th">
         <!-- call cell-span template to allow colspan and rowspan attributes
		 -->
         <xsl:call-template name="cell-span"/>
         <!-- valign attribute -->
         <xsl:if test="@valign">
            <xsl:attribute name="display-align">
               <xsl:value-of select="@valign"/>
            </xsl:attribute>
         </xsl:if>
         <fo:block>
            <!-- align attribute -->
            <xsl:if test="@align">
               <xsl:attribute name="text-align">
                  <xsl:value-of select="@align"/>
               </xsl:attribute>
            </xsl:if>
            <xsl:apply-templates/>
         </fo:block>
      </fo:table-cell>
   </xsl:template>

   <!-- HTML table tag <td> -->
   <xsl:template match="td">
      <fo:table-cell xsl:use-attribute-sets="table.data.td">
         <xsl:call-template name="cell-span"/>
         <xsl:if test="@valign">
            <xsl:attribute name="display-align">
               <xsl:value-of select="@valign"/>
            </xsl:attribute>
         </xsl:if>
         <fo:block>
            <xsl:if test="@align">
               <xsl:attribute name="text-align">
                  <xsl:value-of select="@align"/>
               </xsl:attribute>
            </xsl:if>
            <xsl:apply-templates/>
         </fo:block>
      </fo:table-cell>
   </xsl:template>

   <!-- This is called in other templates to allow rowspan and colspan
   attributes -->
   <xsl:template name="cell-span">
     <xsl:if test="@colspan">
       <xsl:attribute name="number-columns-spanned">
         <xsl:value-of select="@colspan"/>
       </xsl:attribute>
     </xsl:if>
     <xsl:if test="@rowspan">
       <xsl:attribute name="number-rows-spanned">
         <xsl:value-of select="@rowspan"/>
     </xsl:attribute>
     </xsl:if>
   </xsl:template>

   <!-- =======================
   HTML Lists Begin here
   ========================= -->

   <!-- Unordered Lists -->
   <xsl:template match="ul">
          <fo:list-block space-before="0.25em" space-after="0.25em">
              <xsl:apply-templates/>
          </fo:list-block>
   </xsl:template>

   <xsl:template match="ul/li">
       <fo:list-item xsl:use-attribute-sets="list.item">
         <fo:list-item-label end-indent="label-end()" start-indent=".75em">
           <fo:block>•</fo:block>
         </fo:list-item-label>
         <fo:list-item-body start-indent="body-start()">
           <fo:block>
             <xsl:apply-templates/>
           </fo:block>
         </fo:list-item-body>
       </fo:list-item>
  </xsl:template>

   <!-- Ordered Lists -->
   <xsl:template match="ol">
       <fo:list-block space-before="0.25em" space-after="0.25em">
           <xsl:apply-templates/>
       </fo:list-block>
   </xsl:template>

  <xsl:template match="ol/li">
       <fo:list-item xsl:use-attribute-sets="list.item">
         <fo:list-item-label end-indent="label-end()" start-indent=".75em">
           <fo:block>
              <!-- This allows type attribute to specify the number format -->
             <xsl:choose>
               <xsl:when test="@type='i'">
                 <xsl:number format="i. "/>
               </xsl:when>
               <xsl:when test="@type='I'">
                 <xsl:number format="I. "/>
               </xsl:when>
               <xsl:when test="@type='a'">
                 <xsl:number format="a. "/>
               </xsl:when>
               <xsl:when test="@type='A'">
                 <xsl:number format="A. "/>
               </xsl:when>
               <xsl:otherwise>
                 <xsl:number format="1. "/>
               </xsl:otherwise>
             </xsl:choose>
           </fo:block>
         </fo:list-item-label>
         <fo:list-item-body start-indent="body-start()">
           <fo:block>
             <xsl:apply-templates/>
           </fo:block>
         </fo:list-item-body>
       </fo:list-item>
  </xsl:template>

</xsl:stylesheet>

Listing 2 FOP.cfc

<cfcomponent>
   <!--- Initialize the FOP driver from xml.apache.org --->
   <cfset variables.driver = CreateObject("java", "org.apache.fop.apps.Driver")>
   <cfset variables.lockname = CreateUUID()>

   <cffunction name="ConvertFileToPDF" access="public">
      <cfargument name="foFile" type="string" required="true">
      <cfset var output = "" />
      <!--- Set up Java input source --->
      <cfset var input = CreateObject("java", "org.xml.sax.InputSource")>
      <cfset input.init( ARGUMENTS.foFile)>
      <!--- Proceed with PDF generation --->
      <cfset output = private_generatePDF(input)>
      <cfreturn output />
   </cffunction>

   <cffunction name="ConvertStringToPDF" access="public">
      <cfargument name="foString" type="string" required="true">
      <!--- Set up Java input source --->
      <cfset var reader = CreateObject("java", "java.io.StringReader")>
      <cfset var input = CreateObject("java", "org.xml.sax.InputSource")>
      <cfset reader.init(foString)>
      <cfset input.init(reader)>
      <!--- Proceed with PDF generation --->
      <cfset output = private_generatePDF(input)>
      <cfreturn output />
   </cffunction>

   <cffunction name="private_generatePDF" access="private">
      <cfargument name="input" type="any" required="true">
      <!--- Output stream for writing PDF file --->
      <cfset var output = CreateObject("java", "java.io.ByteArrayOutputStream")>
      <!--- Turn on the output stream --->
      <cfset output.init()>
      <!--- Hook the FOP driver to the input/output --->
      <cfset variables.driver.setInputSource(input)>
      <cfset variables.driver.setOutputStream(output)>
      <!--- Perform the actual PDF generation --->
      <cfset variables.driver.run()>
      <cfreturn output />
   </cffunction>
</cfcomponent>

Listing 3 modified piece of TransdformXML.cfm

<!--- now invoke the FOP component - pass in transformed xml and pdf file to be
created --->
<cfinvoke component="FOP" method="ConvertStringToPDF"
foString="#TransformedXMLCode#" returnvariable="FOPByteArray">

<!--- Now display PDF file to browser --->
<cfscript>
   //Retrieve the page context's response object
   context = getPageContext();
   context.setFlushOutput(false);
   response = context.getResponse().getResponse();
   out = response.getOutputStream();
   //Set the MIME type
   response.setContentType("application/pdf");
   //We must specify the content length but that's easy using the
   ByteArrayOutputStream's size method
   response.setContentLength(FOPByteArray.size());
   //Write the output to the browser and flush (to actually send)
   out.write(FOPByteArray.toByteArray());
   out.flush();
   //Close the output stream object
   out.close();
</cfscript>

Listing 4 FOPExample2Form.cfm

<!--- This is the page to start with --->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head><title>FOPExample2 Form</title></head>
<body>
<cfquery name="getTitles" datasource="exampleapps">
   select distinct title
   from tblEmployees
</cfquery>
<form action="FOPExample2Results.cfm" method="post">
Select 1 or more titles:<br>
<select name="titles" multiple>
   <cfoutput query="getTitles">
      <option value="'#getTitles.title#'">#getTitles.title#
   </cfoutput>
</select>
<input type="submit" value="submit">
</form>
</body>
</html>

Listing 5 FOPExample2Results.cfm

<!--- FOPExample2Form submits to this file where the results are displayed in a
pdf --->

<cfquery name="getemployees" datasource="exampleapps">
   select top 10 firstname,lastname,phone,startdate,title
   from tblEmployees
   where title in (#preserveSingleQuotes(FORM.titles)#)
   order by title,lastname,firstname
</cfquery>

<!--- Create an XML string containing query results --->
<cfxml variable="MyXml">
<project>
  <cfoutput>
  <img src="#ExpandPath('logo.jpg')#" height="50px" width="150px"/>
  </cfoutput>

  <p align="justify">This is a simple paragraph just to show you the basic text
  decoration commands. Notice the <strong>bold</strong>,
   <em>italic</em>, <u>underlined</u>, and
   <strike>strike-through</strike> text. Also notice that this text is
   indented like a paragraph with space before and after the block of text. Above
   you will see the use of an image and here you see the use of an anchor tag,
   <a href="http://xml.apache.org/fop/index.html">xml.apache.org/fop</a>.
   Next I will demonstrate the use of tables followed by an example of how to
   create lists. </p>

  <h1>TABLES</h1>
  <table>
    <cfoutput query="getemployees" group="title">
      <tr>
     <th colspan="3" align="center" valign="center"
	 width="200">#getemployees.title#</th>
     </tr>

<tr><td><strong>Name</strong></td><td><strong>Startdate
</strong></td><td><strong>Phone</strong></td></tr>
      <cfoutput>
        <tr>
      <td>#getemployees.lastname#, #getemployees.firstname#</td><td>#DateFormat
(getemployees.startdate,"mm/dd/yyyy")#</td><td>#getemployees.phone#</td>
      </tr>
      </cfoutput>
    </cfoutput>
  </table>

  <pagebreak/>

  <h1>UNORDERED LISTS</h1>
    <cfoutput query="getemployees" group="title">
   #getemployees.title#
     <ul>
      <cfoutput>
      <li>#getemployees.lastname#, #getemployees.firstname#</li>
      </cfoutput>
       </ul>
    </cfoutput>

  <pagebreak/>

  <h1>ORDERED LISTS</h1>
    <cfoutput query="getemployees" group="title">
   #getemployees.title#
     <ol>
      <cfoutput>
      <li type="1">#getemployees.lastname#, #getemployees.firstname#</li>
      </cfoutput>
       </ol>
    </cfoutput>

  </project>
</cfxml>

<!--- turn off debugging to prevent errors when displaying pdf content --->
<cfsetting showdebugoutput="No">

<!--- set filenames --->
<CFSET MyStylesheet = "FOPExample2.xsl">
<cfset pdfFile = "Result.pdf">

<!--- get contents of xsl file --->
<CFFILE ACTION="READ" FILE="#ExpandPath(MyStylesheet)#"
VARIABLE="XSLFileContent">

<!--- perform xml transformation with XMLFileContent agaisnt XSLFileContent --->
<CFSET TransformedXmlCode = XmlTransform(MyXML, XSLFileContent)>

<!--- now invoke the FOP component - pass in transformed xml and pdf file to be
created --->
<cfinvoke component="FOP" method="ConvertStringToPDF"
foString="#TransformedXMLCode#" returnvariable="FOPByteArray">

<!--- Now display PDF file to browser --->
<cfscript>
   //Retrieve the page context's response object
    context = getPageContext();
    context.setFlushOutput(false);
    response = context.getResponse().getResponse();
    out = response.getOutputStream();
   //Set the MIME type
   response.setContentType("application/pdf");
   //We must specify the content length but that's easy using the
   ByteArrayOutputStream's size method
   response.setContentLength(FOPByteArray.size());
   //Write the output to the browser and flush (to actually send)
   out.write(FOPByteArray.toByteArray());
   out.flush();
   //Close the output stream object
   out.close();
</cfscript>