如何在一个Java应用程序中处理不同版本的xsd文件?

2022-09-04 04:20:44

事实

在我的java应用程序中,我必须同时处理具有不同模式版本的XML文件(xsd文件)。XML文件的内容在不同版本之间只发生了一点变化,所以我想主要使用相同的代码来处理它,并且只是根据所用架构的版本进行一些大小写区分。

当前解决方案

现在,我正在使用SAX解析器解析XML文件,而我自己忽略了架构版本,只是检查我处理所需的标签是否存在。ContentHandler

可能的替代方案

我真的很想使用JAXB来生成用于解析XML文件的类。通过这种方式,我可以从Java代码中删除所有硬编码的字符串(常量),并改用生成的类进行处理。

问题

  • 如何使用 JAXB 以统一的方式处理不同的模式版本?
  • 有没有更好的解决方案?

进展

我将架构版本编译为不同的包 v1、v2 和 v3。现在我可以创建一个这样的方式:Unmarshaller

JAXBContext jc = JAXBContext.newInstance( 
    v1.Root.class, v2.Root.class, v3.Root.class );
Unmarshaller u = jc.createUnmarshaller();

现在,我提供了与 XML 文件架构匹配的包中的类。u.unmarshal( xmlInputStream );Root

接下来,我将尝试定义一个来访问架构的公共部分。如果您以前做过这样的事情,请告诉我。与此同时,我正在阅读JAXB规范...interface


答案 1

首先,您需要某种方法来识别适用于特定实例文档的架构。您说文档具有属性,因此这是一个解决方案。但请注意,您必须专门配置分析器以使用此属性,恶意文档可能会指定您无法控制的架构位置。相反,我建议获取属性值,并使用它来在内部表中查找适当的架构。schemaLocation

接下来是访问数据。你没有说为什么你使用三种不同的模式。唯一合理的原因是不断发展的数据规范(即,模式表示相同数据的版本 1、2 和 3)。如果这不是你的理由,那么你需要重新思考你的设计。

如果您尝试支持不断发展的数据规范,那么您需要回答“如何处理丢失的数据”的问题。这个问题有几个答案:一个是维护多个版本的代码。通过重构常见功能,这不是一个坏主意,但它很容易变得不可维护。

另一种方法是使用单个代码库和某种包含规则的适配器对象。如果你沿着这条路走下去,JAXB是错误的解决方案,因为它与模式相关联。你也许可以使用一个宽松的XML->Java转换器:我相信XStream会工作,我知道实用XML的1.1版本会工作(因为我写了它) - 尽管你必须自己构建它。

根据架构的复杂性,另一个更好的替代方法是开发一组使用 XPath 检索数据的对象。我可能会使用“master”对象来实现,该对象包含架构的每个变体中每个字段的 XPath 表达式。然后创建包含实例文档的 DOM 版本的轻量级“包装器”对象,并使用适用于架构的 XPath。但是,请注意,这是有限的 tor 只读访问。


答案 2

推荐