TransformerFactory 和 Xalan 依赖冲突

Posted

技术标签:

【中文标题】TransformerFactory 和 Xalan 依赖冲突【英文标题】:TransformerFactory and Xalan Dependency Conflict 【发布时间】:2017-12-22 11:46:54 【问题描述】:

我有以下代码:

javax.xml.transform.TransformerFactory factory = TransformerFactory.newInstance();
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
javax.xml.transform.Transformer transformer = factory.newTransformer();

这正常工作。但是,我还需要在我的 pom.xml 中添加 Xalan 作为依赖项,当我这样做时,上面的代码现在会抛出一个错误:

java.lang.IllegalArgumentException: Not supported: http://javax.xml.XMLConstants/property/accessExternalDTD

我认为这与 Xalan 的 jar 中有不同的 Transformer 实现有关。如何在不更改上述代码并将 Xalan 保留为依赖项的情况下解决此冲突?

【问题讨论】:

为什么需要 Xalan 依赖项? Xalan 从 JDK 1.4 开始就得到认可。正常情况下不需要。 我正在制作一个对每个 Java XML 解析器都有单元测试的 Web 应用程序。 【参考方案1】:

需要如下设置系统级属性

System.setProperty("javax.xml.transform.TransformerFactory","com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");

【讨论】:

这个解决方案是最后帮助我的唯一解决方案,谢谢! 这个解决方案有效,有人能解释为什么吗?? @rahul 之所以有效,是因为无论 JDK 的哪个版本,它都开始支持 JAXP 1.5。 Xerces 仅支持 1.4。通过设置此属性,您可以指定实现类实际上应该是来自 JDK 的实现类。只要您不使用不提供此类的其他 JDK(例如 IBM JDK),这很好。【参考方案2】:

从 Xalan 中排除 Xerces 可修复此问题:

<dependency>
    <groupId>xalan</groupId>
    <artifactId>xalan</artifactId>
    <version>2.7.2</version>
    <exclusions>
        <exclusion>
            <groupId>xerces</groupId>
            <artifactId>xercesImpl</artifactId>
        </exclusion>
    </exclusions>
</dependency>

【讨论】:

我已经排除了 xerces 库,但仍然遇到同样的错误。我怎么知道还有什么可能与 TransformerFactory 发生冲突? 与@DavidChampion 一样,还有其他解决方案吗?【参考方案3】:

如果您是多个 XSL 处理器和/或不同版本,您必须处理并非每个实现都能够处理每个属性的情况。这样做的唯一方法是捕获不支持该属性时抛出的 IllegalArgumentException。看看JAXP documentation中的这个修改过的例子:

javax.xml.transform.TransformerFactory factory = TransformerFactory.newInstance();

try 
    factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
 catch (IllegalArgumentException e) 
    //jaxp 1.5 feature not supported

文档说:

如果可以更改代码,并且对于新开发,建议按照上面的演示设置新属性。通过以这种方式设置属性,应用程序可以确保保持所需的行为,无论它们是部署到旧版本还是新版本的 JDK,或者是否通过系统属性或 jaxp.properties 设置属性。

【讨论】:

通过使用此解决方案,Sonar 仍然不满意,并将其突出显示为 Blocker 说“xml 解析器不应受到 xxe 攻击”【参考方案4】:

对我有用的解决方案是这样做:

compile('org.opensaml:opensaml:2.6.1') 
    exclude group: 'xerces', module: 'xercesImpl'
    exclude module: 'xalan'

【讨论】:

【参考方案5】:

它可能来自您项目的其他 xalan 版本。

在您的 POM 中检查 xalan 的 Dependent Hierarchy,并在所有 xalan 版本中排除 xercesImpl。

【讨论】:

请尝试在评论部分限制可能性。我们需要验证它。所以应该在评论区。谢谢【参考方案6】:

我遇到了类似的问题,在 TransformerFactory::newInstance 中创建了来自 SaxonJ 的实现,在尝试设置它不支持的属性时给了我错误。

查看method documentation,我发现TransformerFactory 有一个优先级列表,它试图找到要返回的实现。

它首先在系统属性中查找,所以在我的 Ant 文件中,在我的运行目标中,我添加了以下内容(其他库将具有相同):

<jvmarg value="-Djavax.xml.transform.TransformerFactory=com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl"/>

这将使 TransformerFactory::newInstance 加载正确的工厂实现。

请记住,我使用的是 OpenJDK8,您必须为其他版本找到正确的包。

【讨论】:

以上是关于TransformerFactory 和 Xalan 依赖冲突的主要内容,如果未能解决你的问题,请参考以下文章

是否可以避免使用 xalan TransformerFactory?

如何防止特征 FEATURE_SECURE_PROCESSING 设置为 true 的 TransformerFactory 剥离属性?

如何在 Java 中选择撒克逊 TransformerFactory

要求在多线程环境中明确 TransformerFactory 的 XSLT Transformer

如何防止具有 META-INF\services\javax.xml.transform.TransformerFactory 的 xalan.jar 接管 Xalan 实现中内置的 JDK 1.6?

weblogic 12c下jxls导出excel报错Could not initialize class org.apache.poi.xssf.usermodel.XSSFVMLDrawing