【问题标题】:JAXB SchemaFactory source order must follow import order between schemas?JAXB SchemaFactory 源顺序必须遵循模式之间的导入顺序吗?
【发布时间】:2011-04-03 06:25:06
【问题描述】:

使用最新的 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) 
      }
   );

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

【问题讨论】:

    标签: java validation xsd jaxb


    【解决方案1】:

    代码的后期发布。

    生成验证模式:

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

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

    【讨论】:

      【解决方案2】:

      如果您在根 Source 上创建一个架构,然后设置一个 ResourceResolver (LSResourceResolver) 以在架构创建期间解析其他导入的架构。

      【讨论】:

      • 有趣的想法。可能并不总是知道模式层次结构的范围。所以我不知道所有的根源(基本上我将 XJC 进程捕获的语法放入 META-INF 文件中,进行编目,加上实际的模式文件放入 jar 并在运行时加载 SchemaFactory)。需要一种将根源的名称空间映射到其关联模式的方法。在加载所有模式后,真的没有其他方法可以引导 Xerces 解决包含问题吗?
      • 这仍然是可能的,希望其他人会提供这个答案。我建议的方法允许 SchemaFactory 驱动模式得到解析的顺序,而无需您进行排序。您指定根架构,它会在处理导入时要求新的架构。
      • 尚未对整个方式进行编码,只是进行了快速测试,但您的想法应该可以完美运行....使用 JRE 1.6 更容易,因为提供了更多开箱即用的 xerces 实现。当我得到一个工作示例时将发布我的代码。感谢您为我指明正确的方向。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-11-25
      • 2019-08-10
      • 2019-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多