如何获取发生 Saxon XSLT 编译错误的行号?
How to get the line number where an Saxon XSLT compilation error occurs?
我正在使用 Saxon PE 9.7.0.18。
我正在使用如下代码编译 XSLT:
import javax.xml.transform.TransformerFactory;
import net.sf.saxon.TransformerFactoryImpl;
...
StringBuilder errorString = new StringBuilder();
ErrorListener errorListener = new ErrorListener() {
public void warning(TransformerException e) {
errorString.append("\nERROR: ").append(e.getMessageAndLocation()); }
public void error(TransformerException e) {
errorString.append("\nWARN: ").append(e.getMessageAndLocation()); }
public void fatalError(TransformerException e) {
errorString.append("\nFATAL: ").append(e.getMessageAndLocation()); }
};
TransformerFactoryImpl transformerFactory =
(TransformerFactoryImpl) TransformerFactory.newInstance(
TransformerFactoryImpl.class.getName(),
DocumentGenerator.class.getClassLoader());
transformerFactory.setErrorListener(errorListener);
Templates templates = transformerFactory.newTemplates(new DOMSource(xslt));
xsltTransformerFactory = new XsltTransformerFactory() {
@SneakyThrows(TransformerConfigurationException.class)
@Override public Transformer newTransformer() { return templates.newTransformer(); }
};
Transformer transformer = xsltTransformerFactory.newTransformer();
不幸的是,如果 XSLT 文件无效,则会产生如下错误:
FATAL: Required item type of first operand of '/' is node();
supplied value has item type xs:string
XSLT 文件有时长达数千行,因为它们是从另一个系统生成的。知道在哪一行发生这样的错误会很有帮助。 (刚才我通过重复删除 XSLT 源文件的一半并查看错误是否仍然发生,以定位有问题的行来执行 "binary search"。一旦我找到该行,XSLT 文件中的错误就非常明显!)
我确定 XSLT 处理器必须知道它正在处理的行?
在调试器中我看到 TransformerException
包含一个 AttributeLocator
但 lineNumber
和 columnNumber
属性都是 -1,这大概解释了为什么 getMessageAndLocation()
方法不包括位置。
我知道在 Saxon 的编译过程中可能会有一个编译时标志来影响这一点,但我没有自己编译 Saxon,我在购买 PE 版本时从 https://www.saxonica.com/download/java.xml 下载了它。
如何找出 XSLT 错误的行号?
您提供了来自 DOM 树的样式表输入,DOM 不保留行号。
除非您有充分的理由使用 DOM,否则最好避免使用。 DOM 在跟踪基本 URI 方面也很糟糕,这会影响 xsl:include
和 xsl:import
的解析等等。而且,它不是线程安全的。
优先使用StreamSource
或SAXSource
。
我正在使用 Saxon PE 9.7.0.18。
我正在使用如下代码编译 XSLT:
import javax.xml.transform.TransformerFactory;
import net.sf.saxon.TransformerFactoryImpl;
...
StringBuilder errorString = new StringBuilder();
ErrorListener errorListener = new ErrorListener() {
public void warning(TransformerException e) {
errorString.append("\nERROR: ").append(e.getMessageAndLocation()); }
public void error(TransformerException e) {
errorString.append("\nWARN: ").append(e.getMessageAndLocation()); }
public void fatalError(TransformerException e) {
errorString.append("\nFATAL: ").append(e.getMessageAndLocation()); }
};
TransformerFactoryImpl transformerFactory =
(TransformerFactoryImpl) TransformerFactory.newInstance(
TransformerFactoryImpl.class.getName(),
DocumentGenerator.class.getClassLoader());
transformerFactory.setErrorListener(errorListener);
Templates templates = transformerFactory.newTemplates(new DOMSource(xslt));
xsltTransformerFactory = new XsltTransformerFactory() {
@SneakyThrows(TransformerConfigurationException.class)
@Override public Transformer newTransformer() { return templates.newTransformer(); }
};
Transformer transformer = xsltTransformerFactory.newTransformer();
不幸的是,如果 XSLT 文件无效,则会产生如下错误:
FATAL: Required item type of first operand of '/' is node();
supplied value has item type xs:string
XSLT 文件有时长达数千行,因为它们是从另一个系统生成的。知道在哪一行发生这样的错误会很有帮助。 (刚才我通过重复删除 XSLT 源文件的一半并查看错误是否仍然发生,以定位有问题的行来执行 "binary search"。一旦我找到该行,XSLT 文件中的错误就非常明显!)
我确定 XSLT 处理器必须知道它正在处理的行?
在调试器中我看到 TransformerException
包含一个 AttributeLocator
但 lineNumber
和 columnNumber
属性都是 -1,这大概解释了为什么 getMessageAndLocation()
方法不包括位置。
我知道在 Saxon 的编译过程中可能会有一个编译时标志来影响这一点,但我没有自己编译 Saxon,我在购买 PE 版本时从 https://www.saxonica.com/download/java.xml 下载了它。
如何找出 XSLT 错误的行号?
您提供了来自 DOM 树的样式表输入,DOM 不保留行号。
除非您有充分的理由使用 DOM,否则最好避免使用。 DOM 在跟踪基本 URI 方面也很糟糕,这会影响 xsl:include
和 xsl:import
的解析等等。而且,它不是线程安全的。
优先使用StreamSource
或SAXSource
。