如何确定坏模式?

How to determine the bad schema?

我正在编写一个小应用程序来验证“候选”xml 文件是否与存储在文件夹中的已知良好模式文件的“银行”...

事实证明,已知的良好模式文件本身会引发问题!

我将模式文件(21 个文件,我很确定这些模式中的大多数不仅引用它们自己,而且其中一些使用文件夹中的其他模式)加载到我的“模式”中的方式 space":

// Load schemas into schema space:
        Schema mySchema;
        try {
            SchemaFactory mySchemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
            mySchemaFactory.setResourceResolver(new ResourceResolver(pathToSchemasFolder));
            mySchema = mySchemaFactory.newSchema(primeAllSchemaDocsFromFolder(pathToSchemasFolder));
            System.out.println("Schemas loaded");
        } catch (SAXException e) {
            throw new RuntimeException("Schema loading failed: " + e);
        }

我得到: Exception in thread "main" java.lang.RuntimeException: Schema loading failed: org.xml.sax.SAXParseException; lineNumber: 232; columnNumber: 5; s4s-elt-chara...

我在验证时已经在使用自定义 XsdErrorHandler()

// Validate xml file within schema space:
        try {
            Validator validator = mySchema.newValidator();
            validator.setErrorHandler(new XsdErrorHandler());
            validator.validate(getSingleXmlFileStreamSource(pathToXmlCandidateFile));
            System.out.println("Validation is successful");

但是,在调试时,我发现它没有被调用...这是有道理的,因为失败的部分是加载模式,在我将 ErrorHandler 设置为 Validator 之前完成的一些事情...

我想知道是否有办法为架构加载过程设置错误处理程序?

或者您可以与我分享任何其他技术来查找有问题的架构名称? (例如:将模式文件逐步添加到模式 space 中,每次测试模式 space 是否有效 - 没有任何无效的模式定义)

有一种方法 SchemaFactory.setErrorHandler() 可以让您在架构编译期间拦截错误。

当您生成 StreamSource 时,您应该提供 publicId 属性。这个属性不影响解析,但在异常中提供了有用的信息:

     * <p>The public identifier is always optional: if the application
     * writer includes one, it will be provided as part of the
     * location information.</p>

如果您将模式文件名用作 publicId,您将能够从 SAXParseException.

中检索它

从原始提问者编辑: 由于我在 newSchema() 中使用 Source[],我可以为每个 Source 准备输入以包括提到的方法,如下所示:

 Source[] sourceArray = new Source[numberOfSchemaFiles];
    for (int i=0; i<numberOfSchemaFiles ; i++) {
        String currentFileName = schemaFiles[i].getName();
        try {
            StreamSource currentStreamSource = new StreamSource(
                    new FileInputStream(directoryPath + currentFileName)
            );
            currentStreamSource.setPublicId(currentFileName);
            sourceArray[i] = currentStreamSource;
        } catch (FileNotFoundException e) {
            throw new RuntimeException("Cannot find file: " + directoryPath + currentFileName);
        }