We are using the Saxon Xslt processor on a Java project to produce ISO20022 XML files. The grouping facility provided by XPath 2.0 is proving a real hit. In this post we give a quick hint on capturing xsl:message output.
The conditional capabilities of Xsl allow us to define rules within our transformations. In the event of rule failures we can report back to Java using the xsl:message statement. For various timing reasons Saxon doesnt report the xsl:message statements via the ErrorListener interface (well not directly).
The two samples below demonstrate how to capture the xsl:message output. The samples are exactly the same except one uses a Transfomer constructed from a Templates object and the other uses an XMLFilter. To begin here is a simple xsl file.
1 2 3 4 5 6 7 8 9 10 11 |
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <helloworld> <xsl:message>Hello World !!</xsl:message> <xsl:text>Hello World !!</xsl:text> </helloworld> </xsl:template> </xsl:stylesheet> |
Here is a JUnit test case that uses the Transformer constructed via the Templates object.
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 |
@Test public void testXslMessageTransformer() throws Throwable { SAXTransformerFactory factory = new net.sf.saxon.TransformerFactoryImpl(); Templates templates = factory.newTemplates(new StreamSource(this.getClass().getResourceAsStream("/xslmessage.xsl"))); Transformer transformer = templates.newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setErrorListener(new ErrorListener() { public void warning(TransformerException exception) throws TransformerException { message = "Captured: " + exception.getLocalizedMessage(); } public void fatalError(TransformerException exception) throws TransformerException { warning(exception); } public void error(TransformerException exception) throws TransformerException { warning(exception); } }); Controller controller = (Controller) transformer; controller.setMessageEmitter(new MessageWarner()); transformer.transform(new StreamSource(new StringReader("<helloworld />")), new StreamResult(System.out)); assertThat(message, containsString("Captured: Hello World !!")); } |
And next we have the same functionality instead we use an XMLFilter.
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 33 34 35 36 |
@Test public void testXslMessageXMLFilter() throws Throwable { SAXTransformerFactory factory = new net.sf.saxon.TransformerFactoryImpl(); Templates templates = factory.newTemplates(new StreamSource(this.getClass().getResourceAsStream("/xslmessage.xsl"))); XMLFilter filter = factory.newXMLFilter(templates); Transformer transformer = factory.newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); Controller controller = (Controller) ((Filter) filter).getTransformer(); controller.setErrorListener(new ErrorListener() { public void warning(TransformerException exception) throws TransformerException { message = "Captured: " + exception.getLocalizedMessage(); } public void fatalError(TransformerException exception) throws TransformerException { warning(exception); } public void error(TransformerException exception) throws TransformerException { warning(exception); } }); controller.setMessageEmitter(new MessageWarner()); XMLReader reader = XMLReaderFactory.createXMLReader(); filter.setParent(reader); transformer.transform(new SAXSource(filter, new InputSource(new StringReader("<helloworld />"))), new StreamResult(System.out)); assertThat(message, containsString("Captured: Hello World !!")); } |
Both samples produce identical output, illustrated below. The ErrorListener assigns the text received from the xsl:message statement to the message member variable. This allows the assertions at the end of the unit tests to succeed.
1 2 |
<?xml version="1.0" encoding="UTF-8"?> <helloworld>Hello World !!</helloworld> |
Leave a Reply