Hslt: report in Saxony 9.4 vs Saxon 9.6

I am trying to throw an exception from java code that will include a message from the xsl: message tag when using Saxon.

Using the following xslt file

<?xml version="1.0" encoding="UTF-8" ?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <xsl:message terminate="yes">exception message</xsl:message> </xsl:template> </xsl:stylesheet> 

In Saxon 9.4 with the following code

 public static void main(String[] args) throws TransformerException { try { TransformerFactory fact = new net.sf.saxon.TransformerFactoryImpl(); Transformer newTransformer = fact.newTransformer(new StreamSource(new File("throw.xslt"))); ((net.sf.saxon.Controller)newTransformer).setRecoveryPolicy(Configuration.DO_NOT_RECOVER); ((net.sf.saxon.Controller)newTransformer).setMessageEmitter(new MessageWarner()); newTransformer.transform(new StreamSource(new File("input.xml")), new StreamResult(new File("output.xml"))); } catch (TransformerException e) { System.out.println("THIS IS EXCEPTION: " + e.getMessage() + " <<<"); throw e; } } 

it gives THIS IS EXCEPTION: exception message <<< , this is the behavior that I expect.

But on Saxon 9.6 with a little adjusted code due to API changes

 public static void main(String[] args) throws TransformerException { try { TransformerFactory fact = new net.sf.saxon.TransformerFactoryImpl(); Transformer newTransformer = fact.newTransformer(new StreamSource(new File("throw.xslt"))); ((net.sf.saxon.jaxp.TransformerImpl)newTransformer).getUnderlyingController().setRecoveryPolicy(Configuration.DO_NOT_RECOVER); ((net.sf.saxon.jaxp.TransformerImpl)newTransformer).getUnderlyingController().setMessageEmitter(new MessageWarner()); newTransformer.transform(new StreamSource(new File("input.xml")), new StreamResult(new File("output.xml"))); } catch (TransformerException e) { System.out.println("THIS IS EXCEPTION: " + e.getMessage() + " <<<"); throw e; } } 

it gives THIS IS EXCEPTION: Processing terminated by xsl:message at line 4 in throw.xslt <<< , and the message xsl: is lost somewhere.

How can I achieve "9.4" behavior at "9.6"?

+5
source share
2 answers

This is due to the message listener to which the MessageEmitter sends messages. In Saxon 9.6, the listener by default implements the UnfailingErrorListener, which cannot throw an exception (like all other listeners in 9.6), but in 9.4 it was possible to exclude exceptions from listeners.

However, you can implement your own message emitter that will throw an exception when it encounters xml: a message with completion set to yes, for example:

 final class ExceptionThrowingMessageEmitter extends XMLEmitter { boolean abort = false; public void startDocument(int properties) throws XPathException { setWriter(new StringWriter()); abort = (properties & ReceiverOptions.TERMINATE) != 0; super.startDocument(properties); } public void endDocument() throws XPathException { XPathException de = new XPathException(getWriter().toString()); de.setErrorCode("XTMM9000"); if (abort) { throw de; } else { //terminate set to no, do something like writing to the log file } } public void close() { // do nothing } } 

and then register it as follows:

 transformer.getUnderlyingController().setMessageEmitter(new ExceptionThrowingMessageEmitter()); 

This way an exception will be thrown when xml: message ends

+3
source

Unfortunately, the new Processing terminated... message is hard-coded in the net.sf.saxon.expr.instruct.Message file (Message.java:253 in 9.6.0-7). Here is a workaround that can give you what you need:

 public static void main(String[] args) throws TransformerException { final StringWriter messageOut = new StringWriter(); try { TransformerFactory fact = new net.sf.saxon.TransformerFactoryImpl(); Transformer newTransformer = fact.newTransformer(new StreamSource(new File("throw.xslt"))); ((net.sf.saxon.jaxp.TransformerImpl)newTransformer).getUnderlyingController().setRecoveryPolicy(Configuration.DO_NOT_RECOVER); ((net.sf.saxon.jaxp.TransformerImpl)newTransformer).getUnderlyingController().setMessageEmitter(new MessageEmitter() { @Override public void open() throws XPathException { setWriter(messageOut); super.open(); } }); newTransformer.transform(new StreamSource(new File("input.xml")), new StreamResult(new File("output.xml"))); } catch (TransformerException e) { System.out.println("THIS IS EXCEPTION: " + e.getMessage() + " <<<"); String message = messageOut.toString(); // this is the "exception message\n" that you want // not sure why it has a \n on it System.out.println("THIS IS THE MESSAGE WE WANT: " + message); throw new TransformerException(message, e); // rethrow using the captured message, if you really want that "exception message" available to a caller in e.getMessage() } } 
+1
source

Source: https://habr.com/ru/post/1234536/


All Articles