If you only have a hammer, you tend to see every problem as a nail.
I try to restrain myself, but one of my more common workplace rants is:
If you start with xml and you end up with xml, then why aren’t you using xsl in between?
My colleagues commonly unmarshal xml to an object, manipulate the object, and marshal the object back to xml. The right choice when there are relatively complex manipulations in the middle. But xsl is a much better choice for simple manipulations:
- Easier to review
- Easier to test
- Easier to modify
- Easier to track change
Here’s a simple servlet that applies xsl transforms to posted request xml. First, the init method that reads in xsl tranform files located in /WEB-INF/xsl and stores the corresponding Templates objects in a HashMap (Templates are thread-safe).
1 | public void init(ServletConfig config) |
Next, a get method that returns the xsl transform whose name matches the request path information.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws java.io.IOException,
ServletException
{
//
// Return the xsl transform if specified in the path
String path = request.getPathInfo();
if ( path != null && path.length() > 1 ) {
path = path.substring(1);
if ( templates.get(path) != null ) {
response.setContentType("application/xml;charset=utf-8");
InputStream in = getTemplateInputStream(getServletContext(),path);
PrintWriter out = response.getWriter();
int ch;
while ( (ch=in.read()) > -1) {
out.write(ch);
}
return;
}
}
//
// Otherwise list loaded transforms
response.setContentType("application/text;charset=utf-8");
PrintWriter out = response.getWriter();
Object[] keys = templates.keySet().toArray();
out.println("Supported transforms are:");
for ( Object key : keys ) {
out.print("\t");
out.println(key.toString());
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws java.io.IOException,
ServletException
{
InputStream in = request.getInputStream();
response.setContentType("application/xml;charset=utf-8");
PrintWriter out = response.getWriter();
//
// Apply named transform to the posted request data
String path = request.getPathInfo();
if ( path != null && path.length() > 1 ) {
try {
Templates template = templates.get(path.substring(1));
if ( template != null ) {
Transformer transform = template.newTransformer();
transform.transform( new StreamSource(in), new StreamResult(out));
out.close();
return;
}
}
catch ( TransformerException e ) {
response.setStatus(response.SC_INTERNAL_SERVER_ERROR);
return;
}
}
response.setStatus(response.SC_FORBIDDEN);
}