A strength of XSLT is its ability to help keep data and presentation separate. As you know, supporting different transformations is a matter of writing different XSLT stylesheets. Figuring out which stylesheet to apply is the only missing piece. For web applications, the User-Agent HTTP header offers the solution.
HTTP requests consist of a header followed by content; the header contains name/value pairs of data, allowing the client and server to exchange additional information with each other. The text shown in Example 8-7 contains the complete HTTP request issued by Netscape 6.0 when running on Windows 2000.
GET / HTTP/1.1 Host: localhost:80 User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; m18) Gecko/20001108 Netscape6/6.0 Accept: */* Accept-Language: en Accept-Encoding: gzip,deflate,compress,identity Keep-Alive: 300 Connection: keep-alive
For the purposes of browser detection, the value of User-Agent must be parsed to determine what kind of browser is requesting information from the servlet. Based on this information, the servlet can select an appropriate XSLT stylesheet that supports the particular strengths and weaknesses of the browser in question.
Unfortunately, there are hundreds of variations of User-Agent, and browser vendors do not rigorously adhere to any standard format. The common browsers can be identified, however, with a small amount of parsing logic. Table 8-2 lists some of the more common browsers you might encounter.
User-Agent |
Browser |
---|---|
Lynx/2.8rel.3 libwww-FM/2.14 |
Lynx 2.8rel3 |
Mozilla/4.0 (compatible; MSIE 4.0; Windows NT) |
Internet Explorer 4.0 |
Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0) |
Internet Explorer 5.5 |
Mozilla/4.08 [en] (WinNT; U ;Nav) |
Netscape 4.08 |
Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; m18) Gecko/20001108 Netscape 6/6.0 |
Netscape 6 |
Mozilla/3.0 (compatible; Opera/3.0; Windows 95/NT4) v3.1 |
Opera 3.0 |
The first browser, Lynx, is listed because it is the most common text-only browser. Whenever the User-Agent begins with Lynx, your web application can select an XSLT stylesheet that omits all graphics from the web page.
The three most popular browsers are clearly Microsoft Internet Explorer, Netscape Navigator, and Opera Software's Opera. Of these three browsers, Navigator was available first, and its User-Agent always begins with Mozilla. In the early days of web development, many sites checked for this and only provided fancy versions of their web sites to Netscape browsers.
When Microsoft Internet Explorer became available, it had to begin its User-Agent string with Mozilla to maintain compatibility with many existing web sites. Therefore, you cannot simply check for Mozilla to determine the browser type. As you can see in Table 8-2, Microsoft browsers include the text MSIE followed by the version number, making them easily identifiable.
A more recent entry, Opera, also begins with Mozilla. The User-Agent for Opera browsers always contains Opera/[version];, where [version] is something like 2.0 or 3.0. With these rules in mind, the algorithm for detecting a browser might look something like this:
if (begins-with "Lynx") { browser is only capable of displaying text } else if (contains "MSIE") { browser is Internet Explorer } else if (contains "Opera") { browser is Opera } else if (begins-with "Mozilla") { browser is Netscape-compatible } else { browser is unknown }
In a servlet, the following code is used to obtain the value of User-Agent:
protected void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException { String userAgent = req.getHeader("User-Agent"); String xslt = null; if (userAgent.startsWith("Lynx")) { xslt = "textHomePage.xslt"; } else { xslt = "htmlHomePage.xslt"; } ...
For more sophisticated applications, it is desirable to use a utility class that can identify the browser, its version number, and possibly even its platform. Although you can certainly write your own class using basic java.lang.String operations, a better option is to use an existing API that someone else has written. The screen capture shown in Figure 8-4 illustrates the output from a simple servlet that identifies various pieces of information about the browser.
This servlet utilizes the org.apache.turbine.util.BrowserDetector class, which is part of Apache's Turbine web application framework.[38] This class actually has only one dependency on anything else in Turbine, so you can either comment out its reference to Turbine's RunData class or simply include the Turbine JAR files in your CLASSPATH.[39] Turbine can be obtained from http://jakarta.apache.org. The code for the servlet is shown in Example 8-8.
[38] This example is based on Version 2.1 of Turbine.
[39] Be sure to read and follow the Apache licensing agreement if you extract this class from Turbine.
import java.io.*; import javax.servlet.*; import javax.servlet.http.*; import org.apache.turbine.util.BrowserDetector; public class BrowserID extends HttpServlet { protected void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException { BrowserDetector bd = new BrowserDetector(req.getHeader( "User-Agent")); res.setContentType("text/plain"); PrintWriter pw = res.getWriter( ); pw.println("User-Agent : " + bd.getUserAgentString( )); pw.println("Supports CSS: " + bd.isCssOK( )); pw.println("JavaScript : " + bd.isJavascriptOK( )); pw.println("Browser Name: " + bd.getBrowserName( )); pw.println("Platform : " + bd.getBrowserPlatform( )); pw.println("Version : " + bd.getBrowserVersion( )); } }
Copyright © 2002 O'Reilly & Associates. All rights reserved.