Example 8-24. LanguageDemo.java servlet
package chap8;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
/**
* Allows any combination of English, Spanish, and Chinese XML
* and XSLT.
*/
public class LanguageDemo extends HttpServlet {
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
ServletContext ctx = getServletContext( );
// these are all required parameters from the HTML form
String xmlLang = req.getParameter("xmlLanguage");
String xsltLang = req.getParameter("xsltLanguage");
String charEnc = req.getParameter("charEnc");
// convert to system-dependent path names
String xmlFileName = ctx.getRealPath(
"/WEB-INF/xml/numbers_" + xmlLang + ".xml");
String xsltFileName = ctx.getRealPath(
"/WEB-INF/xslt/numbers_" + xsltLang + ".xslt");
// do this BEFORE calling HttpServletResponse.getWriter( )
res.setContentType("text/html; charset=" + charEnc);
try {
Source xmlSource = new StreamSource(new File(xmlFileName));
Source xsltSource = new StreamSource(new File(xsltFileName));
TransformerFactory transFact = TransformerFactory.newInstance( );
Transformer trans = transFact.newTransformer(xsltSource);
trans.setOutputProperty(OutputKeys.ENCODING, charEnc);
// note: res.getWriter( ) will use the encoding type that was
// specified earlier in the call to res.setContentType( )
trans.transform(xmlSource, new StreamResult(res.getWriter( )));
} catch (TransformerConfigurationException tce) {
throw new ServletException(tce);
} catch (TransformerException te) {
throw new ServletException(te);
}
}
}
After getting the three request parameters for XML, XSLT, and
encoding, the servlet converts the XML and XSLT names to actual
filenames:
String xmlFileName = ctx.getRealPath(
"/WEB-INF/xml/numbers_" + xmlLang + ".xml");
String xsltFileName = ctx.getRealPath(
"/WEB-INF/xslt/numbers_" + xsltLang + ".xslt");
Because the XML files and XSLT stylesheets are named consistently, it
is easy to determine the filenames. The next step is to set the
content type of the response:
// do this BEFORE calling HttpServletResponse.getWriter( )
res.setContentType("text/html; charset=" + charEnc);
This is a critical step that instructs the servlet container to send
the response to the client using the specified encoding type. This
gets inserted into the Content-Type HTTP response
header, allowing the browser to determine which encoding to expect.
In our example, the three possible character encodings result in the
following possible content types:
Content-Type: text/html; charset=ISO-8869-1
Content-Type: text/html; charset=UTF-8
Content-Type: text/html; charset=UTF-16
Next, the servlet uses the
javax.xml.transform.Source interface and the
javax.xml.transform.stream.StreamSource class to
read from the XML and XSLT files:
Source xmlSource = new StreamSource(new File(xmlFileName));
Source xsltSource = new StreamSource(new File(xsltFileName));
By using java.io.File, the
StreamSource will correctly determine the encoding
of the XML and XSLT files by looking at the XML declaration within
each of the files. The StreamSource constructor
also accepts InputStream or
Reader as parameters. Special precautions must be
taken with the Reader constructors, because Java
Reader implementations use the default Java
character encoding, which is determined when the VM starts up. The
InputStreamReader is used to explicitly specify an
encoding as follows:
Source xmlSource = new StreamSource(new InputStreamReader(
new FileInputStream(xmlFileName), "UTF-8"));
For more information on how Java uses encodings, see the JavaDoc
package description for the java.lang package.
Our servlet then overrides the XSLT stylesheet's output
encoding as follows:
trans.setOutputProperty(OutputKeys.ENCODING, charEnc);