Java 如何从TransformerException中提取有用信息
我正在使用Java 如何从TransformerException中提取有用信息,java,exception,xslt,Java,Exception,Xslt,我正在使用javax.xml.transform.*进行XSLT转换。由于要使用的xslt文件来自外部世界,因此该文件中可能存在错误,我将向用户返回一些有意义的响应 虽然我可以很容易地捕获转换异常s,但我发现没有办法从中获得足够的信息。例如,如果有一个标记要被一个结束标记终止,printStackTrace()会给出一条疤痕消息 javax.xml.transform.TransformerConfigurationException: Could not compile stylesheet
javax.xml.transform.*
进行XSLT转换。由于要使用的xslt文件来自外部世界,因此该文件中可能存在错误,我将向用户返回一些有意义的响应
虽然我可以很容易地捕获转换异常
s,但我发现没有办法从中获得足够的信息。例如,如果有一个标记要被一个结束标记终止,printStackTrace()
会给出一条疤痕消息
javax.xml.transform.TransformerConfigurationException: Could not compile stylesheet
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTemplates(Unknown Source)
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTransformer(Unknown Source)
... (100 lines)
而getMessage()
只提供
Could not compile stylesheet
他们都没有给出错误的真正原因
我注意到在Eclipse测试控制台中可以看到以下内容
[Fatal Error] :259:155: The element type "sometag" must be terminated by the matching end-tag "</sometag>".
ERROR: 'The element type "sometag" must be terminated by the matching end-tag "</sometag>".'
FATAL ERROR: 'Could not compile stylesheet'
[致命错误]:259:155:元素类型“sometag”必须由匹配的结束标记“”终止。
错误:“元素类型“sometag”必须由匹配的结束标记“”终止。”
致命错误:“无法编译样式表”
这正是我想要的。不幸的是,由于这是一个web应用程序,用户无法看到这一点
如何向用户显示正确的错误消息?将您自己的错误消息放在您的Transformer
实例上,如下所示:
final List<TransformationException> errors = new ArrayList<TransformationException>();
Transformer transformer = ... ;
transformer.setErrorListener(new ErrorListener() {
@Override
public void error(TransformerException exception) {
errors.add(exception);
}
@Override
public void fatalError(TransformerException exception) {
errors.add(exception);
}
@Override
public void warning(TransformerException exception) {
// handle warnings as well if you want them
}
});
// Any other transformer setup
Source xmlSource = ... ;
Result outputTarget = ... ;
try {
transformer.transform(xmlSource, outputTarget);
} catch (TransformerException e) {
errors.add(e); // Just in case one is thrown that isn't handled
}
if (!errors.isEmpty()) {
// Handle errors
} else {
// Handle output since there were no errors
}
您可以将System.out配置为写入自己的OutputStream。 使用ErrorListener不会捕获所有输出。 如果使用线程,可以查看此处()以避免更改System.out以查找其他线程 范例
public final class XslUtilities {
private XslUtilities() {
// only static methods
}
public static class ConvertWithXslException extends Exception {
public ConvertWithXslException(String message, Throwable cause) {
super(message, cause);
}
}
public static String convertWithXsl(String input, String xsl) throws ConvertWithXslException {
ByteArrayOutputStream systemOutByteArrayOutputStream = new ByteArrayOutputStream();
PrintStream oldSystemOutPrintStream = System.out;
System.setOut(new PrintStream(systemOutByteArrayOutputStream));
ByteArrayOutputStream systemErrByteArrayOutputStream = new ByteArrayOutputStream();
PrintStream oldSystemErrPrintStream = System.err;
System.setErr(new PrintStream(systemErrByteArrayOutputStream));
String resultXml;
try {
System.setProperty("javax.xml.transform.TransformerFactory", "net.sf.saxon.TransformerFactoryImpl");
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer(new StreamSource(new StringReader(xsl)));
StringWriter stringWriter = new StringWriter();
transformer.transform(new StreamSource(new StringReader(input)), new StreamResult(stringWriter));
resultXml = stringWriter.toString();
} catch (TransformerException e) {
System.out.flush();
final String systemOut = systemOutByteArrayOutputStream.toString();
System.err.flush();
final String systemErr = systemErrByteArrayOutputStream.toString();
throw new ConvertWithXslException("TransformerException - " + e.getMessageAndLocation()
+ (systemOut.length() > 0 ? ("\nSystem.out:" + systemOut) : "")
+ (systemErr.length() > 0 ? ("\nSystem.err:" + systemErr) : ""), e);
} finally {
System.setOut(oldSystemOutPrintStream);
System.setErr(oldSystemErrPrintStream);
}
return resultXml;
}
}
首先,任何解决方案都可能取决于您对XSLT处理器的选择。JAXP接口的不同实现很可能在它们生成的异常中提供不同的信息 XML解析器的错误可能存在于包装异常中。出于历史原因,TransformerConfigurationException同时提供getException()和getCause()来访问包装的异常,这两种异常都值得检查 或者,信息可能是在单独调用ErrorListener时提供的
最后,XML解析器(而不是XSLT处理器)会检测到这个特定错误,因此在第一个实例中,它将由解析器处理。设置解析器的ErrorHandler并捕获该级别的解析错误可能是值得的。如果您希望显式控制转换所使用的XML解析器,请使用其XMLReader经过适当初始化的SAXSource。您真的不能。如果要运行验证步骤……原因异常中不是原因吗?@agad不幸的是
getCause()
调用返回null
@earthine关于getOriginalException()的情况如何?@agad在TransformerException
或TransformerConfigurationException
中都没有这样的方法。它捕捉不到什么输出?他想要的只是错误。这真是太过分了。另外,如果他的服务器在运行时输出了其他内容,因为它是一个多线程系统,该怎么办?用户将在收到的错误消息中看到该输出。这不是一个好的解决方案。取决于变压器引擎的一些(有用的)输出进入System.out。不幸的是,ErrorListener没有捕获到这一点。要避免捕获其他线程输出,请使用maiaco解决方案。太好了。
public final class XslUtilities {
private XslUtilities() {
// only static methods
}
public static class ConvertWithXslException extends Exception {
public ConvertWithXslException(String message, Throwable cause) {
super(message, cause);
}
}
public static String convertWithXsl(String input, String xsl) throws ConvertWithXslException {
ByteArrayOutputStream systemOutByteArrayOutputStream = new ByteArrayOutputStream();
PrintStream oldSystemOutPrintStream = System.out;
System.setOut(new PrintStream(systemOutByteArrayOutputStream));
ByteArrayOutputStream systemErrByteArrayOutputStream = new ByteArrayOutputStream();
PrintStream oldSystemErrPrintStream = System.err;
System.setErr(new PrintStream(systemErrByteArrayOutputStream));
String resultXml;
try {
System.setProperty("javax.xml.transform.TransformerFactory", "net.sf.saxon.TransformerFactoryImpl");
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer(new StreamSource(new StringReader(xsl)));
StringWriter stringWriter = new StringWriter();
transformer.transform(new StreamSource(new StringReader(input)), new StreamResult(stringWriter));
resultXml = stringWriter.toString();
} catch (TransformerException e) {
System.out.flush();
final String systemOut = systemOutByteArrayOutputStream.toString();
System.err.flush();
final String systemErr = systemErrByteArrayOutputStream.toString();
throw new ConvertWithXslException("TransformerException - " + e.getMessageAndLocation()
+ (systemOut.length() > 0 ? ("\nSystem.out:" + systemOut) : "")
+ (systemErr.length() > 0 ? ("\nSystem.err:" + systemErr) : ""), e);
} finally {
System.setOut(oldSystemOutPrintStream);
System.setErr(oldSystemErrPrintStream);
}
return resultXml;
}
}