TransformerFactory和Xalan依赖冲突

13

我有以下代码:

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依赖?自JDK 1.4以来,Xalan已被认可。在正常情况下,它是不必要的。 - fhossfel
我正在制作一个Web应用程序,其中包含每个Java XML解析器的单元测试。 - Velvet Carrot
7个回答

14

需要按照以下方式设置系统级属性

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

1
这个解决方案最终是唯一帮助我的,谢谢! - Gregor
这个解决方案可行,有人能解释一下为什么吗? - Rahul
1
@rahul 这个可以工作是因为自从JDK支持JAXP 1.5版本以来,它就开始支持了。而Xerces只支持1.4版本。通过设置这个属性,您指定实现类应该实际上是来自JDK的那个类。只要您不使用不提供此类的不同JDK,例如IBM JDK,这就没问题。 - JSamir
我在同一类的静态代码块中使用 TransformerFactory 添加了这行代码,但现在在 JUnit 测试用例中出现了 javax.xml.transform.TransformerFactoryConfigurationError: Provider org.apache.xalan.processor.TransformerFactoryImpl not found 错误。请帮忙解决。 - tarekahf

5
将Xerces从Xalan中排除可以解决此问题:
<dependency>
    <groupId>xalan</groupId>
    <artifactId>xalan</artifactId>
    <version>2.7.2</version>
    <exclusions>
        <exclusion>
            <groupId>xerces</groupId>
            <artifactId>xercesImpl</artifactId>
        </exclusion>
    </exclusions>
</dependency>

5
我已经排除了xerces库,但仍然遇到相同的错误。我该如何找出还可能与TransformerFactory冲突的内容? - David Champion
和 @DavidChampion 一样,还有其他人有解决方案吗? - davejal

3
这是因为我使用了来自外部依赖项的xalan转换器工厂。
TransformerFactory factory = TransformerFactory.newInstance();

我刚刚指定了我将使用AdoptOpenJdk提供的内部jar包。

TransformerFactory factory = TransformerFactory.newInstance("com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl", null);

它对我有用,我更喜欢这个解决方案而不是那个有更多偏好的解决方案https://dev59.com/SVcO5IYBdhLWcg3w3VAc#64364531,影响较小。谢谢。 - fl4l

2

如果您使用多个XSL处理器或不同版本的处理器,您需要处理不能处理每个属性的情况。唯一的方法是捕获抛出的IllegalArgumentException异常,如果该属性不受支持。请查看来自JAXP文档的以下修改示例:

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设置属性,都能保持所需的行为。

1
通过使用这个解决方案,Sonar 仍然不满意并将其标记为阻碍问题,称“XML 解析器不应该容易受到 XXE 攻击”。 - Sumit Rane

1
我曾遇到类似的问题,其中SaxonJ的实现是在TransformerFactory::newInstance中创建的,当尝试设置不支持的属性时,会导致错误。
查看方法文档,我发现TransformerFactory有一个优先级列表,它尝试查找要返回的实现。
它首先查找系统属性,因此在我的Ant文件中,在运行目标内,我添加了以下内容(其他库将具有相同的内容):
<jvmarg value="-Djavax.xml.transform.TransformerFactory=com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl"/>

这将使TransformerFactory :: newInstance加载正确的工厂实现。
请注意,我使用的是OpenJDK8,您需要为其他版本找到正确的软件包。

0

这可能来自于你的项目中其他版本的xalan。

检查你POM中依赖层次结构里的xalan,排除所有版本中的xercesImpl。


1
请在注释部分限制可能性。我们需要进行验证。因此,它应该在注释部分。谢谢。 - parlad

0
我的解决方案是这样的:
compile('org.opensaml:opensaml:2.6.1') {
    exclude group: 'xerces', module: 'xercesImpl'
    exclude module: 'xalan'
}

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