Templates
      By Scott Ferguson
Resin 3.0

Features
Installation
Configuration
Web Applications
IOC/AOP
Resources
JSP
Quercus
Servlets and Filters
Databases
Admin (JMX)
CMP
EJB
Amber
EJB 3.0
Security
XML and XSLT
XTP
JMS
Performance
Protocols
Third-party
Troubleshooting/FAQ

Introduction
User's Guide
Reference
Tutorials

StyleScript
Tag Libraries
Templates
Tag Libraries
Reference
Tutorials

  1. Displaying the Guest Book
  2. Intelligent forms
  3. Conclusion

Displaying the Guest Book
The first advantage of XTP is that it separates the JSP code from the page. The page design can just use a standard HTML/XML editor. More importantly, since it's easy to create tags, you can create tags meaningful for your specific application.

The XTP templates example is an expansion of the JSP "model 2" example. You may want to refer to Resin's support of XSLT and JSP .

The guest book uses three application-specific tags

TagMeaning
ct:guest-bookiterates over the guest book entries.
ct:guest-namewrites the guest's name.
ct:guest-commentwrites the guest's comment.

Compare the login.xtp page with the login.jsp in the JSP templates example.

login.xtp
<?xml-stylesheet href='guestbook.xsl'?>
<title>Hogwarts Comments</title>

<table width='100%'>
<tr>
  <td width='25%'><em>Name</em></td>
  <td width='75%'><em>Comment</em></td>
</tr>
<ct:guest-book>
  <tr>
  <td><ct:guest-name/>
  <td><ct:guest-comment/>
</ct:guest-book>
</table>

HTML tags should be copied to the generated output. So we just create a default rule to copy the input to the output. XSLT is a pattern based language. 'node()' matches any node and '@*' matches any attribute. So any tag that doesn't match any other rules will be copied.

It's important to notice that XSLT works with XML trees, not text streams like JSP. The xsl:copy of an attribute adds and attribute to the containing element.

defaultcopy.xsl: strict XSLT
<xsl:template match='node()|@*'>
  <xsl:copy>
    <xsl:apply-templates select='node()|@*'/>
  </xsl:copy>
</xsl:template>
Strict XSLT follows the XML syntax. There are several advantages of using XML but readability is not one of them. To make stylesheets more readable we've added some simple syntactic sugar to XSLT, called XSLT-lite. XML purists can stick to the standard XML syntax: Resin supports both. You can look at our XSLT and XSLT-lite references and also some XSLT-lite examples.

XSLT-lite makes scanning templates easier because the template pattern is clear, on its own line. The following is exactly equivalent to the defaultcopy.xsl above.

defaultcopy.xsl: XSLT-lite
node()|@*
<<
<xsl:copy>
  <xsl:apply-templates select='node()|@*'/>
</xsl:copy>
>>

guestbook.xsl contains the custom tags for the guestbook example. When Resin looks at a node, it will select the best matching pattern and execute it. The element <ct:guest-book> will generate a loop, while <form action='GuestXtp'> will copy the form to the output.

guestbook.xsl
<!-- Use language=javascript for the XSLT -->
<xtp:directive.page language=javascript/>

<xsl:import href='defaultcopy.xsl'/>

<!-- Generated JSP uses language=javascript -->
/ 
<<
<jsp:directive.page language='javascript'/>
<xsl:apply-templates/>
>>

ct:guest-book
<<
<% for (var _ct_guest in application.attribute.guest_book) { %>
<xsl:apply-templates/>
<% } %>
>>

ct:guest-name
<<
<%= _ct_guest.name %>
>>

ct:guest-comment
<<
<%= _ct_guest.comment %>
>>

So now we've created some tags for a custom application. That's nice and it shows how XSLT can clean JSP pages. The guest book JSP was fairly simple so the added complexity of creating stylesheets doesn't really show how powerful the XTP concept is. For a taste of real power, we'll create a simple form library.

Intelligent forms
Adding addition functionality to forms makes HTML and JSP complex. GuestXtp just adds simple filling in of default values. The GuestXtp servlet calls request.setAttribute to set default values for form element. For example, once a user has added a comment, she can edit the comment. The default value is the old comment.

In fact, the w3c now has a new requirements document for the next generation of intelligent forms. That doesn't really help web designers because web sites still need to support old browsers. XTP gives web sites the more powerful functionality now.

There are a few other common form extensions:

  • Server defaults
  • Server validation
  • Client validation
  • Client actions

The XTP file itself is simple. It just looks like any HTML page, except form values are called ct:*.

login.xtp

<form action='GuestXtp' method='post'>
  <ct:hidden name='action' value='login'/>
  <table>
  <tr><td>Name<td><ct:input name='Name'/>
  <tr><td>Password<td><ct:password name='Password'/>
  <tr><td colspan=2>Hint: the password is quidditch
  <tr><td/><td><ct:submit value='Login'/>
</form>

The transformation is relatively simple. Copy all properties to the output and add a value attribute if the servlet supplied a default value.

<ct:input size=40 name='Name'/>

<input name=Name size=40 value='Harry Potter'>

XSLT lets stylesheets pull common formatting code into functions using the named template mechanism. The template functions are called with xsl:call-template. xsl:call-template works like xsl:apply-templates, but it passes the current node, not the children nodes.

Because the generated JSP will add an attribute at run time, the form.xsl treats its output as unparsed content. Unknown elements, like <form> or <input> are printed as text. Unparsed content works just like JSP.

fun:copy-attrs is a simple XSLT function which copies the attributes from the XTP element to the output. In the ct:input example above, it will copy name=Name and size=40.

xtp:cache tells Resin that the XSLT results are cacheable. Once it's generated the JSP, it doesn't need to run the XSLT engine again. This greatly improves the performance.

form.xsl
<xsl:stylesheet parsed-content='false'>

<xtp:cache/>

<xsl:template name='fun:copy-attrs'>
  <xsl:for-each select='@*'>
    <xsl:text> </xsl:text><{name(.)}>="<{.}>"<xsl:text/>
  </xsl:for-each>
</xsl:template>

fun:input-attrs is the core of the form processing. It calls fun:copy-attrs to copy the user's attributes. Then it generates the JSP to add a value attribute if it's available.


<xsl:template name='fun:input-attrs'>
  <xsl:call-template name='fun:copy-attrs'/>
  <xsl:if test='@value'>
    value="<{@value}>"
  </xsl:if>
  <xsl:if test='not(@value)'>
      <% { 
         var _ct_v = request.attribute["<{@name}>"];
         if (_ct_v == null)
         _ct_v = "";
         out.write(' value="', _ct_v.replace('"', """), '"');
       }
    %>
  </xsl:if>
</xsl:template>

Now that the functions have been defined, creating the individual tags is simple.


ct:input
<<
<input <xsl:call-template name='fun:input-attrs'/>>
>>

ct:password
<<
<input type='password' <xsl:call-template name='fun:input-attrs'/>>
>>

ct:submit 
<<
<input type=submit <xsl:call-template name='fun:input-attrs'/>>
>>

Conclusion
XTP is a tradeoff. It takes more work to design custom tags than to write standard inline JSP. However, once you've written the tags, using them is a breeze. In the next few months, we'll start building useful libraries of tags similar to Perl's CGI.pl.

An important value of XTP is that it lets web pages use the latest W3C specifications without waiting for all the browsers to support it. For example, the W3C has proposed requirements for intelligent forms. A properly designed form.xsl can implement intelligent forms on the server and support all browsers, not just the browsers supporting the spec.


Tag Libraries
Reference
Tutorials
Copyright © 1998-2006 Caucho Technology, Inc. All rights reserved.
Resin® is a registered trademark, and HardCoretm and Quercustm are trademarks of Caucho Technology, Inc.