Java JAXB SchemaFactory源顺序必须遵循模式之间的导入顺序?

Java JAXB SchemaFactory源顺序必须遵循模式之间的导入顺序?,java,validation,xsd,jaxb,Java,Validation,Xsd,Jaxb,使用最新的JAXB(Sun)并具有架构层次结构,这些架构在架构之间使用导入指令来共享类型定义。模式验证在JAXB中对Marshaller/Unmarshaller的setSchema调用中激活,该调用应将验证推迟到Xerces(使用Java 1.5)。在使用SchemaFactory创建Schema对象时,我不想知道模式之间导入指令的顺序。不幸的是,我还没有找到Xerces的特性/属性来支持这一点。例如,如果通过导入将a.xsd拉入b.xsd,则以下代码不起作用: FileInputStream

使用最新的JAXB(Sun)并具有架构层次结构,这些架构在架构之间使用导入指令来共享类型定义。模式验证在JAXB中对Marshaller/Unmarshaller的setSchema调用中激活,该调用应将验证推迟到Xerces(使用Java 1.5)。在使用SchemaFactory创建Schema对象时,我不想知道模式之间导入指令的顺序。不幸的是,我还没有找到Xerces的特性/属性来支持这一点。例如,如果通过导入将a.xsd拉入b.xsd,则以下代码不起作用:

FileInputStream a = new FileInputStream("a.xsd");
FileInputStream b = new FileInputStream("b.xsd");

Schema schema = SchemaFactory.newInstance(
   XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(
      new Source[] { 
          new StreamSource(b),
          new StreamSource(a) 
      }
   );

源数组的顺序必须是a.xsd,然后是b.xsd。如何解决这个问题?

如果在根源上创建一个架构,然后在架构创建过程中设置ResourceResolver(LSResourceResolver)来解析其他导入的架构,该怎么办。

代码后期发布

使用以下内容生成验证架构:

SchemaFactory factory = SchemaFactory
.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
factory.setResourceResolver(new SimpleResolver(streams));
....
Schema schemaGrammers = factory.newSchema(streams.toArray(new SchemaSource[0]));
架构(schemaGrammers对象)被注入封送拆收器:

Marshaller m = ...createMarshaller();
m.setSchema(<schemaGrammers>);
Marshaller m=…createMarshaller();
m、 设置模式();
SimpleResolver实现了LSResourceResolver类:

private class SimpleResolver implements LSResourceResolver {

    private Set<Source> streams;

    public SimpleResolver(Set<Source> streams) {
        this.streams = streams;
    }

    @Override
    public LSInput resolveResource(String type, String namespaceURI,
            String publicId, String systemId, String baseURI) {
        DOMImplementationRegistry registry;
        try {

            registry = DOMImplementationRegistry.newInstance();
            DOMImplementationLS domImplementationLS = (DOMImplementationLS) registry
                    .getDOMImplementation("LS 3.0");

            LSInput ret = domImplementationLS.createLSInput();

            for (Source source : streams) {
                SchemaSource schema = (SchemaSource) source;
                if (schema.getResourceName().equals(
                        schema.getResourceName(systemId))
                        & schema.getTargetNamespace().equals(namespaceURI)) {
                    logger.debug(
                            "Resolved systemid [{}] with namespace [{}]",
                            schema.getResourceName(systemId), namespaceURI);

                    URL url = new URL(schema.getSystemId());
                    URLConnection uc = url.openConnection();

                    ret.setByteStream(uc.getInputStream());
                    ret.setSystemId(systemId);
                    return ret;
                }
            }

        } catch (ClassCastException e) {
            logger.error(e.getMessage());
        } catch (ClassNotFoundException e) {
            logger.error(e.getMessage());
        } catch (InstantiationException e) {
            logger.error(e.getMessage());
        } catch (IllegalAccessException e) {
            logger.error(e.getMessage());
        } catch (FileNotFoundException e) {
            logger.error(e.getMessage());
        } catch (IOException e) {
            logger.error(e.getMessage());
        }

        logger.error("No stream found for system id [{}]", systemId);
        return null;
    }

}
私有类SimpleResolver实现LSResourceResolver{
私有集流;
公共SimpleResolver(设置流){
this.streams=溪流;
}
@凌驾
公共LSInput resolveResource(字符串类型、字符串名称空间URI、,
字符串publicId、字符串systemId、字符串baseURI){
注册处;
试一试{
registry=doImplementationRegistry.newInstance();
dominmplementals dominmplementals=(dominmplementals)注册表
.GetDom实施(“LS 3.0”);
LSInput ret=doImplementals.createLSInput();
用于(源:流){
SchemaSource schema=(SchemaSource)源;
如果(schema.getResourceName().equals(
schema.getResourceName(系统ID))
&schema.getTargetNamespace().equals(namespaceURI)){
logger.debug(
“已解析命名空间为[{}]的systemid[{}]”,
schema.getResourceName(systemId),namespaceURI);
URL=新URL(schema.getSystemId());
URLConnection uc=url.openConnection();
ret.setByteStream(uc.getInputStream());
ret.setSystemId(系统ID);
返回ret;
}
}
}catch(ClassCastException e){
logger.error(例如getMessage());
}catch(classnotfounde异常){
logger.error(例如getMessage());
}捕获(实例化异常e){
logger.error(例如getMessage());
}捕获(非法访问例外e){
logger.error(例如getMessage());
}catch(filenotfounde异常){
logger.error(例如getMessage());
}捕获(IOE异常){
logger.error(例如getMessage());
}
错误(“没有找到系统id[{}]”的流,systemId);
返回null;
}
}

必须创建新的输入流,否则会发生冲突。不知道为什么(没有费心调试代码),但我传递给构造函数[即Set对象]的流已经被读取。

有趣的想法。可能并不总是知道模式层次结构的范围。因此,我不知道所有的根源代码(基本上,我将XJC进程捕获的语法放入META-INF文件,进行编目,将实际的模式文件放入jar,并在运行时加载SchemaFactory)。需要一种将根源的名称空间映射到其关联架构的方法。真的没有其他方法可以引导Xerces在加载所有模式后解析include吗?这可能仍然是可能的,希望其他人会提供这个答案。我建议的方法允许SchemaFactory驱动模式解析的顺序,而无需进行排序。你指定根模式,它会在导入过程中要求新的模式。虽然没有完整的编码,只是做了一个快速测试,但你的想法应该可以完美地工作……JRE 1.6更容易,因为有更多现成的xerces实现。当我得到一个工作示例时,将发布我的代码。谢谢你给我指明了正确的方向。