重复使用 xalan 变压器导致其扩展功能中断
我正在使用 xalan 2.7.1 通过 xslt 样式表验证我的 xml 文档。它适用于第一个文档,并通过使用 NodeInfo.lineNumber 和 NodeInfo.columnNumber 扩展在出现错误时返回错误消息以及 xml 源的正确行号和列号。
问题是,当我尝试重用转换器来验证其他 xml 文档时,它成功转换了文档,但对于所有错误始终返回 lineNumber=columnNumber=-1。
有什么想法吗?
编辑:这是我的代码::
package mycompany;
import java.io.File;
import javax.xml.transform.ErrorListener;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.apache.xalan.processor.TransformerFactoryImpl;
public class XsltTransformer {
public static void main(String[] args) {
TransformerFactory tFactory = TransformerFactory.newInstance();
tFactory.setAttribute(TransformerFactoryImpl.FEATURE_SOURCE_LOCATION, Boolean.TRUE);
StreamSource xsltStreamSource = new StreamSource(new File("E:\\Temp\\Test\\myXslt.xsl"));
try {
Transformer transformer = tFactory.newTransformer(xsltStreamSource);
File srcFolder = new File("E:\\Temp\\Test");
for (File file : srcFolder.listFiles()) {
if (file.getName().endsWith("xml")) {
Source source = new StreamSource(file);
StreamResult result = new StreamResult(System.out);
XsltTransformer xsltTransformer = new XsltTransformer();
ErrorListenerImpl errorHandler = xsltTransformer.new ErrorListenerImpl();
transformer.setErrorListener(errorHandler);
transformer.transform(source, result);
if (errorHandler.e != null) {
System.out.println("Transformation Exception: " + errorHandler.e.getMessage());
}
transformer.reset();
}
}
} catch (TransformerException e) {
e.printStackTrace();
}
}
private class ErrorListenerImpl implements ErrorListener {
public TransformerException e = null;
public void error(TransformerException exception) {
this.e = exception;
}
public void fatalError(TransformerException exception) {
this.e = exception;
}
public void warning(TransformerException exception) {
this.e = exception;
}
}
}
编辑:这里是 myXslt.xsl 和 XML 源:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<axsl:stylesheet
xmlns:axsl="http://www.w3.org/1999/XSL/Transform"
xmlns:iso="http://purl.oclc.org/dsdl/schematron"
xmlns:sch="http://www.ascc.net/xml/schematron"
version="1.0"
xmlns:nodeinfo="xalan://org.apache.xalan.lib.NodeInfo">
<axsl:output
xmlns:svrl="http://purl.oclc.org/dsdl/svrl"
xmlns:schold="http://www.ascc.net/xml/schematron"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
indent="yes"
standalone="yes"
omit-xml-declaration="no"
method="xml" />
<!--SCHEMA METADATA -->
<axsl:template match="/">
<svrl:schematron-output xmlns:svrl="http://purl.oclc.org/dsdl/svrl" xmlns:schold="http://www.ascc.net/xml/schematron"
xmlns:xs="http://www.w3.org/2001/XMLSchema" schemaVersion="ISO19757-3" title="Test ISO schematron file. Introduction mode ">
<svrl:active-pattern>
<axsl:apply-templates />
</svrl:active-pattern>
<axsl:apply-templates mode="M1" select="/" />
</svrl:schematron-output>
</axsl:template>
<!--RULE -->
<axsl:template mode="M1" priority="1000" match="//*[@remote-property]">
<svrl:fired-rule xmlns:svrl="http://purl.oclc.org/dsdl/svrl" xmlns:schold="http://www.ascc.net/xml/schematron"
xmlns:xs="http://www.w3.org/2001/XMLSchema" context="//*[@remote-property]" />
<!--ASSERT -->
<axsl:choose>
<axsl:when test="@remote-property = //@id or @remote-property = //@name" />
<axsl:otherwise>
<svrl:failed-assert xmlns:svrl="http://purl.oclc.org/dsdl/svrl" xmlns:schold="http://www.ascc.net/xml/schematron"
xmlns:xs="http://www.w3.org/2001/XMLSchema" test="@remote-property = //@id or @remote-property = //@name">
<axsl:attribute name="lineNumber">
<axsl:value-of select="nodeinfo:lineNumber()" />
</axsl:attribute>
<axsl:attribute name="columnNumber">
<axsl:value-of select="nodeinfo:columnNumber()" />
</axsl:attribute>
<svrl:text>
Invalid remote-property: remote class element with this id or name does not exists
</svrl:text>
</svrl:failed-assert>
</axsl:otherwise>
</axsl:choose>
</axsl:template>
</axsl:stylesheet>
source1.xml:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<remote-service>
<class name="Table1" table="table1">
<id name="col1"/>
<property name="col2"/>
</class>
</remote-service>
<application>
<text-field name="field1" remote-property="col1X"/>
</application>
</root>
和 source2.xml
<?xml version="1.0" encoding="UTF-8"?>
<root>
<application>
<text-field name="field1" remote-property="col1Z"/>
</application>
</root>
I am using xalan 2.7.1 to validate my xml docs with xslt style sheet. It works fine for the first document and returns error message in case of error along with correct line and column number of xml source by making use of NodeInfo.lineNumber and NodeInfo.columnNumber extensions.
The problem is when I try to reuse transformer to validate other xml docs, it successfully transforms the document but always returns lineNumber=columnNumber=-1 for all errors.
Any idea?
Edit: Here is my code::
package mycompany;
import java.io.File;
import javax.xml.transform.ErrorListener;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.apache.xalan.processor.TransformerFactoryImpl;
public class XsltTransformer {
public static void main(String[] args) {
TransformerFactory tFactory = TransformerFactory.newInstance();
tFactory.setAttribute(TransformerFactoryImpl.FEATURE_SOURCE_LOCATION, Boolean.TRUE);
StreamSource xsltStreamSource = new StreamSource(new File("E:\\Temp\\Test\\myXslt.xsl"));
try {
Transformer transformer = tFactory.newTransformer(xsltStreamSource);
File srcFolder = new File("E:\\Temp\\Test");
for (File file : srcFolder.listFiles()) {
if (file.getName().endsWith("xml")) {
Source source = new StreamSource(file);
StreamResult result = new StreamResult(System.out);
XsltTransformer xsltTransformer = new XsltTransformer();
ErrorListenerImpl errorHandler = xsltTransformer.new ErrorListenerImpl();
transformer.setErrorListener(errorHandler);
transformer.transform(source, result);
if (errorHandler.e != null) {
System.out.println("Transformation Exception: " + errorHandler.e.getMessage());
}
transformer.reset();
}
}
} catch (TransformerException e) {
e.printStackTrace();
}
}
private class ErrorListenerImpl implements ErrorListener {
public TransformerException e = null;
public void error(TransformerException exception) {
this.e = exception;
}
public void fatalError(TransformerException exception) {
this.e = exception;
}
public void warning(TransformerException exception) {
this.e = exception;
}
}
}
Edit: Here are myXslt.xsl and XML sources:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<axsl:stylesheet
xmlns:axsl="http://www.w3.org/1999/XSL/Transform"
xmlns:iso="http://purl.oclc.org/dsdl/schematron"
xmlns:sch="http://www.ascc.net/xml/schematron"
version="1.0"
xmlns:nodeinfo="xalan://org.apache.xalan.lib.NodeInfo">
<axsl:output
xmlns:svrl="http://purl.oclc.org/dsdl/svrl"
xmlns:schold="http://www.ascc.net/xml/schematron"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
indent="yes"
standalone="yes"
omit-xml-declaration="no"
method="xml" />
<!--SCHEMA METADATA -->
<axsl:template match="/">
<svrl:schematron-output xmlns:svrl="http://purl.oclc.org/dsdl/svrl" xmlns:schold="http://www.ascc.net/xml/schematron"
xmlns:xs="http://www.w3.org/2001/XMLSchema" schemaVersion="ISO19757-3" title="Test ISO schematron file. Introduction mode ">
<svrl:active-pattern>
<axsl:apply-templates />
</svrl:active-pattern>
<axsl:apply-templates mode="M1" select="/" />
</svrl:schematron-output>
</axsl:template>
<!--RULE -->
<axsl:template mode="M1" priority="1000" match="//*[@remote-property]">
<svrl:fired-rule xmlns:svrl="http://purl.oclc.org/dsdl/svrl" xmlns:schold="http://www.ascc.net/xml/schematron"
xmlns:xs="http://www.w3.org/2001/XMLSchema" context="//*[@remote-property]" />
<!--ASSERT -->
<axsl:choose>
<axsl:when test="@remote-property = //@id or @remote-property = //@name" />
<axsl:otherwise>
<svrl:failed-assert xmlns:svrl="http://purl.oclc.org/dsdl/svrl" xmlns:schold="http://www.ascc.net/xml/schematron"
xmlns:xs="http://www.w3.org/2001/XMLSchema" test="@remote-property = //@id or @remote-property = //@name">
<axsl:attribute name="lineNumber">
<axsl:value-of select="nodeinfo:lineNumber()" />
</axsl:attribute>
<axsl:attribute name="columnNumber">
<axsl:value-of select="nodeinfo:columnNumber()" />
</axsl:attribute>
<svrl:text>
Invalid remote-property: remote class element with this id or name does not exists
</svrl:text>
</svrl:failed-assert>
</axsl:otherwise>
</axsl:choose>
</axsl:template>
</axsl:stylesheet>
source1.xml:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<remote-service>
<class name="Table1" table="table1">
<id name="col1"/>
<property name="col2"/>
</class>
</remote-service>
<application>
<text-field name="field1" remote-property="col1X"/>
</application>
</root>
and source2.xml
<?xml version="1.0" encoding="UTF-8"?>
<root>
<application>
<text-field name="field1" remote-property="col1Z"/>
</application>
</root>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
javadoc状态:
您可能必须将 ErrorListener 引用重置为重置转换器的新 ErrorListener。
更新
我没有使用 schematron 库的经验,从我看来,这可能是重置变压器使用该库的问题。
如果您无法重置变压器,您可以使用 XSL 模板工具来避免必须解释每个 Transorm 上的 XSL 表:
稍后通过从中获取变压器来重新使用模板:
The javadoc states:
You might have to reset your ErrorListener reference to the new ErrorListener of the reset transformer.
update
I have no experience with the schematron library, from what I see it is probably an issue of that library being used by a reset transformer.
If you cannot get it to work resetting the transformer you might be able to use the XSL template facility to prevent having to interpret the XSL sheet on every transorm:
Later re-use the template by getting the transformer from it: