实现LSResourceResolver以递归方式读取XSD集

use*_*601 5 java xml xsd

我需要从jar加载XSD文件,所以实现了LSResourceResolver,如下所示:

        Source schemaFile = new StreamSource(getClass().getClassLoader().getResourceAsStream("resources/xsd/root/maindoc/MainSchema.xsd"));
        SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        schemaFactory.setResourceResolver(new LSResourceResolver(){
            @Override
            public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) {
                    LSInput input = new DOMInputImpl();
                String filePath = getNormalizedPath("resources/xsd/root/maindoc/", systemId);
                InputStream stream = getClass().getClassLoader().getResourceAsStream(filePath);
                input.setPublicId(publicId);
                input.setSystemId(systemId);
                input.setBaseURI(baseURI);
                input.setCharacterStream(new InputStreamReader(stream));             
                return input;
            }

        });         
        Schema schema = schemaFactory.newSchema(schemaFile); 
Run Code Online (Sandbox Code Playgroud)

此类实现成功解析了主模式中的链接,但无法解析引用文档中的链接.

通过引用文档的调用,我收到的不是null的baseURI参数,但是在我的情况下它的值就像是"file:///var/xxx/yyy.xsd",所以看起来不可能从这个构造一个有效的路径的systenId.

我错过了什么吗?是否可以递归地使解析器工作?

当然有一种解决方法可以展平架构,但我不太喜欢它.

and*_*and 7

考虑使用方法newSchema(URL schema).

我刚刚遇到了类似的问题,实施起来LSResourceResolver似乎太麻烦了.看看这个答案吧.我不知道它是否处理递归包含,但对于这样一个简单的任务来说它肯定看起来太复杂了.

我发现了这篇文章.这是很老,但总体思路是仍然有效:它往往是更好地使用URLInputStream为架构的阅读.

使用URL界面的优点:

  • 文件和资源的简单构造,无需自定义 LSResourceResolver
  • 缓冲由实现处理.

您不能(优雅地)使用此接口从实际流(标准输入或网络连接)读取模式.显然应该使用流接口来完成.但我想大多数应用程序实际上是从主机文件系统或应用程序资源中读取模式.

例:

java.net.URL url = getClass().getResource("resources/main.xsd");
SchemaFactory schemaFactory = SchemaFactory.newInstance(
    XMLConstants.W3C_XML_SCHEMA_NS_URI);
schemaFactory.setErrorHandler(new CustomErrorHandler());
try {
    schema = schemaFactory.newSchema(url);
} catch (SAXException e) {
    //...
}
Run Code Online (Sandbox Code Playgroud)

请注意自定义错误处理程序 出于某种原因,Xerces仅针对缺少的包含文件发出警告.为了使它抛出异常,实现这样的处理程序:

class CustomErrorHandler implements ErrorHandler {

    public void fatalError(SAXParseException e) throws SAXException {
        throw e;
    }

    public void error(SAXParseException e) throws SAXException {
        throw e;
    }

    public void warning(SAXParseException e) throws SAXException {
        throw e;
    }

}
Run Code Online (Sandbox Code Playgroud)