xslt:Saxon 9.4与Saxon 9.6的消息

tom*_*mgi 6 java xml xslt saxon

我正在尝试从使用Saxon时包含来自xsl:message标签的消息的java代码中抛出异常.

使用以下xslt文件

<?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>
Run Code Online (Sandbox Code Playgroud)

在Saxon 9.4上使用以下代码

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;
    }
}   
Run Code Online (Sandbox Code Playgroud)

它给出了THIS IS EXCEPTION: exception message <<<,这是我期待的行为.

但是对于Saxon 9.6而言,由于API的变化而调整了一些代码

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

它给出THIS IS EXCEPTION: Processing terminated by xsl:message at line 4 in throw.xslt <<<了xsl:消息丢失的地方.

如何在"9.6"上实现"9.4"行为?

小智 5

这是由于MessageEmitter向其发送消息的消息侦听器。在saxon 9.6中,默认侦听器实现了UnfailingErrorListener,它不能引发异常(与9.6中的所有其他侦听器一样),但是在9.4中,可以从侦听器引发异常。

但是,您可以实现自己的消息发射器,遇到终止设置为yes的xml:message时会抛出异常,如下所示:

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
  }
}
Run Code Online (Sandbox Code Playgroud)

然后,像这样注册它:

transformer.getUnderlyingController().setMessageEmitter(new ExceptionThrowingMessageEmitter());  
Run Code Online (Sandbox Code Playgroud)

这样,当终止xml:message时,将引发异常


Ale*_*uda 1

不幸的是,新消息Processing terminated...被硬编码在 net.sf.saxon.expr.instruct.Message 中(9.6.0-7 中的 Message.java:253)。这是一个可能满足您需要的解决方法:

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()
    }
}
Run Code Online (Sandbox Code Playgroud)