15.2 Transforming XML into HTML
You may also have heard about the Extensible Stylesheet Language (XSL). XSL defines one set of XML elements to transform an XML document into some other type of document, and another set of elements to produce a formatted version of an XML document suitable for display. Browsers and other programs that need to render an XML document with different styles for different elements, such as a bold large font for a header and a regular font for paragraph text, use the formatting part of XSL. The transformation part of XSL is referred to as XSLT. XSLT can turn a source XML document, such as a document representing an order, into different forms using different stylesheets. This is useful in business-to-business (B2B) applications, where different partners often require the same information in slightly different formats. You can read more about XSL and XSLT at http://www.w3.org/TR/xsl/.
In a web application, XSLT can transform structured XML data into HTML. Example 15-2 shows an example of a JSP page in which the same phone book information used in Example 15-1 is transformed into an HTML table.
Example 15-2. Transforming XML to HTML (phone_html.jsp)
<%@ page contentType="text/html" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %> <html> <head> <title>Phone List</title> </head> <body bgcolor="white"> <c:import url="htmltable.xsl" var="stylesheet" /> <x:transform xslt="${stylesheet}"> <?xml version="1.0" encoding="ISO-8859-1"?> <employees> <employee id="123"> <first-name>Hans</first-name> <last-name>Bergsten</last-name> <telephone>310-555-1212</telephone> </employee> <employee id="456"> <first-name>Bob</first-name> <last-name>Eckstein</last-name> <telephone>800-555-5678</telephone> </employee> <employee id="789"> <first-name>Paula</first-name> <last-name>Ferguson</last-name> <telephone>213-555-1234</telephone> </employee> </employees> </x:transform> </body> </html>
At the top of the page, the taglib directive for the JSTL XML library is included, along with the directive for the JSTL core library used in previous chapters.
To transform the XML data, you first need to get hold of the XSLT stylesheet. The JSTL <c:import> action, described in Table 15-1, loads the stylesheet from the file specified by the url attribute and saves it in the variable named by the var attribute.
Table 15-1. Attributes for JSTL <c:import>|
url
|
String
|
Yes
|
Mandatory. A page- or context-relative path, or an absolute URL.
|
context
|
String
|
Yes
|
Optional. The context path for another application.
|
charEncoding
|
String
|
Yes
|
Optional. The character encoding for the imported content. Default is the encoding specified by the protocol used for the import or ISO-8859-1 if no encoding is found.
|
var
|
String
|
No
|
Optional. The name of the variable to hold the result as a String.
|
scope
|
String
|
No
|
Optional. The scope for the variable, one of page, request, session, or application. page is the default.
|
varReader
|
String
|
No
|
Optional. The name of the variable to expose the result as a Reader to the body.
|
The <c:import> action is very versatile. You can use it to import data from resources in the same application, another application on the same server (identified by the context attribute), and even from an external server by specifying an absolute URL for any protocol supported by the web container, such as HTTP, HTTPS, or FTP. Parameters can be defined either in the URL as a query string or using nested <c:param> actions. The imported data can be saved as a String in any scope, or exposed as a java.io.Reader to actions within the element's body. Using a Reader is slightly more efficient, because the <c:import> action doesn't have to read the input in this case; it just wraps a Reader around the input stream that a nested action then reads directly. I'll show you an example of this later. When you import a resource (such as a JSP page) that belongs to the same application, the target resource has access to all request parameters and variables in the request scope, the same way as when you use the <jsp:forward> action (Chapter 10).
The transformation is performed by a JSTL action named <x:transform>, described in Table 15-2.
Table 15-2. Attributes for JSTL <x:transform>|
doc
|
String, java.io.Reader, javax.xml.transform.Source, org.w3c.dom.Document, or the types exposed by <x:parse> and <x:set>
|
Yes
|
Mandatory, unless specified as the body. The XML document to transform.
|
xslt
|
String, java.io.Reader, javax.xml.transform.Source
|
Yes
|
Mandatory. The XSLT stylesheet.
|
docSystemId
|
String
|
Yes
|
Optional. The system identifier for the XML document.
|
xsltSystemId
|
String
|
Yes
|
Optional. The system identifier for the XSLT stylesheet.
|
result
|
javax.xml.transform.Result
|
Yes
|
Optional. A Result object used to capture or process the transformation result.
|
var
|
String
|
No
|
Optional. The name of the variable to hold the result as a org.w3c.dom.Document.
|
scope
|
String
|
No
|
Optional. The scope for the variable; one of page, request, session, or application. page is the default.
|
The XML document to transform can be specified as the body, as in Example 15-2, or as a variable through the doc attribute. The example XML document contains elements representing information about employees. The xsl attribute is set to the XSL stylesheet imported by the <c:import> action. It contains XSLT elements for transforming the XML document into an HTML table. In Example 15-2, both the var and the result attributes are omitted, so the <x:transform> action adds its result to the response. This is the most common use, but the var and result attributes can be used if the transformation result needs to be captured and processed further.
Descriptions of all the XSLT elements would fill a book all by itself, but Example 15-3 shows the stylesheet used here to give you an idea of how XSLT looks.
Example 15-3. XSL stylesheet that generates an HTML table (htmltable.xsl)
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="employees"> <table border="1" width="100%"> <tr> <th>ID</th> <th>Employee Name</th> <th>Phone Number</th> </tr> <xsl:for-each select="employee"> <tr> <td> <xsl:value-of select="@id"/> </td> <td> <xsl:value-of select="last-name"/>, <xsl:value-of select="first-name"/> </td> <td> <xsl:value-of select="telephone"/> </td> </tr> </xsl:for-each> </table> </xsl:template> </xsl:stylesheet>
The XSLT elements are similar to JSP action elements in that they perform some action rather than identify information types. The XSLT elements select and process pieces of the source XML document. Here, the <xsl:template> element selects the top <employees> element in the source XML document, the <xsl:for-each> element loops over all nested <employee> elements, and the <xsl:value-of> elements extract the attribute values and nested elements for each <employee> element. The non-XSLT elements are used as template data, the same way as in JSP. You get the idea.
An XSLT stylesheet can use parameters to represent dynamic data, provided to the XSLT processor when a document is transformed:
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:param name="empName" /> <xsl:template match="employees/employee[name = $empName]"> ...
The parameter in this example limits the <employee> elements to be processed to those that have a <name> element with the value specified by the parameter.
To pass the parameter value to the XSLT stylesheet, you must use a nested <x:param> action in the <x:transform> body:
<x:transform xslt="${stylesheet}"> <x:param name="empName" value="${param:empName}" /> <?xml version="1.0" encoding="ISO-8859-1"?> <employees> <employee id="123"> <first-name>Hans</first-name> <last-name>Bergsten</last-name> <telephone>310-555-1212</telephone> </employee> ... </x:transform>
Here I pass on a request parameter value to the stylesheet, but you can, of course, use any EL expression as the value.
XML documents, including XSLT stylesheets, can contain references to external entities, for instance in the XSL <xsl:include> and <xsl:import> elements. If these references are written as relative paths in the document, a base URI must be used to establish what they are relative to. You can pass base URIs for the XSLT stylesheet and the XML source to the <x:transform> action through the xsltSystemId and the docSystemId attributes. The value can be any valid URI, such as an absolute file or HTTP URL or a context- or page-relative path.
|
No comments:
Post a Comment