使用 JAXB 支持具有细微变化的模式
情况
我需要支持基于模式生成 XML 文档,这些模式之间的差异很小。具体来说,我需要支持的模式基于行业标准,这些标准会随着时间的推移而略有变化,并且供应商可能会制作自己的定制版本。
问题
我打算使用 JAXB 2(来自 Metro)和继承作为解决方案。我预计包结构最终会是这样的:
com.company.xml.schema.v1
com.company.xml.schema.v2
com.company.xml.schema.v2.vendorxyz
v2 包中的类将简单地扩展 v1 包中的类并根据需要进行覆盖。不幸的是,这个计划最终是不可能的,因为子类无法覆盖父类中的注释(参见此处)。例如,如果模式中的属性在版本之间被重命名,则 v2 元素类将必须完全重新实现该元素,而不是从 v1 继承。
因此,据我所知,我只有两个选项
选项 1
为每个架构类型创建一个“基本”包,使用 @XmlAccessorType(XmlAccessType.NONE) 注释该包中的元素类,并删除所有其他注释。然后,在每个版本化包中创建类,这些类是“基”包中相应类的子类,并添加所有必需的注释。这个解决方案确实在继承领域给了我一点帮助,但是代码重复巨大,维护起来将是一个挑战。
选项 2
不要使用 JAXB。我真的不喜欢这个解决方案,因为我也想使用 JAX-RS/JAX-WS。
问题
- 我应该如何使用 JAXB 来支持具有细微变化的多个模式,而不需要大量重复代码?
- 我应该考虑不同的技术组合吗?
编辑
Blaise 提供的以下解决方案非常适合我们的大多数模式,这些模式只是使用大致相同的数据进行的较小的相互转换。然而,当使用继承和包名称进行版本控制更有意义时,我们遇到了一个问题。例如:(
com.company.xml.schema.v1.ElementA
com.company.xml.schema.v2.ElementA
其中 v2.ElementA 扩展了 v1.ElementA)
在这种情况下使用 MOXy 的 OXM 会偶然发现一个错误,并且可以找到解决方法 这里(Blaise 提供的解决方案,同样如此!)
The Situation
I need to support generating XML documents based on schemas that vary only slightly between each other. Specifically, the schemas that I need to support are based on industry standards that change slightly over time and vendors may make their own customized version of them.
The Problem
I was intending to use JAXB 2 (from Metro) with inheritance as a solution. I expected the package structure to end up something like this:
com.company.xml.schema.v1
com.company.xml.schema.v2
com.company.xml.schema.v2.vendorxyz
Where the classes in the v2 package would simply extend the classes in the v1 package and override as necessary. Unfortunately, that plan ended up being impossible since subclasses cannot overwrite the annotations in parent classes (see here). For example, if an attribute in a schema was renamed between versions, then the v2 element class would have to completely re-implement the element without inheriting from the v1.
So that leaves me with only two options as far as I can tell
Option 1
Create a "base" package for each schema type, annotate the element classes in that package with @XmlAccessorType(XmlAccessType.NONE), and remove all other annotations. Then, in each versioned package create classes that subclass the corresponding class in the "base" package and add all the required annotations. This solution does give me a little help in the inheritance realm, but code duplication is huge and it would be a challenge to maintain.
Option 2
Don't use JAXB. I really don't like this solution since I'd also like to work with JAX-RS/JAX-WS.
Questions
- How should I be using JAXB in order to support multiple schemas with minor variations, without a bunch of code duplication?
- Is there a different technology combination I should be looking at?
EDIT
The solution below from Blaise worked perfectly for most of our schemas which were just a minor translation of each other with generally the same data. However, we ran into a problem in cases where it made more sense to use inheritance with package names for versioning. For Example:
com.company.xml.schema.v1.ElementA
com.company.xml.schema.v2.ElementA
(where v2.ElementA extends v1.ElementA)
Using MOXy's OXM in this case stumbles across a bug and the workaround can be found here (with the solution provided by Blaise, no less!)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
注意:我是EclipseLink JAXB (MOXy) 的领导者和 JAXB 2 的成员(JSR-222)专家组。
您可以使用 EclipseLink JAXB 中的外部绑定文档来映射 XML 模式之间的变化。
供应商 1
您可以使用标准 JAXB 注释来映射供应商之一:
供应商 2
我们将使用 MOXy 的外部元数据来自定义注释提供的元数据。在下面的文档 (
oxm-v2.xml
) 中,我们将把firstName
和lastName
属性映射到 XML 属性:Vendor 3< /strong>
我们将再次使用 MOXy 的外部绑定文档 (oxm-v3.xml) 来覆盖注释。这次我们将使
id
属性成为一个 XML 元素。演示
下面的示例代码演示了如何指定外部元数据。请注意我如何引入第四个供应商来表明可以组合外部元数据文档。
输出
以下是每个供应商的输出。请记住,使用相同的
Customer
实例来制作每个 XML 文档。了解更多信息
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB 2 (JSR-222) expert group.
You could use the external binding document in EclipseLink JAXB to map the variations among XML Schemas.
Vendor 1
You could use the standard JAXB annotations to map one of the vendors:
Vendor 2
We will use MOXy's external metadata to customize the metadata provided by annotations. In the document (
oxm-v2.xml
) below we will map thefirstName
andlastName
properties to XML Attributes:Vendor 3
Again we will use MOXy's external binding document (oxm-v3.xml) to override the annotations. This time we will make the
id
property an XML element.Demo
The sample code below demonstrates to specify the external metadata. Note how I introduced a fourth vendor to show that the external metadata documents can be combined.
Output
Below is the output from each of the vendors. Remember that the same instance of
Customer
was used to make each of these XML documents.For More Information