I don't know how your workplace functions but mine has one glaring flaw, a lack of centralization. Take a look around and you can see a few places in which common tasks are being preformed across multiple teams. With the hope of starting a trend, work presented us with a fun little problem to solve. How can we centralize our outgoing e-mail messages? We have a handful of websites, some in .NET others in Java, each responsible for composing and sending their own e-mails (mostly confirmations and reminders).
To meet the centralization requirement we decided on setting up a web service that was then exposed to all development teams. Ok, one problem solved, but we still had to figure out how compose our data-centric e-mails and then send them out the door. Enter XSLT, in a nutshell what XSLT allows us to do is transform an XML document into some other format, in our case HTML and/or text. This will allow our web service to take an incoming XML document and transform it into an HTML page. In order to do these transformations programatically we will use the Xalan XSLT processor. Before we get started with the Java code, we will also need some XML and an XSLT template.
First the XML:
emailMessage.xml
----------------
<EmailMessage>
<Customer>
<customerFirstName>Joe</customerFirstName>
<customerLastName>Customer</customerLastName>
<customerEmail>joe.customer@somewhere.com</customerEmail>
</Customer>
<Service>
<confirmationNumber>12345-67</confirmationNumber>
<price>59.99</price>
<date>2007-04-04</date>
</Service>
</EmailMessage>
Now the XSLT:
emailMessage_html.xslt
----------------------
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/EmailMessage">
<html>
<head>
<title>Email Message Sample</title>
</head>
<body>
<div>
<p>Thank you for your order. The information we have on file is below:</p>
<p>
<b>Customer Information</b><br />
First Name: <xsl:value-of select="Customer/customerFirstName" /><br />
Last Name: <xsl:value-of select="Customer/customerLastName" /><br />
E-mail: <xsl:value-of select="Customer/customerEmail" /><br />
</p>
<p>
<b>Service Information</b><br />
Confirmation Number: <xsl:value-of select="Service/confirmationNumber" /><br />
Price: <xsl:value-of select="Service/price" /><br />
Date: <xsl:value-of select="Service/date" /><br />
</p>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
And finally the Xalan transformer class:
TemplateTransformer.java
------------------------
import java.io.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
public class TemplateTransformer {
// constructors
public TemplateTransformer() {}
// methods
public String transform(String xml, String xsltStyleSheetPath) {
String text = "";
TransformerFactory tFactory = TransformerFactory.newInstance();
// Define the source XSL
StreamSource source = new StreamSource(new File(xsltStyleSheetPath));
// Define the source XML
StreamSource sourceXML = new StreamSource(new StringReader(xml));
// Define the result destination
StreamResult result = new StreamResult(new StringWriter());
try {
// Tranform the XML using the XSL
Transformer transformer = tFactory.newTransformer(source);
transformer.transform(sourceXML, result);
StringWriter writer = (StringWriter)result.getWriter();
text = writer.toString();
}
catch (TransformerException te) {
return ""; // yeah, I'm being lazy
}
return text;
}
}
And you're done, it's essentially four lines of code. Specify the source XSL, the source XML and the destination. Then call the transform method, simple as that.
Now some testing code. The following is a simple JSP page that can be used to see the results of the transformation, for simplicity sake I'm assuming the XSLT and XML files are on the local hard drive.
<%@ page language = "java"
import = "java.text.*, java.util.*, java.io.*"
%>
<%
String xmlPath = "c:\\temp\\xslt\\emailMessage.xml";
String xslPath = "c:\\temp\\xslt\\emailMessage_html.xslt";
TemplateTransformer t = new TemplateTransformer();
String result = t.transform(xmlPath, xslPath);
%>
<html>
<head>
<title>XSLT/Xalan Test Page</title>
</head>
<body>
<b>XSL Path:</b> <%= xslPath %><br />
<b>XML Path:</b> <%= xmlPath %><br />
<br />
<b>Result:</b><br />
<pre>
<%= result %>
</pre>
</body>
</html>
Well, hopefully all of that worked and made a little bit of sense.