xslt:撒克逊 9.4 与撒克逊 9.6 中的消息
Posted
技术标签:
【中文标题】xslt:撒克逊 9.4 与撒克逊 9.6 中的消息【英文标题】:xslt:message in Saxon 9.4 vs Saxon 9.6 【发布时间】:2016-01-25 18:43:39 【问题描述】:我正在尝试从 java 代码中抛出异常,该异常将在使用 Saxon 时包含来自 xsl:message 标记的消息。
使用下面的 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>
在 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;
它给出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;
它给出了THIS IS EXCEPTION: Processing terminated by xsl:message at line 4 in throw.xslt <<<
,而 xsl:message 在某处丢失了。
如何在“9.6”上实现“9.4”行为?
【问题讨论】:
【参考方案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()
【讨论】:
【参考方案2】:这是由于 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
然后,像这样注册它:
transformer.getUnderlyingController().setMessageEmitter(new ExceptionThrowingMessageEmitter());
这样,当有终止 xml:message 时会抛出异常
【讨论】:
不知道有没有办法使用Emitter获取xsl:message行/列号?以上是关于xslt:撒克逊 9.4 与撒克逊 9.6 中的消息的主要内容,如果未能解决你的问题,请参考以下文章