XSLT

XSLT, the XML transformation language, is more "standard" thanJSP. Unlike JSP, XSLT is purely intended to transform data to another format - for example, for display to users - and not to acquire data. Thus in a web application, XSLT stylesheets transform content for presentation, but can't be used to handle user requests. For some tasks, XSLT is more capable than any alternative view technology. It ensures an elegant division between data and presentation.

However, before we leap to the conclusion that XSLT is the ultimate way to render web content, we must consider some significant negatives. XSLT is complex for the uninitiated. XSL transformations are slow (sometimes very slow), compared to the other rendering techniques we've discussed. In Chapter 15 we'll look at some benchmarks to quantify the performance issues. We will probably need to convert Java objects to XML before we can transform them, incurring additional complexity and performance overhead. However, we may be able to minimize these disadvantages by using only those features of XSLT that simplify application code.

The following section isn't an introduction to XSLT or XML. Please refer to a good reference such as Michael Kay's excellent XSLT Programmer's Reference from Wrox (ISBN 1-8-6100506-7) if any of the concepts discussed are unfamiliar.

When to Use XSLT

Adopting XSLT as a view technology has the following advantages, both technical and practical:

  • XSLT is a standard in its own right. XSLT skills are not J2EE or Java-specific. For example, XML and XSLT are widely used in the Microsoft developer community. This means that we may be able to recruit XSLT authors with experience of our industry or type of site, rather than limiting ourselves to JSP experts. XSLT may well become a cross-platform standard for web authoring. We may also be able to leverage existing XSLT stylesheets.

  • XSLT is superior to any other presentation solution for rendering tree structured content. It can even be used to perform the equivalent of SQL joins against reference data.

  • XSLT has excellent sorting capability.

  • As XSLT stylesheets are XML documents, using XSLT helps to ensure that generated markup is well formed. For example, crossed tags will be illegal in a stylesheet. This will help to avoid many common browser errors.

  • Using XSLT forces us to make data available as XML. This may have benefits beyond web presentation.

  • XSLT isn't web-specific, as long as it isn't used only within other view technologies such as JSP.

  • Unlike JSP (but like all the other templating solutions we've considered) XSLT is not web specific. An investment in developing XSLT skills in-house can produce benefits in many areas.

Against these we need to balance the following disadvantages:

  • XSLT has a complex syntax, because XSLT stylesheets are XML documents. As we've seen with JSP custom tags, markup isn't an ideal syntax for a scripting language. Although it's easy to do complex tasks once one understands it, XSLT will seem less intuitive to a page designer (and even to many Java developers) than a simple template language such as VTL, or even JSP. Tool support is still limited.

  • XSLT performance, although not bad enough to rule out its use for any but the most performance-sensitive applications, is unlikely ever to approach that of JSP or simpler templating solutions.

  • Even with good XSLT authoring tools (a necessity as XSLT stylesheets often look very different to the output they generate), a project will still need at least one developer with an expert understanding of XSLT. Stylesheet performance, for example, can vary widely depending on how a stylesheet is constructed.

  • XSLT isn't integrated as smoothly with J2EE as JSP. However, as we'll see, we can use JSP custom tags and an MVC framework to provide the necessary infrastructure.

  • We will usually need to perform the additional step of converting Java objects into XML elements before we can use XSLT to display the data they contain.

Choosing to use XSLT is more of a strategic decision than, say, choosing between JSP and Velocity, which is essentially a choice between how to display the JavaBean properties of the same objects. The XSLT model significantly differs from most other solutions for presenting data, and adopting XSLT may require significant training.

If data already exists in XML, using XSLT is almost always the best approach. However, getting XML out of an OO, Java-based application is not always so easy. In Chapter 6 we discussed the idea of "domification": convertingJavaBeans to XML documents on the fly. The following example will use the Domify open source package. While the use of reflection will incur a small performance overhead, remember that other template technologies such as Velocity and even JSP also make heavy use of reflection.

What Do We Want from XSL?

It's important to remember that XSLT is built on several separable technologies. The XPath expression language, used as a sub-language in XSLT stylesheets, is the key to XSLT's powerful capability for selecting content within XML model data nodes.

Even without adopting XSLT as our main view technology, we may be able to enjoy the benefits of XPath. Using Domify or another library (such as Apache Commons JXPath, available from http://jakarta.apache.org/commons/jxpath/) we can even apply XPath expressions to JavaBean model data, as well as data that already exists in XML form. We can also choose to generate only part of a view using XPath and XSLT: the JSTL, for example, provides standard tags that allow the evaluation of XPath expressions and allow us to embed XSLT processing in JSP pages.

How to Use XSLT in Views

Assuming that we have our data in XML form, how do we approach the task of rendering it in the view itself?

Using XSLT Instead of JSP

The "pure" approach is to perform all rendering and content generation with XSLT. The advantages of a pure XSLT approach are:

  • By converting all model data to XML, we have created a platform-neutral presentation layer.

  • We know that our generated content will always be well formed. Non-matching tags are a common source of errors in HTML tags, and it is impossible to be certain that content generated from aJSP will be well formed under all execution paths.

  • We standardize on a single view technology.

The disadvantages of a pure XLT approach are:

  • We are forced to convert all model data into XML. There are situations where this may be difficult.

  • The XSLT mechanisms for importing data are relatively complex, relying on the importation of rules using <xsl: import> and <xsl: include> XSLT elements. However, the <xsl: import> mechanism is very powerful. Included files must be well-formed XML documents. In contrast, JSP and other template languages offer easy inclusion of any kind of content.

  • We will suffer the maximum possible performance hit from using XSLT, with every byte of data returned to the client being the result of an XSL transform.

Using XSLT from JSP Custom Tags

We can reap some of the benefit of XSLT and XPath by embedding XSLT-like operations and XPath expressions within other templates. The JSTL makes this particularly easy, so we'll focus on using XSLT in JSP pages.

The advantage of this approach is that enables us to "cherry pick" when to use XSLT. For example, if some model data is available as XML, we can expose it more easily and efficiently using XPath and XSLT than usingJava scriptlets. The disadvantages are that:

  • It's impossible to guarantee that generated markup will be well formed.

  • We won't have a complete XML representation of our site. This is another key benefit of adopting XML: we don't choose XML for any particular stylesheet, but because exposing XML allows us to use any stylesheet and thus expose any XML or other text-based format that we want.

  • Combining technologies may increase complexity.

Let's look at using JSTL to expose a model object, available as a request attribute, which is already in XML form, as an org.w3c.dom.Node.

First we must import the XML tag library from the JSTL:

    <%@ taglib uri="/x" prefix="x"%> 

This library offers XSLT-like tags that allow us to iterate over, evaluate and perform conditional logic based on XPath expressions. For example, assuming that the request attribute node is an XML node, we can iterate over sub-elements like this:

    <x:forEach select="$node/reservation/seats/item">                                                                                <x:out select="name"/>    </x:forEach> 

Only the first element of the path ($node) isJSTL-specific, using the JSTL Expression Language to identify an object containing XML data. The remainder of the expression is an XPath relative to this node, so this tag treats its contents in the same way as the <xsl : for-each> tag. This is a trivial example; we can use the full power of XPath in such expressions.

This is a simple and powerful approach when model data exists in XML form. However, the JSTL doesn't provide any support for exposing JavaBean data as XML. However, in this case we can use a simple enclosing tag to "Domify" JavaBean data. The following example uses a tag available in the framework code with the sample application that uses the Domify library to expose an object attribute (obtained via a JSP expression) and make it available as a scripting variable named node (see the source of com.interface21.web.tags.DomifyTag for the implementation of this tag). This enables use of any of the JSTL XML tags within its scope. The following fragment could be used, after the tag library imports shown, to display the list of seats in the Reservation model object on showReservation.jsp, without any other changes:

    <%@ taglib uri="/x" prefix="x"%>    <%@ taglib uri="/i21" prefix="i21"%>    <i21:domify      root= "reservation" model="<%=reservation%>">                                                                                <ul>      <x: forEach select="$node/reservation/seats/item">          <li/><x:out select="name"/>          </x:forEach>      </ul>    </i21:domify>                                                                                                             

This is simply unnecessary for our sample application's "Show Reservation" view: it's easier to perform such simple iteration using theJSTL <forEach> tag. However, if we required anything like the full power of XPath node selection, it would be a different matter.

TheJSTL also provides tags that allow the use of XSLT stylesheets to generate part of aJSP: again, useful functionality when data exists in XML form or when its display requires the power of XSLT.

TheJSTL also provides tags that allow the parsing of XML body content for use by other XSLT tags. These should be used with caution: acquiring content is the business of web tier controllers and business objects, not JSP views. The potential for parse errors is also problematic in views.

Important 

JSTL introduces powerful, standard support for using XPath and XSLT within JSP views. This is often a good compromise, enabling us to use the power of XSLT where it is appropriate, while using JSP as our main view technology.

Note that JSP isn't our only choice for using embedded XSLT (although, with theJSTL, it's a very good choice): other view technologies, such as Velocity, may also allow us to work with XPath and XSLT within larger, composite views.

Implementing our Example Using a "Pure" XSLT Approach

As J2EE doesn't integrate XML and XSLT as smoothly as it does JSP, the biggest challenge is to use a "pure" XML approach, in which an XSLT stylesheet generates the entire view. Fortunately, our MVC framework provides the necessary infrastructure code. The generic com.interface21.web.servlet.view.xslt.XsltView implementation of the View interface compiles and caches an XSLT stylesheet on initialization. When it is asked to render a model to the response, it automatically uses the Domify package to create an XML Node representing the model's data. It then uses the TrAX API to perform an XSLT transform using the cached stylesheet and this XML data and write the output to the response.

Note 

The implementation of this class and the extension functions used in this example are discussed in Appendix A.

All we need to do in our application is to declare a view bean of type XsltView in /WEB-INF/classes/views.properties. We must always set bean properties to specify the document root (the tag name for the root element corresponding to the model) and the template URL (the location of the stylesheet within the WAR). We may also optionally set the excludedProperties property to a CSV string of fully qualified properties we wish to exclude from domification. This can simplify the generated node. In the present case it is essential to prevent a cyclic reference. The definition for our sample view is as follows:

    showReservation.class=com.interface21.web.servlet.view.xslt.XsltView    showReservation.root=reservationInfo    showReservation.stylesheet=/xsl/showReservation.xsl    showReservation.excludedProperties=      com.wrox.expertj2ee.ticket.referencedata.support.ShowImp1.performances 

Note that if we don't specify a stylesheet URL, the output will display the input XML document. This is very useful functionality during development. The XsltView class will also add a special element called <request-info> to the model, which contains locale information it extracts from the request. This can support internationalization within XSLT stylesheets.

Our framework also provides XSLT extension functions in the com.interface21.web.servlet.view.xslt.FormatHelper class that simplify formatting dates and currencies. Like Velocity, XSLT currently lack good support in this area. We'll use these extension functions in our stylesheet.

Now we understand how the necessary infrastructure code works and how to configure it, let's look at what we need to develop as part of our application to expose the "Show Reservation" screen using an XSLT stylesheet.

As the data doesn't exist in XML, we're reliant on Domify. Thus it's important to understand the structure of the XML document that Domify will generate from our model, which contains three model objects (Reservation, PriceBand, and Performance) and the RequestInfo object we added in XsltView. Note that nodes in this document are generated only on demand; while this DOM document is an essential reference as we write an XSLT stylesheet, it doesn't give an accurate reflection of what the application needs to do at runtime (so long as our stylesheets are efficient, and don't force exhaustive searching of document nodes).

The following is a complete listing of the generated document:

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

The root element corresponds to our model map:

    <reservationImfo> 

We will have one <item> element per model object, the "key" attribute being the object's name in the model (this is Domify's default behavior on exposing java.util.Map objects). Note that simple bean properties are exposed as sub-elements of the relevant <item> element, their text content being a string representation of their value:

    <item key="priceband"      type="com.wrox.expertj2ee.ticket.referencedata.support.PriceBandImpl">      <name>AA</name>      <description>Premium Reserve</description>      <price>102.5</price>      <seatTypeId>1</seatTypeId>    </item> 

There's no guarantee about the order in which model objects will be exposed by Domify. In this case, the second of the four model objects is the <request-info> object added by the Xs1tView class to expose locale information. Note that this contains standard language and country codes:

    <item key="request-info"      type="com.interface21.web.servlet.view.RequestInfo">      <language>en</language>      <country>GB</country>    </item> 

The remaining elements expose the Reservation and Performance objects. Note that the Reservation object contains nested objects with their own bean properties. These are exposed in a natural, hierarchical XML structure:

    <item key="reservation"      type="com.wrox.expertj2ee.ticket.boxoffice.support.ReservationImpl">      <timestamp>1027419612736</timestamp>      <reference>AA</reference>      <totalPrice>10.0</totalPrice>      <quoteRequest>        <performanceID>1</performanceID>        <seatsRequeste>2</seatsRequeste>        <seatsMustBeAdjacent>false</seatsMustBeAdjacent>        <bookingFee>3.5</bookingFee>        <holdTill>          <date>23</date>          <time>1027419912736</time>          <year>102</year>          <month>6</month>          <hours>11</hours>          <minutes>25</minutes>          <seconds>12</seconds>          <day>2</day>          <timezoneOffset>-60</timezoneOffset>        </holdTill>        <classID>1</classID>        <reserve>true</reserve>      </quoteRequest>      <seats>        <item type="com.wrox.expertj2ee.ticket.boxoffice.Seat">          <name>AI</name>          <id>1</id>          <seatClassId>1</seatClassId>          <left>0</left>          <right>0</right>        </item>        <item type="com.wrox.expertj2ee.ticket.boxoffice.Seat">          <name>A2</name>          <id>2</id>          <seatClassId>1</seatClassId>          <left>0</left>          <right>0</right>        </item>        </seat>        <seatsAreAdjacent>true</seatsAreAdjacent>        <reserved>true</reserved>        <minutesReservationWillBeValid>4</minutesReservationWillBeValid>      </item>      <item key="performance"        type="com.wrox.expertj2ee.ticket.referencedata.support.PerformanceImpl">        <name>1</name>        <show>          <name>Romeo and Juliet</name>          <id>1</id>          <seatingPlanId>1</seatingPlanId>          <seatTypes/>        </show>        <when>          <date>23</date>          <time>1027419612746</time>          <year>102</year>          <month>6</month>          <hours>11</hours>          <minutes>20</minutes>          <seconds>12</seconds>          <day>2</day>          <timezoneOffset>-60</timezoneOffset>        </when>        <priceStructureId>1</priceStructureId>      </item>    </reservationInfo> 

Now let's look at the stylesheet for displaying this information.

The XSLT authoring model is also quite different to that for JSP and template engines such as Velocity. Instead of executing sequentially, XSLT templates are usually based on rules that are applied to elements in the XML input.

We begin by declaring a namespace for the extension functions in the FormatHelper class:

    <?xml version="1.0"encoding="UTF-8"?>    <xsl :stylesheet version="1.0"      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"      xmlns: format ="com.interface21.web.servlet.view.xslt.FormatHelper"                                                        > 

As we'll access the locale codes in the "request info" item, we declare a global variable to shorten the path and possibly improve performance:

    <!--Make this available globally -->    <xsl:variable name="reqInfo"select="/reservationInfo/item[@key='request-info']"/> 

In such a simple stylesheet, we could use a number of approaches to displaying the content. XSLT guru Michael Kay distinguishes between four common types of XSLT stylesheet in XSLT Programmer's Reference. In this case we can choose between what he calls a "Fill-in-the-blanks" stylesheet and a "Rulebased" stylesheet.

A Fill-in-the-blanks" stylesheet looks like the generated content, using XPath expressions and iteration to select dynamic content. Such stylesheets execute in down-the-page order and use a similar structure to JSP or Velocity templates. "Rule-based" stylesheets define rules for content elements, so don't mirror the structure of the output document. This is less intuitive at first sight, but can prove very powerful.

I've chosen to use a simple Rule-based stylesheet for the example, as it is a little more concise than a Fill-in-the-blanks stylesheet and demonstrates the classic XSLT model.

We begin by defining a rule for the root element. This prompts the application of the rule for all <item> elements in the XML input with a key attribute value of "performance". In the present example, we know there will only ever be one such <item> element. Note that this effectively disables automatic application of rules as elements are encountered. As we don't know the order of input elements, this isn't very useful in the present case, but it can be very powerful in other situations:

    <xsl:template match="/*">      <xsl:apply-templates select="item[@key='performance']"/>    </xsl:template> 

The template for <item> elements with a key value of "performance" can assume such an element as its context node. This means it can work with XPaths relative to such an element. I've highlighted the use of the dateTimeElement() extension function:

    <xsl: template match="item[@key='performance']">                                                                              <html>        <head>        <title>Seats reserved for <xsl:value-of select="show/name"/></title>      </head>      <body>      <b><xsl:value-of select="show/name" />:      <xsl:apply-templates select ="format:dateTimeElement(when/time,      $reqInfo/language, $reqInfo/country)"/>                                                                                      </b>      <br/>      <br/> 

The only tricky thing here is how we handle the information about seat allocation and the price of seats. This information comes from the Reservation object, although the rest of the content comes from the Performance and PriceBand elements. We handle this by invoking the appropriate template for the ReservationInfo object data, providing an XPath from the root of the document, not the context node:

    <xsl:apply-templates select="/reservationInfo/item[@key='reservation' ]"/>                                                   <form method="GET" action="payment.html">      <input type="submit" value="Proceed"></input>    </form>    Please check the seating plan below for the location of the reserved seats.    <br/>    <br/>      <xsl:variable name="seatingPlanImage">static/seatingplans/<xsl:value-of       select="show/seatingPlanId"/>.jpg</xsl:variable>      <img src="/books/1/392/1/html/2/{$seatingPlanImage}"/>      </body>      </html>    </xsl:template> 

The template for the reservation information is pretty straightforward, save for the need to display the description of the PriceBand object, obtained from the root element (highlighted):

    <xsl: template match="item[@key= 'reservation' ]">      <xsl :value-of select="quoteRequest/seatsRequested"/>      seats in      <xsl:value-of select="/reservationInfo/item[@key='priceband']/description                                                    />      have been reserved      for you for      <xsl :value-of select="minutesReservationWillBeValid" /      minutes to give you time to complete your purchase.      The seat numbers are: 

XSLT makes light work of iteration over the array of reserved seats:

    <ul>    <xsl:for-each select="seats/item">      <li/><xsl:value-of select="name"/>    </xsl:for-each>                                                                                                              </ul>    <p/>    The total cost of these tickets will be    <xsl :value-of select="format:currency (totalPrice, $reqInfo/language,    $reqInfo/country)"/.    This includes a booking fee of    <xsl:value-of select ="format: currency (quoteRequest/bookingFee,    $reqInfo/language, $reqInfo/country)"/>. 

XSLT conditional syntax is quite like that of JSTL:

   <xsl:if test="not (seatsAreAdjacent='true' )">     <b>Please note that due to lack of availability, some of the     seats offered are not adjacent.</b>     <form method="GET" action="payment.html"       <input type="submit" value="Try another date"/>     </form>   </xsl:if> </xsl:template> 

Finally, we need a rule to display the <formatted-date> element created by the dateTimeElement() extension function:

    <xsl:template match="formatted-date"      <xsl:value-of select="day-of-week"/><xsl:text> </xsl:text>       <xsl:value-of select="month"/><xsl:text> </xsl:text>       <xsl:value-of select="day-of-month"/>       <xsl:value-of select="year"/>       at       <xsl:value-of select="hours"/>:<xsl:value-of select="minutes"/>       <xsl:text> </xsl:text>       <xsl:value-of select="am-pm"/>    </xsl:template>    </xsl:stylesheet> 

The good news is that if this stylesheet is evaluated successfully, we know that the generated output is well-formed.

There's no need to change controller code, and the output rendered to the browser will look exactly as that generated by JSP and Velocity. A user would have no way of telling that XSLT was being used.

Note 

It is possible to perform XSLT transformations in the client browser, providing both XML document and stylesheet on the server. However, this approach, which has the potential to move processing load from server to client, is problematic in the real world, as not all browsers offer standard or dependable XSLT support. A special View implementation could add support for this in our MVC framework without changing controller or model code.

Important 

The XSLT stylesheet for our simple view is arguably more complex and harder to understand than the approaches we've seen so far - although it's simple given an understanding of XSLT. It would be hard to justify using XSLT as the view technology for the sample application as its business requirements stand.

However, XSLT is a very powerful language, which comes into its own with more complex presentational requirements, which it can often handle with ease. For example, if the welcome page of our sample application needed to display a tree structure of genres, shows and performances (rather than just genres and shows, as at present) and sorting or filtering was required, XSLT would be a very good choice, and the necessary XSLT stylesheet would almost certainly be simpler than a JSP generating the same output.

Fortunately we don't need to commit to a "pure" XML approach to enjoy some of the benefits of XSLT. We can embed XPath expressions and XSLT transforms within JSP pages using the JSTL.

Important 

XSLT and XPath are best used when data already exists in XML form, but it's relatively easy to convert JavaBean models to XML, as in our example.



Expert One-on-One J2EE Design and Development
Microsoft Office PowerPoint 2007 On Demand
ISBN: B0085SG5O4
EAN: 2147483647
Year: 2005
Pages: 183

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net