Apache Xerces 配置参数详解

逐项解析 Xerces-J 2.12.2 的 SAX 标准特性、扩展特性与扩展属性、JAXP 系统属性及 ErrorHandler 错误处理,全部配置项均附 OpenJDK 17 下的实测默认值与运行回显。

Apache XercesApache Xerces2026/10/12

Apache Xerces 配置参数详解

一、配置体系总览

Xerces-J(本文实测版本 2.12.2)的配置分为四层,作用范围从大到小:

层次机制典型示例优先级
JAXP 工厂选择系统属性 / ServiceLoader-Djavax.xml.parsers.DocumentBuilderFactory=...最高
JAXP 工厂开关工厂对象的方法factory.setNamespaceAware(true)、factory.setFeature(...)次之
解析器特性URI 字符串标识的布尔开关reader.setFeature("http://apache.org/xml/features/validation/schema", true)再次
解析器属性URI 字符串标识的对象注入reader.setProperty(".../external-schemaLocation", "...")最低(同层按调用顺序)

特性(feature)与属性(property)的 URI 遵循两个命名空间:

  • SAX 标准前缀:http://xml.org/sax/features/、http://xml.org/sax/properties/
  • Xerces 扩展前缀:http://apache.org/xml/features/、http://apache.org/xml/properties/

所有实测结论均来自 OpenJDK 17(Ubuntu 22.04 与 CentOS 8 双端一致)下的探测程序:对 XMLReader 逐项调用 getFeature/getProperty 并打印结果。

二、SAX 标准特性

以 http://xml.org/sax/features/ 为前缀。对 JAXP 工厂产出的解析器(org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser)实测默认值:

特性 URI实测默认值说明
http://xml.org/sax/features/namespacesfalse(JAXP 工厂)/ true(原生 SAXParser 类)开启后回调中的 uri、localName 生效。这就是默认 SAX 输出 uri/localName 为空串、而 Xerces 原生类有值的原因
http://xml.org/sax/features/namespace-prefixestrue(JAXP 工厂)/ false(原生 SAXParser 类)是否报告 xmlns:* 与 xmlns 属性
http://xml.org/sax/features/validationfalseDTD 校验开关。只开它对 XSD 文档无效,实测报 "no grammar found"

与 setNamespaceAware(true) 的关系:工厂方法内部会同步 namespaces 特性;直接操作 XMLReader 时用 setFeature 即可,两者等价。

三、Xerces 扩展特性

以 http://apache.org/xml/features/ 为前缀,为 Xerces 专属能力。逐项实测结果(两 OS 一致):

3.1 校验类

特性 URI(完整)实测默认值说明
http://apache.org/xml/features/validation/schemafalseXSD 校验总开关。与 http://xml.org/sax/features/validation 同时开启才会执行 Schema 校验
http://apache.org/xml/features/validation/dynamicfalse动态校验:文档声明了 grammar 才校验
http://apache.org/xml/features/validation/schema-full-checking可识别完整 Schema 约束检查,更严格但更慢
http://apache.org/xml/features/honour-all-schemaLocationsfalse校验 xsi:schemaLocation 声明的全部 schema。注意:没有 /validation/ 段,写成 .../features/validation/honour-all-schemaLocations 会实测抛 SAXNotRecognizedException
http://apache.org/xml/features/validation/warn-on-duplicate-attdef可识别DTD 重复属性定义告警
http://apache.org/xml/features/validation/warn-on-undeclared-elemdeffalseDTD 未声明元素告警。注意是 elemdef,写成 warn-on-undeclared-element 实测不被识别

3.2 DTD 与实体加载类

特性 URI(完整)实测默认值说明
http://apache.org/xml/features/nonvalidating/load-external-dtdtrue即使不校验也加载外部 DTD。生产环境建议关闭以防外部实体注入
http://apache.org/xml/features/nonvalidating/load-dtd-grammarfalse加载 DTD 作为 grammar
http://apache.org/xml/features/disallow-doctype-declfalse禁止 DOCTYPE 声明,防御 XXE 的首选开关

disallow-doctype-decl 的实测拦截效果——对含 <!DOCTYPE books [<!ENTITY xxe SYSTEM "file:///etc/passwd">]> 的文档开启该特性后解析:

已开启 disallow-doctype-decl=true,开始解析...
[Fatal Error] :2:10: DOCTYPE is disallowed when the feature "http://apache.org/xml/features/disallow-doctype-decl" set to true.
解析被拦截,异常原文: 行=2 列=10 DOCTYPE is disallowed when the feature "http://apache.org/xml/features/disallow-doctype-decl" set to true.

3.3 解析行为类

特性 URI(完整)实测默认值说明
http://apache.org/xml/features/standard-uri-conformantfalse严格 URI 合规检查
http://apache.org/xml/features/continue-after-fatal-error可识别致命错误后是否继续
http://apache.org/xml/features/allow-java-encodings可识别允许 Java 风格编码名
http://apache.org/xml/features/generate-synthetic-annotations可识别Schema 综合注解生成
http://apache.org/xml/features/validate-annotations可识别校验 Schema 注解本身

四、Xerces 扩展属性

以 http://apache.org/xml/properties/ 为前缀,值是对象而非布尔值。实测可读(未设置时返回 null):

属性 URI(完整)实测值说明
http://apache.org/xml/properties/schema/external-schemaLocationnull外部指定 XSD(带命名空间文档),键值格式为"命名空间 URI + 空格 + schema 路径",多对用空格分隔
http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocationnull外部指定 XSD(无命名空间文档),值为单个路径

实测一(用 external-schemaLocation 对违规文档校验):

XMLReader reader = new org.apache.xerces.parsers.SAXParser();
reader.setFeature("http://xml.org/sax/features/validation", true);
reader.setFeature("http://apache.org/xml/features/validation/schema", true);
reader.setProperty("http://apache.org/xml/properties/schema/external-schemaLocation",
        "http://www.example.com/books /root/xerces-demo/src/main/resources/books.xsd");
reader.setErrorHandler(handler);
reader.parse("src/main/resources/books-invalid.xml");

实测回显:

---- 校验 books-invalid.xml(通过扩展属性指定 schema)----
[ERROR]   行 8 列 11: cvc-complex-type.4: Attribute 'id' must appear on element 'book'.
[ERROR]   行 11 列 36: cvc-datatype-valid.1.2.1: 'not-a-number' is not a valid value for 'decimal'.
[ERROR]   行 11 列 36: cvc-type.3.1.3: The value 'not-a-number' of element 'price' is not valid.
解析结束

实测二(路径错误提示):把属性值写成相对路径 src/main/resources/books.xsd 时,该路径会基于实例文档的 base URI 解析(而非进程工作目录),实测报:

[WARNING] 行 3: schema_reference.4: Failed to read schema document 'src/main/resources/books.xsd', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not <xsd:schema>.

结论:属性值一律使用绝对路径或绝对 URL。另外两个实测细节:对带默认命名空间的文档误用 external-noNamespaceSchemaLocation 会报 TargetNamespace.2: Expecting no namespace, but the schema document has a target namespace of 'http://www.example.com/books'。

标准词法处理器应使用 SAX 标准属性 http://xml.org/sax/properties/lexical-handler(Xerces 扩展名下的 lexical-handler 实测不被识别);错误处理器与实体解析器则通过 setErrorHandler()、setEntityResolver() 方法注入,不走 property。

五、JAXP 系统属性

5.1 支持实现切换的系统属性

系统属性Xerces-J 提供的实现类(实测可用)
javax.xml.parsers.DocumentBuilderFactoryorg.apache.xerces.jaxp.DocumentBuilderFactoryImpl
javax.xml.parsers.SAXParserFactoryorg.apache.xerces.jaxp.SAXParserFactoryImpl
javax.xml.validation.SchemaFactory:http://www.w3.org/2001/XMLSchemaorg.apache.xerces.jaxp.validation.XMLSchemaFactory
org.xml.sax.driverorg.apache.xerces.parsers.SAXParser

注意:xercesImpl-2.12.2.jar 的 META-INF/services 实测包含 DatatypeFactory、DocumentBuilderFactory、SAXParserFactory、XMLEventFactory、SchemaFactory、DOMImplementationSourceList、org.xml.sax.driver 七个声明,不含 TransformerFactory(转换器需另配 Xalan)。

5.2 三种选择机制的实测对比

对同一个探测程序 JaxpSwitchDemo 三种运行方式(OpenJDK 17,双 OS 结果一致):

场景 1,classpath 不含 xercesImpl:

javax.xml.parsers.DocumentBuilderFactory = (未设置)
实际 DocumentBuilderFactory 实现: com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl

场景 2,classpath 含 xercesImpl(未设任何系统属性):

javax.xml.parsers.DocumentBuilderFactory = (未设置)
实际 DocumentBuilderFactory 实现: org.apache.xerces.jaxp.DocumentBuilderFactoryImpl

场景 3,显式系统属性:

java -Djavax.xml.parsers.DocumentBuilderFactory=org.apache.xerces.jaxp.DocumentBuilderFactoryImpl \
     -Djavax.xml.parsers.SAXParserFactory=org.apache.xerces.jaxp.SAXParserFactoryImpl \
     -cp target/classes com.example.xerces.JaxpSwitchDemo
javax.xml.parsers.DocumentBuilderFactory = org.apache.xerces.jaxp.DocumentBuilderFactoryImpl
实际 DocumentBuilderFactory 实现: org.apache.xerces.jaxp.DocumentBuilderFactoryImpl
javax.xml.parsers.SAXParserFactory = org.apache.xerces.jaxp.SAXParserFactoryImpl
实际 SAXParserFactory 实现: org.apache.xerces.jaxp.SAXParserFactoryImpl

结论:优先级为 系统属性 > classpath ServiceLoader 声明 > JDK 内置默认。把 xercesImpl 放进 classpath 这一动作本身就会切换全部 JAXP 工厂的默认实现,升级 JDK 或引入新依赖时要意识到这一点。

5.3 SchemaFactory 的带冒号语法

javax.xml.validation.SchemaFactory 的系统属性名以 schema 语言 URI 为后缀,冒号分隔:

java -Djavax.xml.validation.SchemaFactory:http://www.w3.org/2001/XMLSchema=org.apache.xerces.jaxp.validation.XMLSchemaFactory ...

实测在不设置该属性、仅把 xercesImpl 放进 classpath 时,SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI) 也已返回 org.apache.xerces.jaxp.validation.XMLSchemaFactory(ServiceLoader 生效)。

六、ErrorHandler 错误处理

6.1 三类错误的语义

回调触发条件实测示例
warning可恢复告警schema_reference.4 找不到 schema 文档
error违反 Schema 约束,可继续解析cvc-complex-type.4、cvc-datatype-valid.1.2.1
fatalError格式错误(not well-formed),解析被迫中断XML document structures must start and end within the same entity.

6.2 实测回显(XSD 校验违规文档)

Validator validator = schema.newValidator();
validator.setErrorHandler(new ErrorHandler() {
    public void warning(SAXParseException e) {
        System.out.println("[WARNING]  行 " + e.getLineNumber() + " 列 " + e.getColumnNumber() + ": " + e.getMessage());
    }
    public void error(SAXParseException e) {
        errors[0]++;
        System.out.println("[ERROR]    行 " + e.getLineNumber() + " 列 " + e.getColumnNumber() + ": " + e.getMessage());
    }
    public void fatalError(SAXParseException e) throws SAXParseException {
        errors[0]++;
        System.out.println("[FATAL]    行 " + e.getLineNumber() + " 列 " + e.getColumnNumber() + ": " + e.getMessage());
        throw e; // 中断解析
    }
});
validator.validate(new StreamSource(new File("src/main/resources/books-invalid.xml")));
[ERROR]    行 8 列 11: cvc-complex-type.4: Attribute 'id' must appear on element 'book'.
[ERROR]    行 11 列 36: cvc-datatype-valid.1.2.1: 'not-a-number' is not a valid value for 'decimal'.
[ERROR]    行 11 列 36: cvc-type.3.1.3: The value 'not-a-number' of element 'price' is not valid.
结果: 校验失败,共报告 3 处错误

格式不合法文档的实测回显(fataError 抛出后 validate 抛 SAXParseException):

[FATAL]    行 9 列 1: XML document structures must start and end within the same entity.
结果: 校验失败(致命错误已中断解析)

6.3 两个必须注意的实测行为

  1. error() 不抛异常时校验器会跑完整个文档并正常返回。 实测只在回调里打印、不计数不抛出时,validate() 正常结束,程序误报"校验通过"。正确做法是维护错误计数或直接抛出 SAXParseException。
  2. DOM 路径同理。 DocumentBuilder.parse() 遇到格式错误时先由默认 handler 打印一行 [Fatal Error] 文件名:9:1: ... 再抛出异常,实测回显:
[Fatal Error] books-badwf.xml:9:1: XML document structures must start and end within the same entity.
捕获 SAXParseException:
  systemId = file:/root/xerces-demo/src/main/resources/books-badwf.xml
  行=9 列=1
  message  = XML document structures must start and end within the same entity.

七、配置组合的推荐基线

结合实测,给出生产环境推荐配置(防御 XXE 并显式声明意图):

SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
factory.setFeature("http://xml.org/sax/features/validation", true);
factory.setFeature("http://apache.org/xml/features/validation/schema", true);

配套 JVM 参数(256–512 MB 堆)写入 /etc/profile.d/xerces-maven.sh:

export MAVEN_OPTS="-Xms256m -Xmx512m"

实测验证(后台运行解析进程后采样):

# jps -lv
7857 com.example.xerces.BigXmlDom -Xms256m -Xmx512m
# jstat -gcutil 7857 1000 3
  S0     S1     E      O      M     CCS    YGC     YGCT     FGC    FGCT     CGC    CGCT       GCT
  0.00 100.00  10.53  99.86  91.58  62.69     44     0.518     0     0.000    12     0.014     0.532
  0.00 100.00  21.05  99.89  91.05  61.42     70     0.779     1     0.012    18     0.020     0.811
  0.00   0.00  17.54  24.64  91.05  61.42    103     1.025     3     0.035    25     0.028     1.089

八、常见问题

Q1:setFeature 抛 SAXNotRecognizedException 一定是版本不支持吗? 不一定。实测两类"假性不识别":.../features/validation/honour-all-schemaLocations 正确 URI 没有 /validation/ 段(应为 http://apache.org/xml/features/honour-all-schemaLocations);warn-on-undeclared-element 应为 warn-on-undeclared-elemdef。先核对 URI 再怀疑版本。

Q2:JAXP 包装类与 Xerces 原生解析器类配置结果为何不同? 实测 org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser 默认 namespaces=false、namespace-prefixes=true,而原生 org.apache.xerces.parsers.SAXParser 默认 namespaces=true、namespace-prefixes=false。业务代码建议统一走 JAXP 工厂,避免两套默认值造成困惑。

Q3:设置了 external-noNamespaceSchemaLocation 却报 TargetNamespace.2? 该属性只适用于无命名空间文档。实测对带 xmlns="http://www.example.com/books" 的文档使用时报 Expecting no namespace, but the schema document has a target namespace of 'http://www.example.com/books',应改用 external-schemaLocation。

Q4:属性值里的相对路径为什么找不到文件? 外部 schema 属性值按实例文档的 base URI 解析。实测相对路径报 schema_reference.4,改为绝对路径后正常。

Q5:只开 http://xml.org/sax/features/validation 为什么对 XSD 无效? 该特性仅指 DTD 校验。实测只开它解析带 xsi:noNamespaceSchemaLocation 的文档报 Document is invalid: no grammar found.,必须再加 http://apache.org/xml/features/validation/schema(或用 SchemaFactory/Validator 路径)。

Q6:错误回调打印了 ERROR 却得到"校验通过"结论? error() 抛不抛异常决定 validate() 是否中断。实测只打印不抛出时校验器跑完全文并正常返回,需要在回调中计数并在校验后判断计数,或直接抛出异常。

九、参考链接