You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Apache Commons Configuration2实现自定义XSD验证XML配置

问题

我希望通过Apache Commons Configuration2加载XML配置,同时执行XSD验证。要求用于验证的XSD由应用提供,而非不可信配置文件中链接的XSD。

我在官方文档和StackOverflow中均未找到匹配示例。有一个类似问题的回答仅适用于Apache Commons Configuration1,无法满足我的需求。

补充说明:
Apache Commons Configuration文档中的XSD验证示例如下:

Parameters params = new Parameters();
FileBasedConfigurationBuilder<XMLConfiguration> builder =
    new FileBasedConfigurationBuilder<XMLConfiguration>(XMLConfiguration.class)
    .configure(params.xml()
        .setFileName("myconfig.xml")
        .setSchemaValidation(true));

// This will throw a ConfigurationException if the XML document does not
// conform to its Schema.
XMLConfiguration config = builder.getConfiguration();

该示例是读取XML配置文件并根据其内部引用的XSD进行验证,但我需要在代码中指定应用提供的XSD来验证。以下是我的尝试:

File f = new File(xmlfile);
log.info("Reading {}", f.getAbsoluteFile());

URL url = getClass().getResource("/schema/configuration.xsd");
log.trace("loading XSD from {}", url);

SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Source schemaFile = new StreamSource(url.openStream());
Schema schema = factory.newSchema(schemaFile);

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setSchema(schema);
dbf.setNamespaceAware(true);
dbf.setValidating(false);    // ignore XSD references within the document
DocumentBuilder db = dbf.newDocumentBuilder();
MyErrorHandler meh = new MyErrorHandler();
db.setErrorHandler(meh);
db.parse(f);                     // <<<=============== note this line

Parameters params = new Parameters();
params.xml()
        .setSchemaValidation(true)
        .setDocumentBuilder(db);

FileBasedConfigurationBuilder<XMLConfiguration> builder = new FileBasedConfigurationBuilder<>(XMLConfiguration.class)
        .configure(params.xml().setFile(f));
config = builder.getConfiguration();

注意db.parse(f);这一行:

  • 保留该行时,文档会被验证,MyErrorHandler会收到警告、错误和致命错误。
  • 移除该行时,无论文档是否有效都会被加载。

这意味着尽管我已正确配置了DocumentBuilder,但将其传入配置构建器params.setDocumentBuilder()并未生效。

解决方案

问题出在重复调用params.xml():第一次调用时你配置了setDocumentBuilder(db),但第二次调用params.xml().setFile(f)时,会生成一个全新的XMLBuilderParameters实例,之前的配置完全丢失。

正确的做法是创建单个XMLBuilderParameters实例,链式配置所有属性后再传入构建器:

File f = new File(xmlfile);
log.info("Reading {}", f.getAbsoluteFile());

URL url = getClass().getResource("/schema/configuration.xsd");
log.trace("loading XSD from {}", url);

SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Source schemaFile = new StreamSource(url.openStream());
Schema schema = factory.newSchema(schemaFile);

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setSchema(schema);
dbf.setNamespaceAware(true);
dbf.setValidating(false); // 忽略配置文件内部的XSD引用
DocumentBuilder db = dbf.newDocumentBuilder();
MyErrorHandler meh = new MyErrorHandler();
db.setErrorHandler(meh);

// 关键:创建一个XMLBuilderParameters实例并链式配置所有参数
XMLBuilderParameters xmlParams = params.xml()
        .setFile(f)
        .setDocumentBuilder(db); // 传入绑定了XSD的自定义DocumentBuilder

FileBasedConfigurationBuilder<XMLConfiguration> builder = 
    new FileBasedConfigurationBuilder<>(XMLConfiguration.class)
        .configure(xmlParams);

// 加载配置时会自动用指定XSD验证,无需手动调用db.parse(f)
config = builder.getConfiguration();

核心要点

  • 避免重复调用params.xml(),每次调用都会生成新的参数对象,导致之前的配置失效。
  • 自定义的DocumentBuilder已绑定你的XSD和错误处理器,构建器加载配置时会使用该实例解析XML,自动触发验证流程。
  • 移除手动的db.parse(f)调用,让配置构建器完成整个解析+验证+加载流程,避免重复解析。

修改后,当XML不符合指定XSD时,会通过MyErrorHandler抛出错误,阻止无效配置被加载。

内容的提问来源于stack exchange,提问作者queeg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 23:32:34