XBRL文件XSD校验误报结构错误的解决需求
我现在碰到了一个XBRL校验的棘手问题,想请教大家怎么调整XSD校验逻辑,避开那些看似误报的结构错误——这些错误其实不会影响XBRL的正常功能,而且文件已经通过了Schematron校验(我们用Schematron来检查业务规则,这部分完全没问题)。我的核心目标是只用XSD来校验XBRL文档里的非ASCII字符、字段过长这类Schematron覆盖不到的问题。
问题场景与错误详情
我有一个确认有效的XBRL文件xbrl_001_valid.xml:
- 它顺利通过了Schematron校验
- 用Arelle工具验证也显示是合法的XBRL文档
但用我自己写的基于Xerces的Java校验程序XbrlValidationWithXsdUsesXercesApplication.java运行时,却抛出了结构错误:
2025-06-09T22:48:53.658+03:00 ERROR 374 --- [XBRL-validation-with-xsd_uses-xerces] [ main] rlValidationWithXsdUsesXercesApplication : Error: org.xml.sax.SAXParseException; systemId: file:/Users/rob.bram/work/test/XBRL-validation-with-xsd_uses-xerces/src/main/resources/xbrl/xbrl_001_valid.xml; lineNumber: 46; columnNumber: 51; cvc-complex-type.2.4.a: Invalid content was found starting with element '{"http://sbr.gov.au/comnmdle/comnmdle.financialinstitutionaccount1.02.00.module":FinancialInstitutionAccount}'. One of '{"http://www.xbrl.org/2003/linkbase":schemaRef, "http://www.xbrl.org/2003/linkbase":linkbaseRef, "http://www.xbrl.org/2003/linkbase":roleRef, "http://www.xbrl.org/2003/linkbase":arcroleRef, "http://www.xbrl.org/2003/instance":item, "http://www.xbrl.org/2003/instance":tuple, "http://www.xbrl.org/2003/instance":context, "http://www.xbrl.org/2003/instance":unit, "http://www.xbrl.org/2003/linkbase":footnoteLink}' is expected.
我的校验程序细节
我的Java代码基于Spring Boot实现,核心逻辑是用Xerces加载本地缓存的XSD文件(包括sbr.gov.au的分类标准XSD和xbrl.org的基础XSD),通过XMLCatalogResolver目录解析器引用本地文件,避免网络请求。关键代码片段如下:
@SpringBootApplication public class XbrlValidationWithXsdUsesXercesApplication implements CommandLineRunner { private static Logger log = LoggerFactory.getLogger(XbrlValidationWithXsdUsesXercesApplication.class); public static void main(String[] args) { SpringApplication.run(XbrlValidationWithXsdUsesXercesApplication.class, args); } @Override public void run(final String... args) throws Exception { validateFile(Path.of("src/main/resources/xbrl/xbrl_001_valid.xml")); validateFile(Path.of("src/main/resources/xbrl/xbrl_002_invalid-against-Schematron.xml")); validateFile(Path.of("src/main/resources/xbrl/xbrl_003_invalid-against-XSD.xml")); } private static void validateFile(final Path xbrlPath) throws SAXException, IOException { log.info("========== {} ==========", xbrlPath); final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); final String[] catalogs = {"src/main/resources/xsd/catalog.xml"}; final XMLCatalogResolver resolver = new XMLCatalogResolver(catalogs) { @Override public LSInput resolveResource( final String type, final String namespaceURI, final String publicId, final String systemId, final String baseURI ) { final LSInput lsInput = super.resolveResource(type, namespaceURI, publicId, systemId, baseURI); final String resolvedSystemId = (lsInput != null) ? lsInput.getSystemId() : "null"; log.debug("Attempted to resolve '{}' to '{}'.", systemId, resolvedSystemId); return lsInput; } }; schemaFactory.setResourceResolver(resolver); final String entryPointXsd = "src/main/resources/xsd/sbr.gov.au/taxonomy/sbr_au_reports/sprstrm/sprcnt/sprcnt_0001/sprcnt.0001.conttrans.request.02.02.report.xsd"; final Schema schema = schemaFactory.newSchema(new File(entryPointXsd)); javax.xml.validation.Validator validator = schema.newValidator(); final XsdErrorHandler errorHandler = new XsdErrorHandler(xbrlPath); validator.setErrorHandler(errorHandler); final Source xmlStreamSource = new StreamSource(xbrlPath.toFile()); validator.validate(xmlStreamSource); if (errorHandler.getErrors().isEmpty()) { log.info("'{}' is valid against '{}'.", xbrlPath, entryPointXsd); } for (SAXParseException error : errorHandler.getErrors()) { log.error("Error: {}", error.toString()); } } public static final class XsdErrorHandler implements ErrorHandler { // 代码省略 } }
环境说明
- 所有XBRL实例文件中
link:schemaRef引用的XSD文件都已本地缓存,包括实例中声明的:<link:schemaRef xlink:href="http://sbr.gov.au/taxonomy/sbr_au_reports/sprstrm/sprcnt/sprcnt_0001/sprcnt.0001.conttrans.request.02.02.report.xsd" xlink:type="simple"/> - 本地缓存了所有依赖的sbr.gov.au和www.xbrl.org的XSD文件,校验时不会发起网络请求。
现在我想搞清楚:为什么这个明明有效的XBRL文件会被XSD校验报结构错误?怎么调整我的校验逻辑,让XSD只检查我需要的内容(非ASCII字符、字段过长等),同时忽略这种不影响功能的结构误报?
内容来源于stack exchange

