[ Team LiB ] Previous Section Next Section

15.3 Transforming XML into a Device-Dependent Format

A web application can use XSLT to respond with different content depending on the type of device making the request. Example 15-4 shows a page that serves both HTML and WML browsers by applying different stylesheets to the same XML document, transforming it to the appropriate markup for the browser that requests it.

Example 15-4. XSL stylesheet that generates HTML or WML (phone.jsp)
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" 
%><%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" 
%><%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" 
%><%@ taglib prefix="ora" uri="orataglib" 
%><c:choose><c:when 
test="${fn:contains(header.Accept, 'text/vnd.wap.wml'}"
><ora:setHeader name="Content-Type" value="text/vnd.wap.wml" 
/><c:import url="wml.xsl" var="stylesheet" 
/></c:when><c:otherwise><ora:setHeader name="Content-Type" value="text/html"
/><c:import url="html.xsl" var="stylesheet" 
/></c:otherwise></c:choose><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>

There are a number of things to note here. First, see how messy the page looks. That's because the start tag for all JSP directives and actions in this page are written on the same line as the end tag for the preceding element, to make sure that no extra linefeeds are added to the response. As described earlier, leading whitespace (such as linefeed characters) in a WML page can cause a WML browser to reject the page.

Because the page can serve both HTML and WML content, the page directive's contentType attribute cannot be used to set the content type. Instead, the content type needs to be set dynamically. This page uses a JSTL function and a custom action to handle this. The JSTL fn:contains( ) function checks if the HTTP Accept header contains the content type for WML. This piece of information is used to decide which type of content to return. If the browser accepts WML, the <ora:setHeader> custom action sets the Content-Type header dynamically to text/vnd.wap.wml, otherwise to text/html. The <c:import> actions import the appropriate stylesheet, wml.xsl or html.xsl, based on the device type making the request, and the <x:transform> action finally transforms the XML document accordingly.

For a simple example like this, letting an XSLT stylesheet transform the XML source into a complete web page works fine. However, on most real web sites, the HTML version of the site differs significantly from the WML version. You want to provide a rich interface for HTML browsers with a nice layout, navigation bars, images, colors, and fonts, and typically as much content as you can fit on each page. A WML browser, on the other hand, has a very small screen with limited layout, font, and graphics capabilities. Developing an efficient interface for this type of device is very different. A more practical approach for combining XML, XSLT, and JSP to serve different types of browsers is to keep the actual content (articles, product information, phone lists, etc.) in a device-independent XML format, but use separate JSP pages for each device type. The JSP pages can then use the <x:transform> action to transform the key content and merge it with the device-dependent template text to form a complete page suitable for each specific device type, like in Example 15-1.

    [ Team LiB ] Previous Section Next Section