Wednesday, October 21, 2009

15.2 Transforming XML into HTML



[ Team LiB ]






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>

Attribute name



Java type



Dynamic value accepted



Description



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>

Attribute name



Java type



Dynamic value accepted



Description



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.







    [ Team LiB ]



    No comments: