XALAN_HOME=/path/to/xalan.jar
XERCES_HOME=/path/to/xerces.jar
export CLASSPATH=$CLASSPATH:$XALAN_HOME:$XERCES_HOME
/xslt
/xslt/WEB-INF
/xslt/WEB-INF/classes
To do so, type the following commands:
> cd $TOMCAT_HOME/webapps
> mkdir xslt
> cd xslt
> mkdir WEB-INF
> cd WEB-INF
> mkdir classes
> cd classes
The /xslt/WEB-INF/classes directory is the place where you will store all the servlets classes described below.
Once the directories are created, you should install a servlet context, by editing the file $TOMCAT_HOME/conf/server.xml, and adding the following lines:
<Context path="/xslt" docBase="webapps/xslt" debug="0" reloadable="true"
>
</Context>
path="/xslt" tells Tomcat that all requests starting with /onjava
belong to the onjava web application.
docBase="webapps/xslt" tells the servlet container that the
web application is located on webapps/xslt"
Once you have done these operations, you need to restart Tomcat.
If you want the output to be displayed on the screen, simply omit the -out flag and argument.
import org.xml.sax.SAXException;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
public class XalanXslProcessorBean {
TransformerFactory tFactory;
//the constructor simply
gets a new TransformerFactory instance
public XalanXslProcessorBean() {
tFactory = TransformerFactory.newInstance();
}
//this method takes as input
a XML source, a XSL source, and returns the output of the transformation
to the servlet output stream
public void process(StreamSource xmlSource,
StreamSource xslSource,
HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException, SAXException {
try {
Templates templates = tFactory.newTemplates(xslSource);
Transformer transformer = templates.newTransformer();
transformer.transform(xmlSource, new StreamResult(response.getOutputStream()));
}
catch (Exception e) {
//should
log some message here
}
}
}
<story>
<title>NASA Proposes Launch Solar Sail Vehicle For 2010</title>
<url>http://slashdot.org/article.pl?sid=00/05/15/058238</url>
<time>2000-05-15 07:54:15</time>
<author>timothy</author>
<department>ralph-nader-will-have-to-hire-a-chase-car</department>
<topic>space</topic>
<comments>99</comments>
<section>articles</section>
<image>topicspace.gif</image>
</story>
<story>
<title>Linuxcare Responds To Tim O'Reilly's Article</title>
<url>http://slashdot.org/article.pl?sid=00/05/15/0254252</url>
<time>2000-05-15 02:57:07</time>
<author>timothy</author>
<department>consider-source-horses-mouth-grain-of-salt</department>
<topic>linuxbiz</topic>
<comments>142</comments>
<section>articles</section>
<image>topiclinuxbiz.gif</image>
</story>
<story>
<title>New Internet VCR Service</title>
<url>http://slashdot.org/article.pl?sid=00/05/14/2048217</url>
<time>2000-05-14 20:51:57</time>
<author>timothy</author>
<department>this-is-cool-but-can-they-do-that?</department>
<topic>news</topic>
<comments>189</comments>
<section>articles</section>
<image>topicnews.gif</image>
</story>
<story>
<title>Google Releases WAP Search Tool</title>
<url>http://slashdot.org/article.pl?sid=00/05/14/1240252</url>
<time>2000-05-14 17:49:11</time>
<author>emmett</author>
<department>wireless</department>
<topic>internet</topic>
<comments>141</comments>
<section>articles</section>
<image>topicinternet.jpg</image>
</story>
<story>
<title>No More Unreal Ports For Linux?</title>
<url>http://slashdot.org/article.pl?sid=00/05/14/1439224</url>
<time>2000-05-14 16:32:11</time>
<author>timothy</author>
<department>one-web-one-program-happy-mothers-day</department>
<topic>games</topic>
<comments>250</comments>
<section>articles</section>
<image>topicgames.jpg</image>
</story>
<story>
<title>Pioneer Introduces 1st DVD Recorder (In Japan)</title>
<url>http://slashdot.org/article.pl?sid=00/05/14/152210</url>
<time>2000-05-14 15:50:48</time>
<author>CmdrTaco</author>
<department>steam-rising-from-the-riaas-forehead</department>
<topic>tv</topic>
<comments>98</comments>
<section>articles</section>
<image>topictv.jpg</image>
</story>
<story>
<title>QuakeForge And QuakeWorld Forever Merge</title>
<url>http://slashdot.org/article.pl?sid=00/05/14/1447248</url>
<time>2000-05-14 15:07:27</time>
<author>CmdrTaco</author>
<department>and-then-there-was-one</department>
<topic>quake</topic>
<comments>57</comments>
<section>articles</section>
<image>topicquake.gif</image>
</story>
<story>
<title>What Happens When Open Source And Work Collide?</title>
<url>http://slashdot.org/article.pl?sid=00/05/09/016208</url>
<time>2000-05-14 14:04:07</time>
<author>Cliff</author>
<department>sticky-situations</department>
<topic>programming</topic>
<comments>170</comments>
<section>askslashdot</section>
<image>topicprogramming.gif</image>
</story>
<story>
<title>Black Holes Don't Exist???</title>
<url>http://slashdot.org/article.pl?sid=00/05/14/1339252</url>
<time>2000-05-14 13:39:24</time>
<author>Roblimo</author>
<department>pop-science-can-be-fun</department>
<topic>science</topic>
<comments>162</comments>
<section>articles</section>
<image>topicscience.gif</image>
</story>
<story>
<title>Los Alamos Lab: We're OK, You're OK</title>
<url>http://slashdot.org/article.pl?sid=00/05/14/0143228</url>
<time>2000-05-14 04:44:44</time>
<author>timothy</author>
<department>sir-please-step-*away*-from-the-plutonium-bin</department>
<topic>news</topic>
<comments>278</comments>
<section>articles</section>
<image>topicnews.gif</image>
</story>
</backslash>
Here is the HTML stylesheet (named slashdot.xsl) we will use:
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates select="backslash/story"/>
</body>
</html>
</xsl:template>
<xsl:template match="backslash/story">
<li><a href="{url}"><xsl:value-of select="title"/></a></li>
</xsl:template>
</xsl:stylesheet>
import javax.xml.transform.stream.*;
public class XslProcessorServlet extends HttpServlet {
XalanXslProcessorBean processor;
public void init(ServletConfig config) {
processor = new XalanXslProcessorBean();
}
public void doGet (HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
//sets the Content-Type portion of the HTTP header to text/html
response.setContentType("text/html");
try {
processor.process(new StreamSource("slashdot.xml"), new StreamSource("slashdot.xsl"),
request, response);
}
catch (Exception e) {
}
}
}
Since slashdot.xml is often updated, you may prefer to fetch it
directly from the slashdot.org site: you then need to change the
processor.process(...)
line
to:
processor.process(new StreamSource(new InputStreamReader((new URL("http://slashdot.org/slashdot.xml")).openStream())),
new StreamSource("slashdot.xsl"), request, response);
Then restart your servlet container if needed, and reload the page.
Suppose that you want to make your content available to both HTML
and WML navigators. Basically, you just need a XSLT stylesheet that can
transform XML to HTML, and another one that can transform XML to WML (Wireless
Meta Language). You then need to implement a mechanism that can use the
appropriate stylesheet, depending on the navigator information contained
in the HTTP request header.
Here is the WML stylesheet. Note the xsl:output tag, which is the only way to produce the <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml"> string in the WML output.
<xsl:template match="/">
<wml>
<template>
<do type="prev" name="Previous"
label="Back">
<prev/>
</do>
</template>
<card id="card1" title="Slashdot news">
<p>
<xsl:apply-templates select="backslash/story"/>
</p>
</card>
</wml>
</xsl:template>
<xsl:template match="backslash/story">
<a href="{url}"><xsl:value-of select="title"/></a><br/>
</xsl:template>
</xsl:stylesheet>
Note that the following servlet code now contains some code to fetch
the user agent from the HTTP header, and uses the WML stylesheet when the
user agent string contains the word (Nokia). Obviously, this only works
with a Nokia phone or with some Nokia emulator.
import javax.xml.transform.stream.*;
public class XslProcessorServlet extends HttpServlet {
XalanXslProcessorBean processor;
public void init(ServletConfig config) {
processor = new XalanXslProcessorBean();
}
public void doGet (HttpServletRequest request,
HttpServletResponse response)
throws ServletException,
IOException {
//fetch
the user agent part of the HTTP header
String useragent = request.getHeader("user-agent");
//if the user agent contains the string "Nokia", then use the WML stylesheet,
otherwise use the HTML one
StreamSource xslsource;
if (useragent.indexOf("Nokia")
>= 0) {
//send the correct Content-Type
response.setContentType("text/vnd.wap.wml");
xslsource = new StreamSource("slashdot_wml.xsl");
} else {
response.setContentType("text/html");
xslsource = new StreamSource("slashdot_html.xsl");
}
try {
processor.process(new StreamSource("slashdot.xml"), xslsource, request,
response);
}
catch (Exception e) {
}
}
}
The author: Olivier Elemento is a consultant in fixed and mobile
Internet technologies. It can be reached at elemento@club-internet.fr.
You can also visist its web site at http://genomenews.free.fr/cv.html