Combine the power of XPath and JSP tag libraries

Achieve simple data access in JSPs using XPath expressions

Java Server Pages and XML represent natural partners for building Web applications that use heterogeneous data sources. XML's DOM API provides a universal way to represent these diverse data sources. XPath provides a standard and simple syntax to access the DOM. JSP pages execute as Java servlets, typically in the context of a Web server where they generate session and data-dependent response documents. By combining these technologies, along with an XPath custom tag library, it's possible to make a standard and uniform approach to both representing the model data and accessing it.

The XPath tag library provides a framework within which dynamic content represented as a DOM document can be manipulated and inserted into a JSP to:

  • Simplify presentation code in the JSP and make it Java-free
  • Simplify templating or substitution points within the JSP
  • Remove complexity from dynamic data access, yet make it powerful

The XPath tag library combined with JSP further aids efficiency by engendering a clear separation between the role of a page author and a programmer.

This article covers intermediate-to-advanced JSP, XML, and DOM topics, so you may need to do some background reading in Resources to get up to speed.

Note: The XPath custom tag library is still in the proof-of-concept stage, hence it is not available as a standalone tag library. However, you can download the XPath-JSP Test Application WAR file and extract the relevant parts to create your own standalone tag library.

XPath syntax

XPath, a W3C recommendation since November 1999, provides an easy notation for specifying and selecting parts of an XML document. An XML document is a tree of elements with only one route or path from the root node of the tree to any other node of the tree. XPath defines this path.

Let's take an example XML document and some XPath expressions used to locate its parts.

The document below represents a user who has a userid and a password. Moreover, a user can have multiple roles, in this case two: Domain Administrator and Help Desk Administrator:

<user> 
            <userid>someone</userid> 
            <password>somewhere</password> 
            <roles> 
               <role id="admin">Domain Administrator</role> 
               <role id="helpdesk">Help Desk Administrator</role> 
             </roles> 
</user> 

The basic XPath syntax is similar to filesystem addressing. As such, if the path starts with /, then it represents an absolute path to the required element:

/user/userid/text()   select 'someone' 
/user/roles/role      select  all 'role' elements 
//role                select  all 'role' elements [ same as 2.] 
//role[@id='admin']/text()  select  'Domain Administrator' 
/user/roles/role[1]    select the first role element 
                          i.e. 'Domain Administrator' 
/user/roles/role[last()]   select the last role element
                          i.e. 'Help Desk Administrator'

The above examples represent just a sample of XPath's power. For a more complete list of XPath syntax see the XPath tutorial in Resources.

Architecture for a Web application using the XPath tag library

Having seen how XPath expressions can be used on an XML document, let us now discuss the architecture of a Web application using the XPath custom tag library, illustrated in Figure 1.

Figure 1. Web application architecture using the XPath custom tag library Click on thumbnail to view full-size image.

In this approach, presentation JSPs access the domain data or enterprise resources using XPath expressions. The domain data is represented as DOM document instances.

Page authors use the XPath custom tag library to embed XPath expressions in JSPs. Developers own the DOM document instances and are responsible for maintaining their state. Additionally, page authors could be given a DTD for the DOM document, providing its structure, which would be helpful in writing the XPath expressions.

Remember that XPath expressions are for access only, they cannot be used to update the state of a DOM document instance.

Examples of XPath expression in JSPs

We will create a sample to illustrate the various XPath custom tag library options. For this example, we assume that the application deals with customer orders. A sample Order XML document looks like this:

Order.xml

<ORDER>
<SHIPTO>
      <NAME>ALICE SMITH</NAME>
      <STREET>123 MAPLE STREET</STREET>
      <CITY>MILL VALLEY</CITY>
      <STATE>CA</STATE>
      <ZIP>90952</ZIP>
</SHIPTO>
<DATE>12-31-2000</DATE>
 <!-- Multiple item elements -->
 <ITEM>
      <TITLE>Twelve Songs of Christmas</TITLE>
      <ARTIST>JIM REEVES</ARTIST>
      <PRICE>15.95</PRICE>
 </ITEM>
  <ITEM>
        <TITLE>First Piano Concerto</TITLE>
        <ARTIST>>Janos</ARTIST>
        <PRICE>12.95</PRICE>
  </ITEM>
</ORDER>
 <!-More items here -->
 ...
 ...
 ...
</ORDER>

The Order XML document consists of a ShipTo, Date, and repeating Item elements. The application keeps an instance of the Order XML document in memory as a DOM document object. The examples below illustrate the usage of XPath expressions in a JSP, which accesses the sample Order DOM document.

Example 1: Simple data access and substitution

In our first example, the JSP uses XPath expressions to access the Order DOM instance. This example shows how data from the DOM instance is retrieved and substituted in the JSP:

viewOrder.jsp

<%@ page errorPage="error.jsp" %>
<%@ taglib uri="/src/tags/taglib.tld" prefix="mytag" %>
<html>
  <head>
    <title>View Orders</title>
  </head>
   <body bgcolor="white" link="#666699" vlink="#666699">
    <B> OrderDate: </B>  <mytag:getvalue select="/ORDER/DATE" /> <BR>
    <HR>
<!-- ifdef tag checks whether the Xpath expression is valid --> 
<mytag:ifdef select="/ORDER/SHIPTO" >
    <B> ShipTo: </B> <BR/>
    <mytag:getvalue select="/ORDER/SHIPTO/NAME" /> <BR>
    <mytag:getvalue select="/ORDER/SHIPTO/STREET" /> <BR>
    <mytag:getvalue select="/ORDER/SHIPTO/CITY" /> <BR>
    <mytag:getvalue select="/ORDER/SHIPTO/STATE" /> <BR>
    <mytag:getvalue select="/ORDER/SHIPTO/ZIP" /> <BR>
</mytag:ifdef>
    <HR>
          
    <!-- The -iterate custom tag- iterates through the repeating element "ITEM"  
     The -getvalue custom tag- substitutes the result of the XPATH expression for 
     the current iteration  -->  
    <mytag:iterate select="/ORDER/ITEM" > 
      <p>
         <B> ARTIST: </B> <mytag:getvalue select="./ARTIST" />    
         <B> TITLE : </B>  <mytag:getvalue select="./TITLE" />    
         <B> PRICE :  </B> <mytag:getvalue select="./PRICE" />    
     <BR>
               
    </mytag:iterate>  
    </body>
    </html>  

The code above uses three tags from the XPath tag library: getvalue, ifdef, and iterate. All three tags have a select attribute that specifies an XPath expression.

The getvalue applies the XPath expression specified in the select, on the Order DOM document instance and substitutes the result.

The conditional ifdef tag evaluates its body content only if the XPath expressions specified in its select are valid.

iterate, an iteration tag, parses its body contents for each iteration. In this case, the select attribute specifies a node set to be retrieved which is then iterated over. Note that the getvalue tag, when used within the iterate tag, specifies a relative XPath expression in its select attribute.

The example above covers simple data access, substitution, and control flow using XPath expressions in a JSP. The next example discusses attribute value substitution.

Example 2: Attribute value substitution

In our second example, the JSP uses XPath expressions to access the ShipTo data from the DOM instance, which is then edited using an HTML form. Note the use of the template: prefix for attribute value substitution:

editShipTo.jsp

<%@ taglib uri="/src/tags/taglib.tld" prefix="mytag" %>  
   
   <html>  
              .....  
              .....  
 
     <form action="/editshipto.do" method="POST" > 
     SHIP TO: <BR/>
     
     <!-- Attribute value substitution is done by using the 'template:' prefix 
        and by enclosing the content in the XPathTemplate tag -->
     <mytag:XPathTemplate>
       NAME: <input type="text" name="name"          
                 template:value="/ORDER/SHIPTO/NAME"/>  <BR/>
    
       STREET: <input type="text" name="street"              
                 template:value="/ORDER/SHIPTO/STREET"/>  <BR/>
     
       CITY : <input type="text" name="city"             
                 template:value="/ORDER/SHIPTO/CITY"/>  <BR/>
    
       STATE: <input type="text" name="state"            
                 template:value="/ORDER/SHIPTO/STATE"/>  <BR/>
       ZIP:  <input type="text" name="zip"           
                 template:value="/ORDER/SHIPTO/ZIP"/>  
                 
     </mytag:XPathTemplate>
      </form> 
        ..... 
        ..... 
    </html> 

The code above illustrates the use of the XPathTemplate container tag that enables XPath expression results to be substituted in attribute values. To achieve this, the template: keyword is used to prefix attribute values that need to be evaluated, as shown in the example above.

The XPathTemplate template tag parses its body content, looking for elements that have attributes starting with the template: prefix. When it finds one, it applies the XPath expression on the DOM document instance and rewrites the attribute and its value without the template: prefix. In the example above we saw how XPath expressions are used in attribute values and how the XPathTemplate tag is used for attribute value substitution. In the next section, we will see the various custom tags available as part of the XPath custom tag library.

The XPath custom tag library

We will now see the various tags and their attributes available in the XPath custom tag library. For each tag you'll find the name, description, and attribute details.

Tag: XPathTemplate

Description:

  • A container/super tag that enables XPath expressions in attributes
  • The body of this tag could be HTML or well-formed XML
  • For attribute-value substitution, the prefix template: is used on the attribute
  • For element substitution, the iterate tag or getvalue tag mentioned below are used

Attributes:

  • Attribute name: content
  • Attribute value: html (default) or xml

Tag: iterate

Description:

  • Allows iteration over an XPath expression that results in multiple nodes
  • Used in conjunction with the getvalue tag

Attributes:

  • Attribute name: select
  • Attribute value: an XPath expression

Tag: getvalue

Description:

  • Substitutes the result of the XPath expression
  • The tag implementation checks whether this tag has an enclosing iterate tag and substitutes the value appropriately

Attributes:

  • Attribute name: select
  • Attribute value: An XPath expression

Tag: ifdef

Description:

  • Tests if the XPath expression is valid and maps to a node
  • If the test returns true, then the body of the tag is evaluated

Attributes:

  • Attribute name: select
  • Attribute value: an XPath expression

Tag: ifnodef

Description:

  • Tests if the XPath expression is invalid or there is no corresponding node for the XPath expression
  • If true, then the body of the tag is evaluated

Attributes:

  • Attribute name: select
  • Attribute value: an XPath expression

Tag: gencontent

Description:

  • Creates a DOM document instance in session scope for the XML in its body
  • If its debug attribute is set to on, it serializes the DOM to the standard output

Attributes:

  • Attribute name: debug
  • Attribute value: on or off

Representing domain data as DOM documents

The previous sections focused on how XPath expressions are used in JSPs to access DOM document instances. Now let us briefly discuss two techniques for creating a DOM document instance to represent the domain data.

Domain data can be represented as a DOM document in two ways:

  1. Domain data classes, for example Order.java, could return a DOM document using a toDOM() method
  2. As a set of JavaBean objects translated to DOM document instances at runtime

Of the two, the second approach proves more elegant, but it carries a performance penalty since the translation from a JavaBean to a DOM document acts as an overhead. The JOX Java libraries provide a nice framework for translating JavaBeans to XML.

Map XPath expressions to DOM instances

So how does an XPath expression get mapped to a DOM document instance?

After the DOM document representing the data available to a JSP is created, it is put in one of the application, request, session, or page scopes. The DOM document instance's name or key is the same as the name of the document element.

Using Order.xml as an example, a DOM document representation of this XML file will be stored in either one of the scopes, with the name Order, which is the name of the document element in Order.xml.

At runtime, a tag handler parses and extracts the root of an XPath expression. For example, if the XPath expression is /ORDER/SHIPTO/NAME, the root of the expression is ORDER. The tag handler then looks up a DOM document instance with the name ORDER in page, session, request, and application scopes.

After looking up the DOM document instance, the tag handler evaluates the XPath expression against it and the result is substituted.

These semantics are not exposed to the JSP page author. They are hidden in the custom tag library implementation.

The XPath-JSP Test Application

I've included an XPath-JSP test application so that you can get some hands-on experience and validate the concepts we discussed in the previous sections.

The test application shows how to create DOM document objects using the gencontent tag in a JSP. It also shows how to access the DOM document instance from presentation JSPs using the various XPath custom tags we covered earlier.

You will also see how an XPath expression in a JSP is parsed and mapped to a DOM document object in memory.

Install the XPath-JSP Test Application

Before downloading and installing the test application, make sure you have the following software packages:

  • Java Development Kit

    You must download and install a Java 2 (version 1.2 or later) JDK implementation for your operating system platform. See

    Resources

    for download information.

  • Servlet container

    You must download and install a servlet container that is compatible with the Servlet API Specification (version 2.2 or later) and the JSP Specification (version 1.1 or later). One popular choice: download Apache's Tomcat (version 3.1 or later). Note: the XPath-JSP test application has been tested on Apache Tomcat version 3.1 only.

After you install the aforementioned software packages, download the XPath-JSP Test Application, contained in a Web application archive (WAR) file. (The Zip file contains the required WAR file.) You can install it on any servlet container compatible with Servlet API 2.2 or later versions.

Now, here's some legal language to keep everyone happy.

IMPORTANT: This product includes software developed by the Apache Software Foundation (http://www.apache.org/).

IMPORTANT: This product includes software developed by OpenXML Inc.

On deploying the xpath-jsp.war file, the directory structure illustrated in Figure 2 results.

Figure 2. The xpath-jsp.war directory structure

CLASSPATH settings

The XPath-JSP WAR file contains the Apache XML parser xerces.jar. For the test application to work properly it might be necessary for the xerces.jar to appear before any other XML parser in the CLASSPATH.

For Tomcat 3.1, make sure the xerces.jar appears before the default parser xml.jar in the CLASSPATH.

Use the XPath-JSP Test Application

To use the XPath-JSP Test Application, follow these steps:

  1. Go to the xpath-jsp/test-DOMs directory and open the dom.jsp file.
  2. The content of this file has some valid XML content enclosed within a <gencontent/> tag. When this JSP executes, it creates a DOM representation of the XML content.

    The DOM document instance is stored in session scope. The "key" or "name" used to store the instance is the document element name of the XML content. In this case, the document element is Order.

  3. Go to xpath-jsp directory and open the viewOrder.jsp and the editShipTo.jsp file.
  4. Note the XPath expressions that will be applied to the DOM document created using the dom.jsp.
  5. To test, access the dom.jsp from your browser. Then access the viewOrder.jsp and the editShipTo.jsp files.

IMPORTANT: The code for this application is still in experimental stage and should not be used for production applications. The code has not been rigorously tested.

That's all there is to it.

Considerations

No solution exists without tradeoffs. With that in mind, let's quickly look at the pros and cons of combining XPath expressions in a JSP.

The XPath-JSP tag custom tag library offers a unique solution to making presentation code simpler and Java-free. It forces separation of presentation and content by providing a small set of tags that enable the use of XPath expressions in JSPs to access DOM documents. Though this requires learning of XPath syntax, the basic syntax is easy to pick up. The DOM documents are fully processed in the backend, which keeps the presentation layer clean and simple.

Performance is potentially slower due to overhead of converting backend data into DOM, then accessing it via XPath. However, it is unclear exactly how much of a penalty may result, under what circumstances, and if it is noticeable in real-world scenarios.

Pros:

  • A standard data access and substitution syntax using XPath
  • Clear separation between the role of page author and developer
  • Page author: expert in UI and presentation, uses XPath Tag Libraries
  • Developer: expert in server-side logic, creates and uses tag libraries and DOM documents
  • XPath provides a simple yet powerful traversal syntax

Cons:

  • Representing domain objects as DOM documents incurs a performance overhead

Conclusion

After reading this tutorial, you should have a good idea of how to build an XPath-JSP application. You should also have some idea of its limitations. We've seen how to use the simple yet powerful XPath data access syntax in JSPs with the help of a custom tag library. In addition, we've examined a couple of approaches to represent domain data as DOM document objects. Further, we've seen how the custom tag library maps XPath expressions to DOM document objects at runtime. Finally, we've looked at the pros and cons of using this approach and how it helps in writing clean and simple JSPs.

I am confident you will have a greater appreciation for this approach after using the test application and the examples. The XPath custom tag library covered in this article is still at a proof-of-concept stage and has a lot of scope for improvements and enhancements. In fact, I've been thinking of how to extend this tag library into a Web application framework that will make it easier to develop and deploy a Web application using the technologies and techniques we have discussed.

Thanks to my colleague Andy Hakim for his comments on drafts of this article and a lot of very helpful feedback on the XPath custom tag library.

Stanley Santiago is a senior software engineer at iPlanet Ecommerce Solutions, a Sun/Netscape Alliance. He has more than eight years of experience working on object-oriented development projects and Internet-based applications using Java and XML.

Learn more about this topic

  • JavaWorld resources
  • Other important resources

Join the discussion
Be the first to comment on this article. Our Commenting Policies
See more