[ Team LiB ] Previous Section Next Section

17.7 Writing JSP Pages as XML Documents

An important part of JSP 2.0 is the added flexibility for writing JSP pages as well-formed, namespace-aware XML documents. Such JSP pages are referred to as JSP Documents, to distinguish them from the type of plain JSP pages described in the rest of this book. Tag files, described in Chapter 11, can also be written as XML documents. While all examples in this section show JSP Documents, you should be aware that everything said about JSP Documents also applies to tag files in XML format.

The main differences between a plain JSP page and a JSP Document are:

  • Template data and JSP elements, taken together, must form a well-formed XML document, which optionally can be validated. This means, among other things, that XML element equivalents must be used instead of the regular JSP directive and scripting elements.

  • A JSP Document is initially processed as a namespace aware XML document, meaning that standard XML entity resolution applies, page encoding determination is performed as defined by the XML specification, namespace declarations are honored and apply to both JSP elements and template data elements, XML quoting rules apply (special characters in attribute values and text nodes must be encoded), etc.

  • Whitespace is processed in the same manner as when XSLT is used to process an XML document. That is, text nodes that contain only whitespace are dropped, except for text nodes in the body of a <jsp:text> element (where whitespace is preserved).

  • An XML declaration may be generated for the response.

Prior to JSP 2.0, a JSP Document had to use <jsp:root> as its root element, making this syntax of interest primarily for validation and authoring tools. The more flexible rules introduced in JSP 2.0 extend the use of the XML syntax to other areas, such as pages used to generate any well-formed XML document and pages created with XML-aware editors.

Apart from the differences listed here, a JSP Document is processed as a regular JSP page after it's been successfully processed (and validated, if necessary) as an XML document, so you can use all standard and custom actions, as well as EL expressions in the document.

17.7.1 Identifying a JSP Document

The container needs help to recognize a JSP page as a page using the XML syntax. A JSP 2.0 container follows these rules, in this order:

  • The requested page has an extension matching the URL pattern of a JSP group declaration in the web.xml file with <is-xml> set to true, as described earlier.

  • The requested page has the .jspx extension, unless this extension has been disabled by a JSP group with <is-xml> set to false. For a tag file in XML syntax, the .tagx extension must be used.

  • The requested page is identified as a JSP page (through the default .jsp extension or an extension defined by a JSP group declaration) and its root element is <jsp:root>.

The third rule was the only one supported by JSP 1.2, as I mentioned earlier, and it's primarily kept for backward compatibility. For new applications, you probably want to rely on one of the first two rules instead.

Let's use a simple JSP Document to discuss the syntax requirements in more detail. Example 17-10 shows a JSP Document that illustrates most of the things you need to consider, as well as the main features available for this format.

Example 17-10. A JSP Document (jspdocument.jspx)
<html 
  xmlns="http://www.w3c.org/1999/xhtml" 
  xmlns:jsp="http://java.sun.com/JSP/Page" 
  xml:lang="en" lang="en">

  <jsp:output doctype-root-element="html"
    doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
    doctype-system="http://www.w3c.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>

  <jsp:directive.page contentType="text/html" /> 

  <head>
    <title>A JSP Document</title>
  </head>
  <body bgcolor="white">
    <h1>All Request Parameters</h1>

    <ul> 
      <c:forEach xmlns:c="http://java.sun.com/jsp/jstl/core"
        items="${paramValues}" var="current">
        <li> 
          ${current.key}:
          <c:forEach items="${current.value}" var="parValue">
            <br/>${parValue} 
          </c:forEach>
        </li> 
      </c:forEach>
    </ul> 

    <jsp:element name="${param.element}">
      <jsp:attribute name="style">${param.style}</jsp:attribute>
      <jsp:body>${param.body}</jsp:body>
    </jsp:element>

  </body>
</html>

The JSP Document in Example 17-10 generates a list of all parameters received with the request and an element based on the parameter data.

The <html> element contains two xmlns attributes. These attributes are used to declare namespaces in an XML document. The first one declares the XHTML namespace as the default namespace for the document. The second one declares that elements with the prefix jsp belong to the JSP namespace, identified by the http://java.sun.com/JSP/Page URI. You must use this declaration in a JSP Document where you use JSP standard actions. You can actually declare a prefix other than jsp for the standard actions in a JSP Document. I suggest, however, that you stick to the default prefix unless you absolutely have to use another (e.g., because you need to use the jsp prefix for another namespace in the generated response); using a different prefix is likely to just cause confusion.

17.7.2 Custom Tag Library Declarations

Custom tag libraries are declared and associated with a prefix through namespace declarations in a JSP Document. In Example 17-10, you see that the JSTL core tag library is declared with an xmlns prefixed attribute in the <c:forEach> element. As in XML, you can declare all namespaces you need either in the root element or in nested elements (where it applies only to that element and its children). The custom tag library prefix is the part of the attribute name following xmlns:, and the attribute value is usually the URI for the library (as defined either in the web.xml file or in the TLD file for the library). That's how the JSTL core library is declared in Example 17-10. If you want to use the TLD or JAR file path instead of a URI value, you must use a value starting with urn:jsptld: followed by the path, for instance:

<html xmlns:ora="urn:jsptld:/WEB-INF/lib/orataglib_3_0.jar" 
  ...>

If the custom tag library consists of a set of tag files directly in the web application structure (i.e., a library that you would identify with the tagdir attribute of a taglib directive in a regular JSP page), the value must start with urn:jsptagdir:, followed by the path to the directory:

<html xmlns:my="urn:jsptagdir:/WEB-INF/tags/mytags" 
  ...>

17.7.3 Generating a DOCTYPE Declaration

Because the page in Example 17-10 generates an XHTML response, the response body should start with a DOCTYPE declaration for XHTML. This is not a JSP specification requirement, but for XML documents defined by a DTD or an XML Schema, it's always a good idea. The <jsp-output> action with the doctype-root-element, doctype-public, and doctype-system attributes adds a DOCTYPE declaration based on the attribute values at the top of the response body. With the attribute values used in Example 17-10, the generated declaration looks like this:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3c.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

The doctype-public attribute is optional. If you omit it, the action generates a declaration without a public identifier.

Note that if you include a DOCTYPE declaration that specifies a DTD in the JSP Document itself, it applies to the JSP Document, not to the generated response. In this case, the container validates the JSP Document against the specified DTD.

17.7.4 XML Syntax for JSP Directives and Scripting Elements

The syntax used for JSP directives and scripting elements in a regular JSP page won't fly in a JSP Document; this syntax is not well-formed XML. You must use these XML elements with equivalent meaning instead:


<jsp:directive.page attribute_list />

Corresponds to <%@ page attribute_list %>, in which the attribute list contains all the attributes supported by the page directive, as described in Appendix A.


<jsp:directive.include file= "file_path" />

Corresponds to <%@ include file="file_path" %>.


<jsp:declaration> ... </jsp:declaration>

Corresponds to <%! ...%>.


<jsp:expression> ... </jsp:expression>

Corresponds to <%= ... %>.


<jsp:scriptlet> ... </jsp:scriptlet>

Corresponds to <% ... %>.

The <jsp:directive.page> element with the contentType attribute in Example 17-10 shows you a concrete example of this syntax.

17.7.5 Generating Elements Dynamically

Example 17-10 contains a JSP standard action that you have not seen in previous examples, combined with a couple of actions that are more familiar:

    <jsp:element name="${param.element}">
      <jsp:attribute name="style">${param.style}</jsp:attribute>
      <jsp:body>${param.body}</jsp:body>
    </jsp:element>

The <jsp:element> action generates a new XML element in the response with the name specified by the name attribute. The <jsp:attribute> and <jsp:body> elements perform the same function as in previous chapters—adding an attribute and a body to the element, respectively. Together, these standard actions allow you to create any XML element, with any number of attributes and a body based on the evaluation result of their bodies, while still keeping the JSP Document as a well-formed XML document. For instance, if the page in Example 17-10 receives the parameters element with the value p, style with the value font-weight:bold, and body with the value Hello+World, this element is generated:

<p style="font-weight:bold">Hello World</p>

17.7.6 Encoding Non-XML Data and Special Characters

Since a JSP Document is a formal XML document, all template data must be well- formed XML. Example 17-10 is well-formed because it contains XHTML elements, such as the <ul> and <li> elements, represented by opening and closing tags, and an empty <br/> tag.

If you use a JSP Document to generate a response in a format that is not XML-based, you can embed the template data that is not well-formed in XML CDATA sections. For instance, if the response must be accessible to older browsers that only understand HTML 3.2, you can't use the XHTML <br/> empty tag syntax, but using HTML 3.2 syntax with a single opening <br> tag violates the well-formedness requirement. Embedding the HTML 3.2 single opening <br> tag in a CDATA section solves the problem; it satisfies the container's well-formed XML requirement and feeds the browser the HTML 3.2 tag it understands:

<ul> 
  <c:forEach items="${paramValues}" var="current"> 
    <li> 
      ${current.key}:
      <c:forEach items="${current.value}" var="parValue">
        <![CDATA[<br>]]>${parValue}
      </c:forEach>
    </li> 
  </c:forEach>

In an XML document, special characters such as greater-than and less-than in an element body (or attribute) must be replaced with character entity codes, for example, the < character must be replaced with &lt; and > must be replaced with &gt;. These characters are common in Java code, so if you need to use scripting elements in a JSP Document, you can use a CDATA section to work around this issue as well:

<jsp:scriptlet>
  <![CDATA[
    if (someNumber > 0) {
      isValid = true;
    }
  ]]>
</jsp:scriptlet>

Another case where special characters must be dealt with is in request-time attribute values. For EL expressions, you must use the XML-safe operators—and, lt, gt, le, and ge instead of &&, <, >, <=, and >=—or use character entity codes in the expression: &amp;&amp;, &lt;, &gt;, &lt;=, and &gt;=. For a scripting request-time attribute value, you must also use a slightly different syntax than in a regular JSP page:

<jsp:setProperty name="emp" property="hireDate"
  value="%= new java.util.Date(  ) %" />

The difference, as shown here, is that the troublesome less-than and greater-than signs are removed.

17.7.7 Using the <jsp:root> Element

Most JSP Documents developed for JSP 2.0 don't use the <jsp:root> element, but it's still supported. Potential reasons for using it in JSP 2.0 are if you need to generate a sequence of XML documents (i.e., the result has more than one root element) or if you want to generate content that is not XML at all but you prefer to use XML syntax in the JSP page (e.g., because you're using an XML-aware editor).

The <jsp:root> element has a mandatory version attribute, and it can be used to declare the JSP namespace and custom tag libraries used in the page with xmlns attributes:

<jsp:root 
  xmlns:jsp="http://java.sun.com/JSP/Page" 
  xmlns:c="http://java.sun.com/jsp/jstl/core"
  version="2.0"> 

  ...
  
</jsp:root>

The version attribute value is the JSP specification version the document complies with, and it must be 1.2 or 2.0. Other than that, a JSP Document with <jsp:root> as its root element looks just the same as the JSP Documents described earlier. The element only serves to identify the page as a JSP Document, and it's not included in the response produced by the page.

17.7.8 XML Declaration Generation

When the container processes a JSP Document, it adds an XML declaration like this to the response in most cases:

<? xml version="1.0" encoding="encodingValue" ?>

The encoding attribute value is the response character encoding defined by a page directive with a contentType attribute containing a character encoding, as described in Chapter 14, or UTF-8 if it's not defined in the JSP Document.

The XML declaration is generated by default for a JSP Document, unless <jsp:root> is used as the root element. You can use the <jsp:output> standard action to suppress the generation of the declaration, or to force it to be generated for a <jsp:root> document:

<jsp:output omit-xml-declaration="true" />

The omit-xml-declaration attribute accepts one of four values: with the value true or yes, the declaration is not generated; if set to false or no, it is. A reason to omit the declaration is when the generated response is included into another document, for instance using the <jsp:include> action in another JSP Document.

For tag files written in XML syntax, no XML declaration is generated by default, since their output typically gets mixed with the content of the page that invokes them. In the rare event you need one, you can use the <jsp:output> action in the tag file with omit-xml-declaration set to false or no.

    [ Team LiB ] Previous Section Next Section