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

时间:2010-08-24 15:51:27

标签: java validation xsd jaxb

使用最新的JAXB(Sun)并具有模式层次结构,这些模式在模式之间使用导入指令来共享类型定义。在JAXB中对Marshaller / Unmarshaller的setSchema调用中激活了模式验证,这应该将验证推迟到Xerces(使用Java 1.5)。在使用SchemaFactory创建Schema对象时,我不想知道模式之间的import指令的顺序。不幸的是,我还没有找到允许这个的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) 
      }
   );

Source数组的顺序必须是a.xsd,然后是b.xsd。有什么方法吗?

2 个答案:

答案 0 :(得分:6)

如果在根源上创建架构,然后设置ResourceResolver(LSResourceResolver)以在架构创建期间解析其他导入的架构,该怎么办呢?

答案 1 :(得分:4)

代码的后期。

使用以下命令生成验证模式:

SchemaFactory factory = SchemaFactory
.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
factory.setResourceResolver(new SimpleResolver(streams));
....
Schema schemaGrammers = factory.newSchema(streams.toArray(new SchemaSource[0]));

Schema(schemaGrammers对象)被注入Marshaller:

Marshaller m = ...createMarshaller();
m.setSchema(<schemaGrammers>);

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;
    }

}

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