31

我正在使用带有 groovy 的 logback,并在解析 xml 时出现很多警告。我知道导致此问题的 JDK1.7_u45 中的错误。

Warning:  org.apache.xerces.parsers.SAXParser: Property 'http://javax.xml.XMLConstants/property/accessExternalDTD' is not recognized.
Warning:  org.apache.xerces.parsers.SAXParser: Property 'http://www.oracle.com/xml/jaxp/properties/entityExpansionLimit' is not recognized.

有什么方法可以关闭此日志警告,使其不再显示在 DEBUG 中?我尝试使用过滤器编写过滤器,但没有帮助。

4

5 回答 5

26

这是 JRE 中的一个已知错误,将其报告为警告。在此处此处查看错误报告

仅当您的类路径中有 xerces jar 时才会出现此问题,xerces 实现无法识别该属性并在org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.setProperty()上引发异常,从而导致警告日志(到系统.err) 来自com.sun.org.apache.xalan.internal.xsltc.compiler.Parser.parse()

简单(如果可能)的解决方案是从类路径中删除 xerces jar。

您的日志过滤器不起作用,因为错误从未发送到 slf4j。哪种建议解决问题的复杂方法 - 将System.err 重定向到 slf4j,然后在其上使用日志过滤器。

重现问题的示例代码(基于问题报告):

import java.io.IOException;
import java.net.URL;

import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamSource;

public class XercesTest {
    public static void main(String[] args) throws IOException, TransformerConfigurationException {
        TransformerFactory tf = TransformerFactory.newInstance();
        URL xsl = MainClass.class.getResource("build.xsl");
        StreamSource stylesheetSource = new StreamSource(
            xsl.openStream(), xsl.toExternalForm());
        tf.newTransformer(stylesheetSource);
    }
}

构建.xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <!-- TODO: Auto-generated template -->
    </xsl:template>
</xsl:stylesheet>

和maven依赖:

<dependency>
    <groupId>xerces</groupId>
    <artifactId>xercesImpl</artifactId>
    <version>2.11.0</version>
</dependency>
于 2015-07-06T20:31:24.773 回答
2

我在一个项目中也遇到了这个错误。据我了解,较新版本的 JRE 内置了 Xerces 实现。更重要的是,JRE 版本正确支持accessExternalDTDentityExpansionLimit属性。

因为我有一个包含xercesImpl.jar在我的 war 文件中的下游依赖项,所以我的解决方案是使用下面的代码将其build.gradle拉出,并让 xerces 的 JRE 实现接管类路径。

warApplication {
    from '/WEB-INF/lib'
        exclude 'xercesImpl*.jar'
}
于 2017-10-25T01:03:29.320 回答
1

如果无法从类路径中删除 xerces,您可以更明确地说明要使用哪个工厂,从而避免引入 xerces。这里有两种解决特定工厂的方法:

public static SchemaFactory getSchemaFactory() {
  return schemaFactory =
    SchemaFactory.newInstance(
        "http://www.w3.org/2001/XMLSchema",
        "com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory",
        null);
}

public static TransformerFactory getTransformerFactory() {
  try {
    final Class<?> transformerFactoryImplClass =
      TransformerFactory.class
          .getClassLoader().loadClass("com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");
    final Method factoryGetter =
      transformerFactoryImplClass.getDeclaredMethod("newTransformerFactoryNoServiceLoader");
    return (TransformerFactory) factoryGetter.invoke(null);
  } catch (ClassNotFoundException
    | NoSuchMethodException
    | IllegalAccessException
    | InvocationTargetException e) {
    // fallback in case com.sun.* is not available
    return TransformerFactory.newInstance();
  }
}
于 2019-06-05T11:32:08.370 回答
0

我知道的老问题,只是想发布一个快捷方式。正如Dana Britzman 的回答中提到的,较新版本的 JRE 内置了 Xerces 和 Xalan 实现。更重要的是,JRE 版本正确支持 accessExternalDTD 和 entityExpansionLimit 属性。

我需要一个 xalan 实现,并做了如下

TransformerFactory tf = com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newInstance("com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl", null);
于 2020-09-20T17:07:35.473 回答
0

为了使用最近的 JDK8 版本解决这个问题,我使用了以下代码:

  DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance("com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl", this.getClass().getClassLoader());

内部打包类是 JDK 的一部分。这将保证它使用 JDK 类并且不会尝试使用任何其他版本(例如,Weblogic 服务器会发生这种情况)

于 2021-03-22T17:06:59.823 回答