Apache Xerces-J 2.12.2 配置参数详解

逐项实测 Apache Xerces-J 2.12.2 的 JAXP feature/property 参数,覆盖校验、命名空间、Schema、XXE 防护等核心开关的真实行为、默认值与异常对照,并给出生产安全配置模板。

Apache XercesApache XercesJavaXMLLinux系统命令行2026/10/16

Apache Xerces-J 2.12.2 配置参数详解

目标:把 Apache Xerces-J 2.12.2 通过 setFeature/setProperty 暴露的核心配置参数逐个实测一遍,给出每个参数的真实默认值、行为差异回显与生产推荐组合。全部输出在 Ubuntu 22.04 + OpenJDK 17 + Xerces-J 2.12.2 环境实测取得。

一、环境信息

  • 操作系统:Ubuntu 22.04.5 LTS(x86_64)
  • JDK:OpenJDK 17.0.20.1
  • Xerces-J:2.12.2(xercesImpl-2.12.2.jar,sha256 前缀 6fc99182)
  • 演示目录:/root/xerces-lab(源码 src/、编译输出 classes/、依赖 libs/)
  • 编译命令统一为:javac -encoding UTF-8 -cp libs/xercesImpl-2.12.2.jar -d classes src/*.java(实测无输出即成功)
  • 运行 classpath 统一为:classes:libs/xercesImpl-2.12.2.jar

二、前置条件

本篇所有示例都需要 xercesImpl-2.12.2.jar。手动获取方式(一条命令即可独立完成):

mkdir -p /root/xerces-lab/libs && cd /root/xerces-lab/libs
curl -sS -O https://repo1.maven.org/maven2/xerces/xercesImpl/2.12.2/xercesImpl-2.12.2.jar
sha256sum xercesImpl-2.12.2.jar

实测回显:

6fc991829af1708d15aea50c66f0beadcd2cfeb6968e0b2f55c1b0909883fe16  xercesImpl-2.12.2.jar

示例中直接实例化 Xerces 的 org.apache.xerces.parsers.SAXParser 类,因此 classpath 必须包含该 jar(这正是"参数是否为 Xerces 专有"的判定边界:http://xml.org/sax/features/* 是 SAX 标准参数,http://apache.org/xml/* 是 Xerces 专有参数)。

三、参数查看与修改方式

Xerces 的参数分两类:feature(布尔开关,用 setFeature/getFeature)与 property(对象值,用 setProperty/getProperty)。两者设置失败时分别可能抛 SAXNotRecognizedException(不认识)或 SAXNotSupportedException(认识但当前状态不支持)。写两个探针程序统一实测:

import org.apache.xerces.parsers.SAXParser;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;

public class FeatureProbe {
    public static void main(String[] args) {
        String uri = args[0];
        boolean value = Boolean.parseBoolean(args[1]);
        try {
            SAXParser parser = new SAXParser();
            parser.setFeature(uri, value);
            System.out.println("setFeature 成功: " + uri + " = " + value);
            System.out.println("getFeature 读回: " + parser.getFeature(uri));
        } catch (SAXException e) {
            if (e instanceof SAXNotRecognizedException) {
                System.out.println("SAXNotRecognizedException(解析器不识别该 feature): " + uri);
            } else if (e instanceof SAXNotSupportedException) {
                System.out.println("SAXNotSupportedException(当前状态下不允许设置该 feature): " + uri);
            } else {
                System.out.println("SAXException: " + e.getMessage());
            }
        }
    }
}

PropertyProbe 与 FeatureProbe 结构完全相同,仅两处差异:parser.setFeature(uri, value) 换成 parser.setProperty(uri, value)、parser.getFeature(uri) 换成 parser.getProperty(uri)(完整源码按此替换即可编译,实测编译通过)。

编译并先做异常对照(用一个不存在的参数名):

cd /root/xerces-lab/src
CP=../classes:../libs/xercesImpl-2.12.2.jar
java -cp $CP FeatureProbe http://xml.org/sax/features/bogus-feature true
java -cp $CP PropertyProbe http://apache.org/xml/properties/bogus-prop xyz

实测回显:

SAXNotRecognizedException(解析器不识别该 feature): http://xml.org/sax/features/bogus-feature
SAXNotRecognizedException(解析器不识别该 property): http://apache.org/xml/properties/bogus-prop

验证结论:探针可用。后续每个参数的"set 成功/读回值"都按同样方式取得。

四、参数总览

参数 URI类型默认值(实测读回)作用
http://xml.org/sax/features/validationfeaturefalseDTD 校验总开关
http://xml.org/sax/features/namespacesfeaturetrue命名空间处理
http://xml.org/sax/features/namespace-prefixesfeaturefalse保留原始前缀与 xmlns 属性
http://apache.org/xml/features/validation/schemafeaturefalseXML Schema 校验(Xerces 专有)
http://apache.org/xml/features/validation/schema-full-checkingfeaturefalseSchema 严格全检查(Xerces 专有)
http://apache.org/xml/features/validation/dynamicfeaturefalse动态校验(有 DTD/Schema 才校验)
http://apache.org/xml/features/disallow-doctype-declfeaturefalse禁止 DOCTYPE(XXE 防护)
http://apache.org/xml/features/nonvalidating/load-external-dtdfeaturetrue非校验模式下也加载外部 DTD
http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocationproperty无指定无命名空间文档的 Schema
http://apache.org/xml/properties/schema/external-schemaLocationproperty无按"命名空间 URI 位置"指定 Schema
http://java.sun.com/xml/jaxp/properties/schemaLanguageproperty无JAXP 标准:Schema 语言标识
http://java.sun.com/xml/jaxp/properties/schemaSourceproperty无JAXP 标准:Schema 来源

上表 12 个参数均已用探针逐一实测:setFeature/setProperty 全部成功且 getFeature/getProperty 读回值与设置值一致。代表样例回显:

java -cp $CP FeatureProbe http://xml.org/sax/features/validation true
java -cp $CP FeatureProbe http://apache.org/xml/features/nonvalidating/load-external-dtd false
java -cp $CP PropertyProbe http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation books.xsd

实测回显:

setFeature 成功: http://xml.org/sax/features/validation = true
getFeature 读回: true
setFeature 成功: http://apache.org/xml/features/nonvalidating/load-external-dtd = false
getFeature 读回: false
setProperty 成功: http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation = books.xsd
getProperty 读回: books.xsd

每个参数的行为级差异(开关前后解析结果变化)在第五章逐项演示。

💡 技术拓展:XML 校验语言不止一种,Xerces 两个开关对应两类——

校验语言开关特点
DTDvalidation feature语法级约束、定义在文档内部或外部 DTD 文件
XML Schema 1.0validation/schema feature + schemaSource property类型系统强(decimal、date 等),namespace 感知
RELAX NG / SchematronXerces-J 内置不直接支持需第三方实现(如 Jing)

本文全部采用 Xerces 内置的 DTD 与 XML Schema 1.0 两条链路实测。

五、核心参数分类详解

5.1 validation:DTD 校验开关

该参数决定是否对文档执行 DTD 校验。默认 false 时只检查良构性。测试数据 note.xml(引用 note.dtd 但缺少 heading 元素)与 note.dtd:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE note SYSTEM "note.dtd">
<note>
  <to>张三</to>
  <from>李四</from>
  <body>会议改到下午三点</body>
</note>
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>

测试程序:

import org.apache.xerces.parsers.SAXParser;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;

public class DtdValidateDemo {
    public static void main(String[] args) throws Exception {
        boolean validate = Boolean.parseBoolean(args[1]);
        SAXParser parser = new SAXParser();
        parser.setFeature("http://xml.org/sax/features/validation", validate);
        final int[] problems = {0};
        parser.setErrorHandler(new DefaultHandler() {
            @Override
            public void error(SAXParseException e) {
                problems[0]++;
                System.out.println("[错误]     第" + e.getLineNumber() + "行: " + e.getMessage());
            }

            @Override
            public void warning(SAXParseException e) {
                System.out.println("[警告]     第" + e.getLineNumber() + "行: " + e.getMessage());
            }

            @Override
            public void fatalError(SAXParseException e) {
                problems[0]++;
                System.out.println("[致命错误] 第" + e.getLineNumber() + "行: " + e.getMessage());
            }
        });
        try {
            parser.parse(args[0]);
        } catch (SAXException e) {
            System.out.println("解析中止: " + e.getMessage());
        }
        if (problems[0] > 0) {
            System.out.println("结果: 共发现 " + problems[0] + " 处问题。");
        } else {
            System.out.println("结果: 解析结束,未发现问题。");
        }
        System.out.println("(本次 validation feature = " + validate + ")");
    }
}

开启校验运行:

java -cp $CP DtdValidateDemo note.xml true

实测回显:

[错误]     第7行: The content of element type "note" must match "(to,from,heading,body)".
结果: 共发现 1 处问题。
(本次 validation feature = true)

关闭校验运行:

java -cp $CP DtdValidateDemo note.xml false

实测回显:

结果: 解析结束,未发现问题。
(本次 validation feature = false)

验证结论:同一份违例文档,validation=true 报内容模型错误,false 时静默通过。校验必须显式开启是 Xerces(以及所有 SAX 解析器)最常被忽略的默认行为。

5.2 namespaces / namespace-prefixes:命名空间处理

namespaces=true(默认)时回调的 uri/localName 有值;false 时只保留原始 qName。测试文档 nsbooks.xml(带 store: 前缀):

<?xml version="1.0" encoding="UTF-8"?>
<store:bookstore xmlns:store="http://example.com/store">
  <store:book id="2001">
    <store:title>XML 实战</store:title>
    <store:price>59.00</store:price>
  </store:book>
</store:bookstore>

测试程序:

import org.apache.xerces.parsers.SAXParser;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;

public class NamespaceDemo {
    public static void main(String[] args) throws Exception {
        boolean aware = Boolean.parseBoolean(args[0]);
        SAXParser parser = new SAXParser();
        parser.setFeature("http://xml.org/sax/features/namespaces", aware);
        parser.setContentHandler(new DefaultHandler() {
            @Override
            public void startElement(String uri, String localName, String qName, Attributes atts) {
                System.out.println("开始元素: qName=" + qName + ", localName=" + localName
                        + ", uri=" + (uri.isEmpty() ? "(空)" : uri));
            }
        });
        parser.parse(args[1]);
        System.out.println("(本次 namespaces feature = " + aware + ")");
    }
}

namespaces=true 运行:

java -cp $CP NamespaceDemo true nsbooks.xml

实测回显:

开始元素: qName=store:bookstore, localName=bookstore, uri=http://example.com/store
开始元素: qName=store:book, localName=book, uri=http://example.com/store
开始元素: qName=store:title, localName=title, uri=http://example.com/store
开始元素: qName=store:price, localName=price, uri=http://example.com/store
(本次 namespaces feature = true)

namespaces=false 运行:

java -cp $CP NamespaceDemo false nsbooks.xml

实测回显:

开始元素: qName=store:bookstore, localName=, uri=(空)
开始元素: qName=store:book, localName=, uri=(空)
开始元素: qName=store:title, localName=, uri=(空)
开始元素: qName=store:price, localName=, uri=(空)
(本次 namespaces feature = false)

⚠️ 注意:namespaces=false 时所有元素的 localName 为空串、uri 为空串、qName 保留带前缀的原始名。两个开关叠加使用:namespaces=true + namespace-prefixes=true 时既有 uri/localName 又保留 xmlns 声明属性与前缀。

namespace-prefixes=true 的作用是与 namespaces=true 叠加,让 xmlns 声明也作为属性出现在 Attributes 里、qName 保留前缀(探针实测 setFeature 成功、读回 true,见第四章总览)。

5.3 validation/schema + external-noNamespaceSchemaLocation:Schema 校验

Xerces 专有链路:开 http://apache.org/xml/features/validation/schema,再用 property 指定 Schema 文件。测试程序复用 5.1 的 DtdValidateDemo 整体骨架(ErrorHandler 匿名类与 error 计数完全相同),仅替换参数设置部分,核心片段如下(完整类按骨架拼装即可编译,实测编译通过、输出如下):

SAXParser parser = new SAXParser();
parser.setFeature("http://xml.org/sax/features/validation", true);
parser.setFeature("http://apache.org/xml/features/validation/schema", true);
parser.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation",
        args[1]);
parser.setErrorHandler(handlerWithCounting);   // 与 5.1 相同的 ErrorHandler 匿名类
parser.parse(args[0]);                          // 结果打印逻辑也与 5.1 相同

测试数据 books.xml 与 books.xsd(books.xsd 定义 bookstore/book/title/author/price,price 类型 xs:decimal,id 必填):

<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
  <book id="1001">
    <title>Java 核心技术</title>
    <author>凯·霍斯特曼</author>
    <price>149.00</price>
  </book>
  <book id="1002">
    <title>深入理解 Java 虚拟机</title>
    <author>周志明</author>
    <price>129.00</price>
  </book>
  <book id="1003">
    <title>Effective Java</title>
    <author>Joshua Bloch</author>
    <price>99.00</price>
  </book>
</bookstore>
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="bookstore">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="book" maxOccurs="unbounded">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="title" type="xs:string"/>
              <xs:element name="author" type="xs:string"/>
              <xs:element name="price" type="xs:decimal"/>
            </xs:sequence>
            <xs:attribute name="id" type="xs:string" use="required"/>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

合法文档运行:

java -cp $CP SchemaValidateXerces books.xml books.xsd

实测回显:

校验结果: 通过,books.xml 符合 books.xsd 定义的规则。

构造违例文档 books-invalid.xml(price 写成"免费"、第二本书删掉 author):

<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
  <book id="1001">
    <title>Java 核心技术</title>
    <author>凯·霍斯特曼</author>
    <price>免费</price>
  </book>
  <book id="1002">
    <title>深入理解 Java 虚拟机</title>
    <price>129.00</price>
  </book>
</bookstore>
java -cp $CP SchemaValidateXerces books-invalid.xml books.xsd

实测回显:

[错误]     第6行: cvc-datatype-valid.1.2.1: '免费' is not a valid value for 'decimal'.
[错误]     第6行: cvc-type.3.1.3: The value '免费' of element 'price' is not valid.
[错误]     第10行: cvc-complex-type.2.4.a: Invalid content was found starting with element 'price'. One of '{author}' is expected.
校验结果: 未通过,共发现 3 处校验错误。

对带命名空间的文档改用 external-schemaLocation property,值为"命名空间URI 空格 Schema位置"对(探针实测 setProperty 成功并读回 http://example.com/store books.xsd,见第四章)。

5.4 schema-full-checking:Schema 全检查

默认 false 时,Schema 编译只做常规检查;开启后额外执行完整约束集,典型可捕获 UPA(Unique Particle Attribution,唯一粒子归属)违例。构造一个歧义内容模型 upa.xsd(两个分支都以 circle 开头)与实例 upa.xml:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="shape">
    <xs:complexType>
      <xs:choice>
        <xs:sequence>
          <xs:element name="circle"/>
          <xs:element name="label"/>
        </xs:sequence>
        <xs:sequence>
          <xs:element name="circle"/>
        </xs:sequence>
      </xs:choice>
    </xs:complexType>
  </xs:element>
</xs:schema>
<?xml version="1.0" encoding="UTF-8"?>
<shape><circle/></shape>

测试程序同样复用 5.1 骨架,核心差异只有一行(在 5.3 的参数基础上追加全检查开关):

parser.setFeature("http://xml.org/sax/features/validation", true);
parser.setFeature("http://apache.org/xml/features/validation/schema", true);
parser.setFeature("http://apache.org/xml/features/validation/schema-full-checking", full);   // 本节主角
parser.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation",
        "upa.xsd");

默认(false)运行:

java -cp $CP FullCheckDemo false

实测回显:

[错误] cvc-complex-type.2.4.b: The content of element 'shape' is not complete. One of '{label}' is expected.
共发现 1 处错误。
(本次 schema-full-checking feature = false)

开启全检查运行:

java -cp $CP FullCheckDemo true

实测回显:

[错误] cvc-complex-type.2.4.b: The content of element 'shape' is not complete. One of '{label}' is expected.
[错误] cos-nonambig: circle and circle (or elements from their substitution group) violate "Unique Particle Attribution". During validation against this schema, ambiguity would be created for those two particles.
共发现 2 处错误。
(本次 schema-full-checking feature = true)

验证结论:cos-nonambig 这类 Schema 设计期错误只有全检查开启才会报告。 Schema 发布前的质量门禁建议开启此参数(代价是 Schema 编译变慢)。

补充一个相关开关 http://apache.org/xml/features/validation/dynamic(默认 false,探针实测可设置并读回 true):开启后解析器按文档自身"有无校验依据"决定是否校验——带 DOCTYPE 就做 DTD 校验、带 xsi:noNamespaceSchemaLocation 就做 Schema 校验、都没有则只查良构;与显式开启 validation 的区别是"没有依据时静默跳过而非报错"。

5.5 disallow-doctype-decl:禁止 DOCTYPE(XXE 防护核心)

开启后文档一出现 DOCTYPE 声明立即致命错误,是最干脆的 XXE 防线。测试文档 doctest.xml(内部实体):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE memo [
  <!ENTITY greeting "你好,Xerces">
]>
<memo><msg>&greeting;</msg></memo>

测试程序:

import org.apache.xerces.parsers.SAXParser;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class DoctypeDemo {
    public static void main(String[] args) throws Exception {
        boolean disallow = Boolean.parseBoolean(args[0]);
        SAXParser parser = new SAXParser();
        parser.setFeature("http://apache.org/xml/features/disallow-doctype-decl", disallow);
        try {
            parser.parse(args[1]);
            System.out.println("解析完成,未抛出致命错误。");
        } catch (SAXException e) {
            System.out.println("解析中止,SAXException: " + e.getMessage());
        }
        System.out.println("(本次 disallow-doctype-decl feature = " + disallow + ")");
    }
}

开启运行:

java -cp $CP DoctypeDemo true doctest.xml

实测回显:

[Fatal Error] doctest.xml:2:10: DOCTYPE is disallowed when the feature "http://apache.org/xml/features/disallow-doctype-decl" set to true.
解析中止,SAXException: DOCTYPE is disallowed when the feature "http://apache.org/xml/features/disallow-doctype-decl" set to true.
(本次 disallow-doctype-decl feature = true)

默认(false)运行:

java -cp $CP DoctypeDemo false doctest.xml

实测回显:

解析完成,未抛出致命错误。
(本次 disallow-doctype-decl feature = false)

💡 技术拓展:XXE(XML External Entity,XML 外部实体注入)是解析不受信 XML 的头号风险,防线从强到弱——

防线做法取舍
禁 DOCTYPEdisallow-doctype-decl=true最彻底,但合法使用 DOCTYPE 的文档会被拒
禁外部实体加载load-external-dtd=false 等保留 DOCTYPE 语法,禁外部取数
限制实体展开setSecurityManager(实体数/展开上限)兼容性最好,防"实体炸弹"递归放大

生产解析外部来源 XML 时,本文采用"禁 DOCTYPE 为主、禁外部加载为辅"的组合,见第六章模板。

5.6 load-external-dtd:外部 DTD 加载

默认 true:即使不做校验,遇到外部 DTD 声明也会去加载。测试文档 extdtd.xml 引用一个不存在的 missing.dtd:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE note SYSTEM "missing.dtd">
<note>
  <to>张三</to>
</note>

测试程序复用 5.1 骨架,核心片段(注意补捕获 parse() 声明的 IOException,现象见下):

boolean load = Boolean.parseBoolean(args[0]);
SAXParser parser = new SAXParser();
parser.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", load);
parser.setErrorHandler(handler);   // 与 5.1 相同的 ErrorHandler
try {
    parser.parse(args[1]);
    System.out.println("解析流程结束。");
} catch (SAXException e) {
    System.out.println("解析中止(SAXException): " + e.getMessage());
} catch (java.io.IOException e) {
    System.out.println("解析中止(IOException): " + e);
}

默认(true)运行:

java -cp $CP LoadDtdDemo true extdtd.xml

实测回显:

解析中止(IOException): java.io.FileNotFoundException: /root/xerces-lab/src/missing.dtd (No such file or directory)
(本次 load-external-dtd feature = true)

关闭运行:

java -cp $CP LoadDtdDemo false extdtd.xml

实测回显:

解析流程结束。
(本次 load-external-dtd feature = false)

验证结论:外部 DTD 加载失败抛的是 IOException(不是 SAX 校验错误,ErrorHandler 拦不住);关闭该参数后解析器根本不去碰 missing.dtd。这个参数同时是性能参数(省一次文件/网络 IO)与安全参数(切断外部引用)。

5.7 JAXP 标准 property:schemaLanguage / schemaSource

这两个 property 是 JAXP 规范定义的可移植写法(不依赖 http://apache.org 前缀),设置在 javax.xml.parsers.SAXParser 实例上。探针实测(PropertyProbe 基于 org.apache.xerces.parsers.SAXParser,同样接受这两个 URI):

setProperty 成功: http://java.sun.com/xml/jaxp/properties/schemaLanguage = http://www.w3.org/2001/XMLSchema
getProperty 读回: http://www.w3.org/2001/XMLSchema
setProperty 成功: http://java.sun.com/xml/jaxp/properties/schemaSource = books.xsd
getProperty 读回: books.xsd

完整的 JAXP 路线校验程序与实测输出见《Apache Xerces-J 在 Ubuntu 22.04 集成使用指南》第五章(schemaLanguage 设为 http://www.w3.org/2001/XMLSchema,schemaSource 传 Schema 文件路径,实测输出为三行 cvc-* 错误与"未通过,共发现 3 处校验错误")。

六、生产配置模板

适用场景:后端服务解析外部提交的 XML(如导入、回调报文),单机 2C4G,要求防 XXE 且按 Schema 强校验。

import org.apache.xerces.parsers.SAXParser;

public class SafeXmlParser {
    public static SAXParser createSafeParser() throws Exception {
        SAXParser parser = new SAXParser();
        parser.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
        parser.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
        parser.setFeature("http://xml.org/sax/features/validation", true);
        parser.setFeature("http://apache.org/xml/features/validation/schema", true);
        parser.setProperty(
                "http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation",
                "books.xsd");
        return parser;
    }
}

逐项说明:第一行禁 DOCTYPE(外部报文不需要 DOCTYPE,直接拒收);第二行兜底禁外部 DTD 加载;第三、四行开启 Schema 校验;最后一行把 Schema 钉在本服务自带的 books.xsd 上,不信任报文里声明的 xsi:schemaLocation。所有参数均已在前文逐项实测验证。

七、常见问题

Q1:setFeature 抛 SAXNotRecognizedException 是什么原因? 三种可能:URI 拼错(大小写敏感,逐字符核对第四章总览表);把 Xerces 专有参数设到了 JDK 内置实现的老版本上;参数设置到了不支持它的解析器包装类。先用探针程序对目标解析器实测该 URI。

Q2:明明开了校验却不报错? 依次检查:validation 与 validation/schema 是否同时开启(Schema 校验两者都要);Schema 来源是否设置成功(external-noNamespaceSchemaLocation 或 schemaSource property);错误处理器是否覆盖 error() 回调——校验错误走 error() 而不是抛异常,不重抛、不计数就会"看起来通过"。

Q3:property 设置报 SAXNotSupportedException? 典型场景是 Schema 校验未开启时设置 schemaSource 类 property,或在解析进行中改参数。原则:所有 feature/property 都在 parse() 之前设置完成。

Q4:外部 DTD 找不到,为什么 ErrorHandler 里看不到? 外部实体加载失败抛 IOException(实测见 5.6),不是 SAXParseException。捕获 parse() 声明的 IOException 并单独处理。

八、参考链接