Book HomeJava and XML, 2nd Edition

10.4. XSP

XSP stands for Extensible Server Pages, and is perhaps the most important development coming out of the Cocoon project. JavaServer Pages (JSP) allows tags and inline Java code to be inserted into an otherwise normal HTML page; when the JSP page is requested, the code is executed and the results are inserted right into the output HTML.[17] This has taken the Java and ASP worlds by storm, ostensibly simplifying server-side Java programming and allowing a separation of output and logic. However, there are still some significant problems. First, JSP does not really provide a separation of content and presentation. This is the same problem I have been talking about: changes to a banner, font color, or text size require the JSP (with the inline Java and JavaBean references) to be modified. JSP also mingles content (pure data) with presentation in the same way static HTML does. Second, there is no ability to transform the JSP into any other format, or use it across applications, because the JSP specification is designed primarily for delivery of output.

[17]This is a drastic oversimplification; the JSP is actually precompiled into a servlet, and a PrintWriter handles output. For more information on JSP, refer to JavaServerPages by Hans Bergsten (O'Reilly).

XSP remedies these problems. XSP is simply XML at its heart. Take a look at the sample XSP page in Example 10-7.

Example 10-7. A simple XSP page

<?xml version="1.0"?>
<?cocoon-process type="xsp"?>
<?cocoon-process type="xslt"?>
<?xml-stylesheet href="myStylesheet.xsl" type="text/xsl"?>

<xsp:page language="java" 
          xmlns:xsp="http://www.apache.org/1999/XSP/Core"
>
 
 <xsp:logic>
  private static int numHits = 0; 
  
  private synchronized int getNumHits( ) { 
   return ++numHits; 
  }
 </xsp:logic>

 <page>
  <title>Hit Counter</title>
 
  <p>I've been requested <xsp:expr>getNumHits( )</xsp:expr> times.</p>
 </page>
</xsp:page>

All XML conventions are followed. For now, think of the xsp:logic element content as "off-limits" to the XML parser; I'll discuss that later. Other than that, the entire document is simply XML with some new elements. In fact, it references an XSL stylesheet that has nothing remarkable about it, as you can see in Example 10-8.

Example 10-8. XSL stylesheet for the XSP page

<?xml version="1.0"?>

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

  <xsl:template match="page">
    <xsl:processing-instruction name="cocoon-format">
      type="text/html"
    </xsl:processing-instruction>
    <html>
      <head>
        <title><xsl:value-of select="title"/></title>
      </head>
      <body>
        <xsl:apply-templates select="*[not(self::title)]" />
      </body>
    </html>
  </xsl:template>

  <xsl:template match="p">
    <p align="center">
      <xsl:apply-templates />
    </p>
  </xsl:template>

</xsl:stylesheet>

Thus, XSP easily handles the first major problem of JSP: it separates content from presentation. This separation allows developers to handle content generation (the XSP page can be generated from a servlet or other Java code as well as being static), while XML and XSL authors can handle presentation and styling through modification of the XSL stylesheet applied to the XSP page. Just as easily, XSP solves the other significant deficiency of JSP: because XSP processing occurs before any stylesheets are applied, the resultant XML document can be transformed into any other format. XSP maintains all the advantages of XML, as the XSP page can be transferred between applications as well as being used just for presentation.

10.4.1. Creating an XSP Page

Now that you have had a taste of XSP, you can build your own XSP page. For this example, I'll continue looking at the XML documents already created. Let's revisit the XML document constructed earlier. This document represents a portion of this chapter and was transformed into a PDF document. Instead of simply using this document for display, assume that the author wants to let his editor view the document as it is being written. However, in addition to the text of the book, the editor should be able to see comments from the author that the public should not see: for example, questions about style and formatting. First, add the following comment to the chapterTen.xml file you built earlier:

<?xml version="1.0"?>

<?cocoon-process type="xslt"?>
<?xml-stylesheet href="XSL/JavaXML.fo.xsl" type="text/xsl"?>

<book>
 <cover>
  <title>Java and XML</title>
  <author>Brett McLaughlin</author>
 </cover>

 <contents>
  <chapter title="Web Publishing Frameworks" number="10">
      
   <paragraph> This chapter begins looking at specific Java and XML 
topics. So far, I have covered the basics of using XML from Java, 
looking at the SAX, DOM, JDOM, and JAXP APIs to manipulate XML and the 
fundamentals of using and creating XML itself. Now that you have a grasp 
on using XML from your code, I want to spend time on specific 
applications. The next six chapters represent the most significant 
applications of XML, and, in particular, how those applications are 
implemented in the Java space. While there are literally thousands of 
important applications of XML, the topics in these chapters are those 
that continually seem to be in the spotlight, and that have a significant
potential to change the way traditional development processes occur. 
   </paragraph>
   
   <authorComment>Mike - Do you think the following sidebar is a little
   much? I could easily leave it out if it's still clear without it.
   </authorComment>

    <sidebar title="The More Things Change, the More They Stay the Same">
Readers of the first edition of this book will find that 
much of this chapter on Cocoon is the same as the first edition. Although
I promised you that Cocoon 2 would be out by now, and although I expected
to be writing a chapter on Cocoon 2, things haven't progressed as quickly
as expected. Stefano Mazzochi, the driving force behind Cocoon, finally 
got around to finishing school (good choice, Stefano!), and so 
development on Cocoon 2 has significantly slowed. The result is that 
Cocoon 1.x is still the current development path, and you should stick 
with it for now. I've updated the section on Cocoon 2 to reflect what is 
coming, and you should keep an eye out for more Cocoon-related books from
O'Reilly in the months to come.</sidebar>

   <paragraph> I'll begin this look at hot topics with the one XML 
application that seems to have generated the largest amount of excitement
in the XML and Java communities: the web publishing framework. Although 
I have continually emphasized that generating presentation from content 
is perhaps over-hyped when compared to the value of the portable data 
that XML provides, using XML for presentation styling is still very 
important. This importance increases when looking at web-based 
applications.</paragraph>
  </chapter>

 </contents>
</book>

With this comment in your XML document, add a corresponding entry into your XSL stylesheet, JavaXML.fo.xsl :

  <xsl:template match="sidebar">
    <fo:block font-size="14pt"
              font-style="italic"
              color="blue" 
              space-before.optimum="16pt" 
              text-align="center">
      <xsl:value-of select="@title" />
    </fo:block>
    <fo:block font-size="12pt"
              color="blue" 
              space-before.optimum="16pt" 
              text-align="justify">
      <xsl:apply-templates/>
    </fo:block>
  </xsl:template>

  <xsl:template match="authorComment">
   <fo:block font-size="10pt" 
             font-style="italic" 
             color="red" 
             space-before.optimum="12pt" 
             text-align="justify">
     <xsl:apply-templates/>
   </fo:block>
  </xsl:template>

The comments appear slightly smaller than the rest of the text, italicized, and in red. Now it's possible to turn your XML document into an XSP page (as in Example 10-9) by adding processing instructions for Cocoon and surrounding the elements within a new root element, xsp:page.

Example 10-9. Turning chapterTen.xml into an XSP page

<?xml version="1.0"?>

<?cocoon-process type="xsp"?>
<?cocoon-process type="xslt"?>
<?xml-stylesheet href="XSL/JavaXML.fo.xsl" type="text/xsl"?>

<xsp:page language="java"
          xmlns:xsp="http://www.apache.org/1999/XSP/Core"
>
<book>
 <cover>
  <title>Java and XML</title>
  <author>Brett McLaughlin</author>
 </cover>

 <contents>
  <chapter title="Web Publishing Frameworks" number="10">
  <!-- Text of chapter -->
  </chapter>
 </contents>
</book>
</xsp:page>

Before adding XSP logic to determine whether to show the comment, build a simple HTML page letting the viewer indicate if he is the book's editor. In a real application, this could be a page that handles authentication and determines a user's role; for this example, it lets the user select author, editor, or just a curious reader, and enter a password for verification. An HTML page that does this is shown in Example 10-10. Save this file as entry.html in your context's document root.

Example 10-10. Entry page for chapterTen.xml XSP page

<html>
 <head>
  <title>Welcome to the Java and XML Book in Progress</title>
 </head>

 <body>
  <h1 align="center"><i>Java and XML</i> Book in Progress</h1>
  <center>
   <form action="/cocoon/chapterTen.xml" method="POST">
    Select your role:
    <select name="userRole">
     <option value="author">I'm the Author</option>
     <option value="editor">I'm the Editor</option>
     <option value="reader">I'm a Reader</option>
    </select>
    <br />
    Enter your password:
    <input type="password" name="password" size="8" />
    <br /><br />
    <input type="submit" value="Take me to the Book!" />
   </form>
  </center>
 </body>
</html>

Also notice that this HTML submits the form data directly to your XSP page. In this example, the XSP acts like a servlet. It reads the request parameters, determines what user role was selected, authenticates that role using the password supplied, and finally determines whether the author comments should be shown. To begin, define a boolean variable; this variable holds the result of comparing the request parameters to see if the user is an author or editor and supplied a correct password. The value of the variable is checked, and if it is true, the authorComment element is displayed; surround the authorComment element with the XSP directives shown here:


   <xsp:logic>
    boolean authorOrEditor = false;

    // Perform logic to see if user is an author or editor

    if (authorOrEditor) {
      <xsp:content>   
        <authorComment>Mike - Do you think the following sidebar is 
        a little much? I could easily leave it out if it's still 
        clear without it.</authorComment>
      </xsp:content>
    }
   </xsp:logic>

This shouldn't look strange; other than the XSP-specific tags, you're just defining a variable and checking its value. If the variable evaluates to true, the authorComment element is added to the XSP page's output; otherwise, the element is not included in the output. One interesting thing to note is that the actual XML document output is surrounded within the xsp:logic block with an xsp:content element (which in turn is within the outer xsp:page element), ensuring that the XSP processor does not try to interpret any elements or text within the block as XSP structures. The same code in JSP might look like this:

<%
 if (authorOrEditor) {
%>
        <authorComment>Mike - Do you think the following sidebar is 
        a little much? I could easily leave it out if it's still 
        clear without it.</authorComment>
<%
 }
%>

This is not very structured, as the JSP block ends before the authorComment element begins; then a new block is appended after the element, which closes the brackets opened in the first JSP block. It is very easy to mismatch coding structures or forget to add matching JSP blocks. The XSP paradigm forces every open element to be closed (standard XML well-formedness) and one block of code is matched with one element.

With these logical structures in place, the XSP page just needs to interpret the request parameters. You can use the built-in XSP variable request, which mimics the javax.servlet.http.HttpServletRequest object. The following code additions read the values of the userRole and password request parameters (if they exist). The value of userRole is then compared with the roles that can see the comments ("author" and "editor"). If a match occurs, the password is checked as well. If the password matches the key for the supplied role, the boolean variable is set to true, and the authorComment element is part of the XML output:

   <xsp:logic>
    boolean authorOrEditor = false;

    // Perform logic to see if user is an author or editor
 <![CDATA[
 String[] roleValues = request.getParameterValues("userRole");
 String[] passwordValues = request.getParameterValues("password");
 if ((roleValues != null) && (passwordValues != null)) {
   String userRole = roleValues[0];
   String password = passwordValues[0];
   if (userRole.equals("author") && password.equals("brett")) {
     authorOrEditor = true;
   } else
     if (userRole.equals("editor") && password.equals("mike")) {
     authorOrEditor = true;
   }
 }
 ]]>
    
    if (authorOrEditor) {
...

Notice that I enclose a good bit of this logic within a CDATA tag. Remember that XSP is still evaluated as XML, and must follow the rules of an XML document; however, the double quotes and ampersands used in the Java fragments are not allowed in XML documents. Instead of escaping these characters and getting a very strange XSP fragment, you can use the CDATA tag and write standard Java code. Without it, you would have to code as follows:

<xsp:logic>
 boolean authorOrEditor = false;

 String[] roleValues = 
   request.getParameterValues(&quot;userRole&quot;);
 String[] passwordValues = 
   request.getParameterValues(&quot;password&quot;);
 if ((roleValues != null) &amp;&amp; 
     (passwordValues != null)) {
   String userRole = roleValues[0];
   String password = passwordValues[0];
   if (userRole.equals("author") &amp;&amp; 
       password.equals("brett")) {
     authorOrEditor = true;
   } else
   if (userRole.equals("editor") &amp;&amp; 
       password.equals("mike")) {
     authorOrEditor = true;
   }
 }
...
</xsp:logic>

Now test the entry page and the resultant PDF generated from the XML. You should get output similar to Figure 10-8 if you direct your web browser to http://<hostname>:<port>/cocoon/entry.html.

Figure 10-8

Figure 10-8. Entry page for chapterTen.xml XSP page

Select the role of author and use the password "brett", or select the editor role with the password "mike". Either case gives you the PDF output shown in Figure 10-9.

Figure 10-9

Figure 10-9. XSP output with author or editor role

The one thing that has not yet been done is to isolate the page's logic from its content. Just as JSP allows inclusion of JavaBeans to abstract the content and presentation from the logic of an application component, XSP allows tag libraries to be created. These tag libraries allow XML tags to trigger the matching code within a tag library.

10.4.2. Using XSP Tag Libraries

In addition to showing comments based on the user's identity, the XSP page should indicate that the chapter is in a draft state. The current date can be shown to indicate the date of the draft (then the date is frozen when the chapter is considered complete). Instead of adding inline Java tags to load the current date, simply create a custom tag library for this purpose. It's also worth looking at the process of creating an XSP element that takes in the chapter number and title and formats the complete title. This function will handle the insertion of the draft date, as well. To do this, you first need to create a tag library that is available to the XSP page. Much of the tag library is based on an XSL stylesheet. You can start with the skeleton shown in Example 10-11, which passes anything it receives through as output. Save this skeleton as JavaXML.xsp.xsl in the XSL/ subdirectory. Be sure to include the javaxml2 namespace declaration, as it will be used to match elements within that namespace used in the XSP pages.

Example 10-11. Skeleton of XSP tag library

<?xml version="1.0"?>

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xsp="http://www.apache.org/1999/XSP/Core"
  xmlns:javaxml2="http://www.oreilly.com/javaxml2"
>
  <xsl:template match="xsp:page">
    <xsp:page>
      <xsl:copy>
        <xsl:apply-templates select="@*"/>
      </xsl:copy>

      <xsl:apply-templates/>
    </xsp:page>
  </xsl:template>

  <xsl:template match="@*|*|text()|processing-instruction( )">
    <xsl:copy>
      <xsl:apply-templates 
           select="@*|*|text()|processing-instruction( )"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

By matching the xsp:page tag, it's possible to ensure that all elements are matched and handled within this stylesheet; this is referred to as a logicsheet in XSP parlance. Now add Java methods for the templates within this logicsheet to call:

  <xsl:template match="xsp:page">
    <xsp:page>
      <xsl:copy>
        <xsl:apply-templates select="@*"/>
      </xsl:copy>

      <xsp:structure>
        <xsp:include>java.util.Date</xsp:include>
        <xsp:include>java.text.SimpleDateFormat</xsp:include>
      </xsp:structure>

      <xsp:logic>
        private static String getDraftDate( ) {
          return (new SimpleDateFormat("MM/dd/yyyy"))
            .format(new Date( ));
        }

        private static String getTitle(int chapterNum, 
                                       String chapterTitle) {
          return chapterNum + ". " + chapterTitle;
        }
      </xsp:logic>

      <xsl:apply-templates/>
    </xsp:page>
  </xsl:template>

Several new XSP elements are introduced here. First, xsp:structure is used to surround several xsp:include statements. These work just like their Java counterpart, import, making the specified Java classes available for use by their unqualified names (rather than the complete packaged names). Once these are available, the logicsheet defines and implements two methods: one that creates a chapter title from the chapter number and textual title, and one that returns the current date as a formatted String. These methods are available to any elements within this logicsheet.

Now define the element that specifies when an XSP result should replace an XML element. The javaxml2-associated namespace is already declared in the root element, so it can be used as the namespace for the new tag library elements. Add the following template into your logicsheet:


  <!-- Create formatted title -->
  <xsl:template match="javaxml2:draftTitle">
    <xsp:expr>getTitle(<xsl:value-of select="@chapterNum" />,
                       "<xsl:value-of select="@chapterTitle" />")
    </xsp:expr> (<xsp:expr>getDraftDate( )</xsp:expr>)
  </xsl:template>

  <xsl:template match="@*|*|text()|processing-instruction( )">
    <xsl:copy>
      <xsl:apply-templates 
           select="@*|*|text()|processing-instruction( )"/>
    </xsl:copy>
  </xsl:template>

When a document with this tag library uses the element javaxml2:draftTitle (or just draftTitle if the default namespace is mapped to http://www.oreilly.com/javaxml2), the result of the method getTitle( ) is prepended to the value of the getDraftDate( ) method. The javaxml2:draftTitle element also expects two attributes to be declared: the chapter number and the textual title of the chapter. Signify to the XSP processor that you are calling a defined method by enclosing the method call within a set of <xsp:expr> tags. To indicate that the second argument (the chapter title) is a String, it should be enclosed within quotes. Since the chapter number should be treated as an int, it is left without quotation marks.

Once you have completed the XSP logicsheet (available online at the book's web site as well), you need to make it accessible to Cocoon. This can be done one of two ways. The first is to specify the location of the file as a URI, which allows the servlet engine (and therefore Cocoon) to locate the logicsheet. For example, to add the XSP logicsheet to Cocoon's set of resources through its URI, you could add the following lines to the cocoon.properties file on a Unix-based system:

# Set the libraries associated with the given namespace.
# Use the syntax:
#   processor.xsp.logicsheet.<namespace-tag>.<language> = URL to file
# where "URL to file" is usually starting with file:// if you locate
# your custom library in your file system.
processor.xsp.logicsheet.context.java  =resource://org/apache/cocoon/processor/
xsp/library/java/context.xsl
processor.xsp.logicsheet.cookie.java   =resource://org/apache/cocoon/processor/
xsp/library/java/cookie.xsl
processor.xsp.logicsheet.global.java   =resource://org/apache/cocoon/processor/
xsp/library/java/global.xsl
processor.xsp.logicsheet.request.java  =resource://org/apache/cocoon/processor/
xsp/library/java/request.xsl
processor.xsp.logicsheet.response.java =resource://org/apache/cocoon/processor/
xsp/library/java/response.xsl
processor.xsp.logicsheet.session.java  =resource://org/apache/cocoon/processor/
xsp/library/java/session.xsl
processor.xsp.logicsheet.util.java     = 
  resource://org/apache/cocoon/processor/xsp/library/java/util.xsl
processor.xsp.logicsheet.sql.java      = 
  resource://org/apache/cocoon/processor/xsp/library/sql/sql.xsl
processor.xsp.logicsheet.esql.java      = 
  resource://org/apache/cocoon/processor/xsp/library/sql/esql.xsl
processor.xsp.logicsheet.fp.java       = 
  resource://org/apache/cocoon/processor/xsp/library/fp/fp.xsl

processor.xsp.library.JavaXML.java = 
  file:///usr/local/jakarta-tomcat/webapps/cocoon/XSL/JavaXML.xsp.xsl

For Windows systems, this would be:

# Set the libraries associated with the given namespace.
# Use the syntax:
#   processor.xsp.logicsheet.<namespace-tag>.<language> = URL to file
# where "URL to file" is usually starting with file:// if you locate
# your custom library in your file system.
processor.xsp.logicsheet.context.java  =resource://org/apache/cocoon/processor/
xsp/library/java/context.xsl
processor.xsp.logicsheet.cookie.java   =resource://org/apache/cocoon/processor/
xsp/library/java/cookie.xsl
processor.xsp.logicsheet.global.java   =resource://org/apache/cocoon/processor/
xsp/library/java/global.xsl
processor.xsp.logicsheet.request.java  =resource://org/apache/cocoon/processor/
xsp/library/java/request.xsl
processor.xsp.logicsheet.response.java =resource://org/apache/cocoon/processor/
xsp/library/java/response.xsl
processor.xsp.logicsheet.session.java  =resource://org/apache/cocoon/processor/
xsp/library/java/session.xsl
processor.xsp.logicsheet.util.java     = 
  resource://org/apache/cocoon/processor/xsp/library/java/util.xsl
processor.xsp.logicsheet.sql.java      = 
  resource://org/apache/cocoon/processor/xsp/library/sql/sql.xsl
processor.xsp.logicsheet.esql.java      = 
  resource://org/apache/cocoon/processor/xsp/library/sql/esql.xsl
processor.xsp.logicsheet.fp.java       = 
  resource://org/apache/cocoon/processor/xsp/library/fp/fp.xsl

processor.xsp.library.javaxml2.java = 
  file:///C:/java/jakarta-tomcat/webapps/cocoon/XSL/JavaXML.xsp.xsl

While this is handy for testing, it is not a very good solution for uncoupling your logicsheets from the servlet engine, and also adds quite a bit of maintenance overhead when adding new logicsheets: a new line would have to be added to the cocoon.properties file for new logicsheets to be available. Allowing specification of a resource in the servlet engine's classpath is an alternative method for loading logicsheets. This lets you add custom logicsheets to a jar file, and that jar file to the servlet engine classpath (which in Tomcat simply means adding that archive to the lib/ directory!). In addition, new logicsheets can be put within the jar file, providing a central location for storing your custom XSP logicsheets. From the XSL/ subdirectory in your web server's document root, perform the following command to create a jar file that contains your logicsheet:

jar cvf logicsheets.jar JavaXML.xsp.xsl

Move the created logicsheets.jar archive into your TOMCAT_HOME/lib/ directory with the other Cocoon libraries. That will ensure that Tomcat loads the library on startup. With your logicsheet available, you can now let Cocoon know where to look for javaxml2-associated namespace references within XSP pages. Edit the cocoon.properties file; locate the section that lists the various Cocoon XSP resources, and add the new logicsheet reference:

# Set the libraries associated with the given namespace.
# Use the syntax:
#   processor.xsp.logicsheet.<namespace-tag>.<language> = URL to file
# where "URL to file" is usually starting with file:// if you locate
# your custom library in your file system.
processor.xsp.logicsheet.context.java  =resource://org/apache/cocoon/processor/
xsp/library/java/context.xsl
processor.xsp.logicsheet.cookie.java   =resource://org/apache/cocoon/processor/
xsp/library/java/cookie.xsl
processor.xsp.logicsheet.global.java   =resource://org/apache/cocoon/processor/
xsp/library/java/global.xsl
processor.xsp.logicsheet.request.java  =resource://org/apache/cocoon/processor/
xsp/library/java/request.xsl
processor.xsp.logicsheet.response.java =resource://org/apache/cocoon/processor/
xsp/library/java/response.xsl
processor.xsp.logicsheet.session.java  =resource://org/apache/cocoon/processor/
xsp/library/java/session.xsl
processor.xsp.logicsheet.util.java     = 
  resource://org/apache/cocoon/processor/xsp/library/java/util.xsl
processor.xsp.logicsheet.sql.java      = 
  resource://org/apache/cocoon/processor/xsp/library/sql/sql.xsl
processor.xsp.logicsheet.esql.java      = 
  resource://org/apache/cocoon/processor/xsp/library/sql/esql.xsl
processor.xsp.logicsheet.fp.java       = 
  resource://org/apache/cocoon/processor/xsp/library/fp/fp.xsl

processor.xsp.logicsheet.javaxml2.java = resource://JavaXML.xsp.xsl

Because the logicsheet is not nested within any subdirectories in the logicsheets.jar file, you can simply use the name of the logicsheet as its resource path. Finally, restart your servlet engine (this also ensures that Tomcat auto-loads the new library). This will reload the cocoon.properties file, and the logicsheet will be available for use. As the Cocoon engine is used to handle requests, any XSP page that declares that it uses the javaxml2 namespace will have access to the logicsheet specified as the javaxml2 library. So the XSP page needs to add a namespace declaration for the javaxml2 namespace:

<?xml version="1.0"?>

<?cocoon-process type="xsp"?>
<?cocoon-process type="xslt"?>
<?xml-stylesheet href="XSL/JavaXML.fo.xsl" type="text/xsl"?>

<xsp:page language="java"
          xmlns:xsp="http://www.apache.org/1999/XSP/Core"
          xmlns:javaxml2="http://www.oreilly.com/javaxml2"
>
<book>
  <!-- Book content -->
</book>
</xsp:page>

With the tag library now available for use, you can finally add in the javaxml2:draftTitle element to your XML document, chapterTen.xml:

<contents>
  <chapter title="Web Publishing Frameworks" number="10">
    <javaxml2:draftTitle chapterNum="10"
                         chapterTitle="Web Publishing Framework" />
...

Replace the hardcoded chapter title with the element defined in the XSP tag library with the following change to your JavaXML.fo.xsl stylesheet:

  <xsl:template match="chapter">
    <fo:block font-size="24pt" 
              text-align-last="center" 
              space-before.optimum="24pt">
<!--              
      <xsl:value-of select="@number" />.
      <xsl:value-of select="@title" />
-->      
      <xsl:apply-templates/>
    </fo:block>
  </xsl:template>

This should generate the title with the chapter number, chapter title, and the date of the draft. Accessing this new version of the XSP page results in the output shown in Figure 10-10.

Figure 10-10

Figure 10-10. Output using XSP tag library

I have only scratched the surface of XSP. Even this simple example allows the title to be converted to a different form by modifying only the XSP logicsheet -- not the content or presentation of the page -- when the chapter is complete. In the same way, XSP allows the creation of very strict contracts separating presentation from content from application logic. Adding server-side Java components such as Enterprise JavaBeans can bring business logic into the equation. Rather than using a less flexible solution like JSP that is coupled to HTML and a presentation format, using XSP allows a looser coupling of components and thus is a better solution for application development. XSP also promises to be key in the upcoming Cocoon 2.0, which I look at now.



Library Navigation Links

Copyright © 2002 O'Reilly & Associates. All rights reserved.