使用Xalan与Saxon并行运行

8

我在我的应用程序中使用Xalan,但需要使用Saxon与参考实现一起生成测试输出以进行比较。 我想在单元测试期间同时使用它们。 但是,一旦在项目.pom中添加对Saxon的依赖项,应用程序似乎在测试期间对所有xslt和XPath操作都使用Saxon:

<dependency>
  <groupId>net.sf.saxon</groupId>
  <artifactId>Saxon-HE</artifactId>
  <version>9.4</version>
  <scope>test</scope>
</dependency>

由于XPath的不同行为,当生成输出时,主应用程序会失败。在测试范围之外运行主应用程序时,它可以正常工作。

在测试期间,我该如何使用Xalan运行主应用程序,但使用Saxon运行测试?

在运行Xalan和Saxon部分之前,我尝试设置以下属性:

System.setProperty("javax.xml.transform.TransformerFactory", "org.apache.xalan.processor.TransformerFactoryImpl ");
System.setProperty("javax.xml.transform.TransformerFactory", "net.sf.saxon.TransformerFactoryImpl");

我也尝试将Xalan和Saxon部分放在不同的项目中,并尝试从第三个项目中同时使用它们,但结果相同。
2个回答

11
避免依赖JAXP工厂机制来选择转换引擎。相反,显式加载您想要的引擎:这更加可靠且更快。对于Saxon,请替换调用中的内容。
TransformerFactory.newInstance()

带有

new net.sf.saxon.TransformerFactoryImpl()

对于Xalan使用

new org.apache.xalan.processor.TransformerFactoryImpl()

尽管如此,失败的部分是XPath。有没有办法告诉XPathFactory使用默认实现?这个答案说明了如何做相反的事情,即在Java中使用Saxon实现https://dev59.com/Z0fSa4cB1Zd3GeqPAMkd。 - Danik
1
根据http://www.jarvana.com/jarvana/view/xalan/xalan/2.7.0/xalan-2.7.0.jar!/org/apache/xpath/jaxp/XPathFactoryImpl.class?classDetails=ok,这将是org.apache.xpath.jaxp.XPathFactoryImpl。无论如何,我建议您在应用程序中使用JAXP机制,而不是使其依赖于实现,除非您的应用程序具有极端用例。只在测试中使用impl相关代码。 - Kasun Gajasinghe
2
我不同意。很多人会因为使用JAXP机制并选择XPath 2.0处理器而出现问题,而他们的应用程序需要XPath 1.0处理器。你不能明确地要求XPath 1.0处理器;如果你不说你想要什么,你就不知道你会得到什么,而且可能无法正常工作。 - Michael Kay
我不得不使用Saxon,因为参考实现依赖于它。根据你的答案,我已经让它正常工作了,谢谢!(请查看下面我的回答中的解决方案) - Danik
回答更新:对于XSLT,该回答仍然有效,但是对于XPath,Saxon不再声明自己为JAXP XPath工厂提供程序。这是因为XPath的JAXP API定义非常松散(很多参数被声明为“Object”,在实现时不确定实际接受什么),因此针对一个XPath处理器编写的应用程序很少能在不同的处理器上使用,尤其是当它实现了不同版本的XPath语言时。 - Michael Kay

2
这里是完整性的解决方案:
System.setProperty(XPathFactory.DEFAULT_PROPERTY_NAME + ":"
    + XPathFactory.DEFAULT_OBJECT_MODEL_URI,
    "org.apache.xpath.jaxp.XPathFactoryImpl");
System.setProperty(XPathFactory.DEFAULT_PROPERTY_NAME + ":"
    + NamespaceConstant.OBJECT_MODEL_SAXON,
    "net.sf.saxon.xpath.XPathFactoryImpl");

XPathFactory jaxpFactory =
    XPathFactory.newInstance(XPathFactory.DEFAULT_OBJECT_MODEL_URI);
XPathFactory saxonFactory =
    XPathFactory.newInstance(NamespaceConstant.OBJECT_MODEL_SAXON);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接