情况
我需要支持基于模式生成XML文档,这些模式之间只是略有不同.具体来说,我需要支持的模式基于行业标准,这些标准随着时间的推移会略有变化,供应商可能会制作自己的定制版本.
问题
我打算使用JAXB 2(来自Metro)继承作为解决方案.我期望包结构最终会像这样:
com.company.xml.schema.v1
com.company.xml.schema.v2
com.company.xml.schema.v2.vendorxyz
Run Code Online (Sandbox Code Playgroud)
其中v2包中的类只是扩展v1包中的类并根据需要覆盖.不幸的是,该计划最终变得不可能,因为子类不能覆盖父类中的注释(参见此处).例如,如果模式中的属性在版本之间重命名,则v2元素类必须完全重新实现该元素而不从v1继承.
据我所知,这让我只有两个选择
选项1
为每个模式类型创建一个"基础"包,使用@XmlAccessorType(XmlAccessType.NONE)注释该包中的元素类,并删除所有其他注释.然后,在每个版本化的包中创建类,这些类将"base"包中的相应类子类化,并添加所有必需的注释.这个解决方案确实给了我一些继承领域的帮助,但代码重复是巨大的,维护是一个挑战.
选项2
不要使用JAXB.我真的不喜欢这个解决方案,因为我也想使用JAX-RS/JAX-WS.
问题
编辑
Blaise下面的解决方案非常适用于我们的大多数模式,这些模式只是彼此之间的一个小翻译,通常具有相同的数据.但是,如果将继承与包名称用于版本控制更有意义,我们遇到了一个问题.例如:
com.company.xml.schema.v1.ElementA
com.company.xml.schema.v2.ElementA
Run Code Online (Sandbox Code Playgroud)
(其中v2.ElementA扩展v1.ElementA)
在这种情况下使用MOXy的OXM会遇到错误,可以在这里找到解决方法(使用Blaise提供的解决方案,不能少!)
情况
我正在使用MOXy的JAXB实现来处理大型XML文档,其架构有许多类似的复杂类型.具体来说,有大约24种类型作为列表包装元素,具有以下结构:
<ITEMS attr1="X" attr2="Y">
<ITEM>...</ITEM>
...
<EXTENSION/>
<ITEMS>
Run Code Online (Sandbox Code Playgroud)
对于这些类似于list-wrapper的元素中的每一个,名称都会更改,并且包含的列表元素会发生更改.但是,始终存在属性(都是可选的)和单个EXTENSION元素(也是可选的).以下是两种类型的使用示例:
<ROLES visible="false">
<ROLE type="X"/>
<ROLE type="Y"/>
</ROLES>
<PAYMENTS visible="true">
<PAYMENT>
<PAYEENAME>Joe</PAYEENAME>
</PAYMENT>
<EXTENSION>
<SOMETHING>Here</SOMETHING>
</EXTENSION>
</PAYMENTS>
Run Code Online (Sandbox Code Playgroud)
问题
我想避免代码重复,因为这些元素之间唯一的变化是名称和它包含的一个或多个元素.做这个的最好方式是什么?
我只能看到两种可能的解决方案.
1
使用泛型创建具体类,以指示要在更改的集合中使用的对象类型.然后使用MOXy的外部OX映射来指示如何对类的任何个人使用进行序列化.就像是:
public class GenericContainer<T> {
@XmlAttribute
protected Boolean visibile;
@XmlElement(name = "Extension")
protected Extension extension;
// OX Mappings done in external meta file
protected List<T> items;
...
}
Run Code Online (Sandbox Code Playgroud)
虽然我喜欢这个选项,但似乎不可能在每次使用的基础上重新定义类的OX映射.
2
创建不带List属性的基类,然后为每个自定义包装元素创建一个具体类.这个解决方案肯定有效,但我最终会得到大约二十几个近乎相同的类.
是#1可能还是有更好的方法来处理这个我没有想到的?
提前致谢!
情况
我在Java中有一个复杂的模型对象图,需要来回翻译成XML文档.XML文档模式的对象图结构与模型的对象树截然不同.这两者是可以互换的,但是翻译需要许多上下文驱动的逻辑,其中使用父/子关系.
问题
我正在处理在旧系统中已经建立的模型对象,而XML文档的模式是相当新的.由于我们的许多代码都依赖于模型对象的结构,因此我们不希望对它们进行重构.以下是我正在处理的结构差异类型的简化示例:
示例数据模型树
项目
- 描述
- 成本
- ...
人
- 名字
- 姓
- 地址
- ...
地址
- 街
- 市
- ...
SaleTransaction(*这是被翻译的东西)
- 买方(人)
- 卖方(人)
- 已售物品[](清单)
- 交换项目[](列表)
- 交易地点(地址)
示例XML文档结构
交换
- 类型
- 派对
- party_contact_ref
- 类型
- CONTACT_ID
- 交换细节
- 类型
- total_amount_exchanged
- 项目
- 项目
- 类型
- owning_party_contact_ref_id
- exchange_use_type
- 往来
- 联系
- ID
- 类型
交易所类型:[现金出售| BARTER | 组合现金与大师]
联系方式:[PERSON | 地址 ]
交易所详细信息类型:[CASH EXCHANGE | BARTER EXCHANGE]
SaleTransaction和Exchange之间的映射是可能的,而不是1-1.在该示例中,模型中的"买方"将映射到XML文档中的联系人和联系人引用元素.此外,"Item"元素的"owning_party_contact_ref_id"属性的值将通过查看SaleTransaction对象图中的几个不同值来确定.
如果我正在使用的对象图需要一些翻译才能在XML文档中使用,我的首选工具是XmlAdapter.但在这种情况下,我没有看到使用JAXB XML适配器作为可行解决方案有三个原因.
问题
我确定这种类型的问题很常见,所以你如何处理?有没有办法用标准工具处理这个问题?
我想出了什么
万一它很有意思,这里有我提出的可行方法:
#1 将对象图转换问题与XML生成问题分开.我有一个本土工具,可以帮助根据一些上下文对象生成对象图.我可以从XML模式创建JAXB类,然后依靠此工具根据模型对象的上下文生成这些类的对象.这样可以很好地从模型对象图生成XML文档,但不是相反.它还意味着依赖非标准工具,如果可能的话我想避免使用它们.
#2 Go XmlAdapter疯狂并修改模型类以保留翻译状态信息(例如,模型树中的此对象用于在XML文档中创建此元素).这将使问题与JAXB的标准使用模型非常接近,但我认为开发,测试和维护将是一场噩梦.
#3 像在#1中那样分离对象图问题,但是使用JDOM而不是JAXB.这将删除所有JAXB所需的类和映射,但需要构建另一个自定义工具来管理模型对象到DOM树映射.
我对三种解决方案中的任何一种都不是很兴奋,但我最偏向于#1.
我们正在使用 go-templates 创建 yaml。在它们中,我们有需要在特定缩进级别缩进的多行输出操作。我们可以indent为此使用该函数,但它不会区别对待第一行,因此要求操作定义没有缩进级别。
例如:
foo:
bar:
baz:
{{ myYamlOutputtingAction | indent 6 }} # <-- notice 0 indent level
Run Code Online (Sandbox Code Playgroud)
有没有一种方法可以将我的操作定义放在对模板上下文有意义的缩进级别?