With the increasing use of XML as an encoding standard to transfer business-related data with, we often need to transform XML to HTML using the eXtensible Stylesheet Language (XSL). Spring offers a view implementation taking away the need to set up an XSLT transformer yourself, leaving you with only one task: the creation of the source for the transformer, an org.w3c.dom document. This is achieved through the use of an abstract method, via the Template Method design pattern.
The following example shows how to use Spring AbstractXsltView to transform an XML file with a Spring bean definition to a simple HTML page:
public void BeansView extends AbstractXsltView { protected Node createDomNode( Map model, String root, HttpServletRequest request, HttpServletResponse response) throws Exception { // get resource from model Resource resource = (Resource)model.get("resource"); // create document builder DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = factory.newDocumentBuilder(); docBuilder.setEntityResolver(new BeansDtdResolver()); // get the resource InputStream is = resource.getInputStream(); try { Document doc = docBuilder.parse(is); } finally { is.close(); } return doc; } }
The AbstractXsltView has three properties that you can use to customize its behavior. The view needs a style sheet to transform the XML document with. (If you don't specify a style sheet, the view will throw an exception telling you it's incorrectly configured.) The second is a URI resolver you might need to register to resolve URIs. No URI resolver will be registered if you do not specify it. URI resolvers are used in xsl:include and xsl:import tags included in your XSL style sheet. (Most XSLT libraries such as Saxon provide concrete URIResolver implementations, and there are also resolvers that use an XML database to look up included resources.) The last property is a String identifying the root in the document. This root String is passed to the createDomNode() method as implemented in the preceding example. It gives the view a bit of flexibility, allowing you to specify which part of an XML document you want to transform. (You will have to take care of returning the node related to the root property yourself, by the way.) The root property isn't used in this example:
<bean /> <bean name="beansView" > <property name="stylesheetLocation"><value>/WEB-INF/beans.xsl</value></property> </bean> <bean name="contextController" />
The last thing to do is implement a controller. The example controller retrieves a Spring Application Context file (taken from the virtual filename in the user's request), loads it, and adds it to the model. Using this controller, http://host.com/path/applicationContext.xml will result in the application Context.xml file from /WEB-INF being loaded and added to the model:
public class ShowContextController extends AbstractController { protected ModelAndView handleRequestInternal( HttpServlerRequest request, HttpServletResponse response) throws Exception { // get the filename: String uri = request.getPathInfo(); String filename = uri.substring(0, uri.lastIndexOf("."); Resource res = getWebApplicationContext().getResource(res); if (!res.exists()) { throw new FileNotFoundException( "ApplicationContext '" + filename + "' does not exist"); } ModelAndView mav = new ModelAndView("beansView", "resource", res); } }
We can now map the ShowContextController using a SimpleUrlHandlerMapping to present all application contexts available to the user, using a simple XSL style sheet.
<bean > <property name="urlMap"> <map> <entry key="/**/*.xml"><ref bean="contextController"/></entry> </map> </property> </bean>
Remember that catching exceptions (such as the FileNotFoundException thrown in the preceding example) can be resolved to an appropriate view by registering a HandlerExceptionResolver in your web application context.