5

情况

我有一个复杂的 Java 模型对象图,需要来回转换为 XML 文档。XML 文档模式的对象图结构与模型的对象树非常不同。两者是可以互换的,但翻译需要大量上下文驱动的逻辑,其中使用了类似父/子的关系。

问题

我正在使用在旧系统中建立良好的模型对象,并且 XML 文档的模式是相当新的。由于我们的很多代码都依赖于模型对象的结构,我们不想重构它们。这是我正在处理的结构差异类型的简化示例:

示例数据模型树

物品

  • 描述
  • 成本
  • ...

  • 地址
  • ...

地址

  • 街道
  • 城市
  • ...

SaleTransaction(*这是正在翻译的东西)

  • 采购员(人)
  • 卖家(人)
  • 已售商品[](列表)
  • 交换物品[](列表)
  • 交易地点(地址)

示例 XML 文档结构

交换

  • 类型
  • 派对
    • party_contact_ref
      • 类型
      • 联系人 ID
  • 交易所详情
    • 类型
    • total_amount_exchanged
  • 项目
    • 物品
      • 类型
      • owning_party_contact_ref_id
      • 交换使用类型
  • 联系人
    • 接触
      • ID
      • 类型

交换类型:[ 现金销售 | 易货交易 | 组合现金和易货]

联系方式:[ 人 | 地址 ]

交换详情类型:[ 现金交换 | 易货交换]

SaleTransaction 和 Exchange 之间的映射是可能的,但不是 1-1。在示例中,模型中的“买家”将映射到 XML 文档中的联系人和联系人引用元素。此外,“Item”元素的“owning_party_contact_ref_id”属性的值将通过查看 SaleTransaction 对象图中的几个不同值来确定。

如果我正在使用的对象图需要一些翻译才能在 XML 文档中使用,我的首选工具是 XmlAdapter。但是,在这种情况下,出于三个原因,我认为使用 JAXB XML 适配器不是一个可行的解决方案。

  1. 模型图中的对象对应的 XML 元素也取决于数据。我相信所有 XmlAdapter 到类/属性的映射都是固定的。
  2. 似乎不可能使用 XmlAdapters 执行多对一或一对多解决方案。MOXy 有一个有趣的扩展,但同样,它需要到属性的固定映射。
  3. 据我所知,XmlAdapters 与单个对象一起工作,并且没有办法获得整个图被编组/解组的上下文。

问题

我敢肯定这种类型的问题相当普遍,那么您如何处理呢?有没有办法用标准工具处理这个问题?

我想出了什么

如果它很有趣,这里是我想出的可能的方法:

#1 将对象图转换问题与 XML 生成问题分开。我有一个自制的工具,可以帮助生成基于某些上下文对象的对象图。我可以从 XML 模式创建 JAXB 类,然后依靠这个工具根据我们的模型对象的上下文生成这些类的对象。这可以很好地从模型对象图生成 XML 文档,但反之则不行。这也意味着依赖非标准工具,如果可能的话我想避免。

#2 疯狂地使用 XmlAdapter 并修改模型类以便能够保留翻译状态信息(例如,模型树中的这个对象被用来在 XML 文档中创建这个元素)。这将使问题非常接近 JAXB 的标准使用模型,但我认为开发、测试和维护将是一场噩梦。

#3 像我在 #1 中那样分离对象图问题,但使用 JDOM 而不是 JAXB。这将删除所有 JAXB 所需的类和映射,但需要构建另一个自定义工具来管理模型对象到 DOM 树的映射。

我对这三种解决方案中的任何一种都不是很兴奋,但我最偏爱#1。

4

4 回答 4

2

1 是您最好的选择恕我直言。编写映射代码很乏味,但你应该抵制太聪明的冲动。您使用的任何映射工具都需要配置,我敢打赌,这与手动编写 Java 映射代码一样多。只需编写大量单元测试。

您可以为任何具有相似命名字段的类尝试 Dozer,它将使用反射来进行映射。我过去使用过它,但我的架构看起来更类似于我的域对象,所以它可能没有那么有用。

为了使代码更愉快,请使用您可以为 JAXB 找到的所有 xjc 插件,例如 fluent-api 和 value-constructor 插件。

于 2012-07-05T20:47:58.673 回答
1

如果我正在使用的对象树需要一些翻译才能在 XML 文档中使用,我的首选工具是 XmlAdapter。不过,在这种情况下,我认为使用 JAXB XML 适配器不是一个可行的解决方案。据我所知,XmlAdapters 与单个对象一起工作,并且没有办法获得整个树被编组/解组的上下文。

通常 anXmlAdapter是无状态的,但您可以XmlAdapterMarshaller/上指定一个Unmarshaller包含状态的实例。这可能就是您所需要的。

YourAdapter yourAdapter = new YourAdapter();
yourAdapter.setState(someState);
marshaller.setAdapter(yourAdapter);
unmarshaller.setAdapter(yourAdapter);

Marshaller您在/上指定的实例Unmarshaller将用于配置相应类的位置:

@XmlJavaTypeAdpater(YourAdapter.class)

了解更多信息

于 2012-07-05T20:30:50.637 回答
0

如果您有 xsd 模式,那么使用castor等工具生成 pojo 非常有用。一旦你有了生成的 pojo 的包,你就可以使用dozer来将你的“旧”对象模型映射到代表 xml 文档的 pojo。然后你只需使用 Marshaller 将 castor 生成的对象转换为 Stream、String 等。

于 2012-07-05T20:04:44.843 回答
0

对不起,我没有给你一个直接的答案,但我还不能评论我的声誉,所以这是我的“答案”。

我肯定会尝试Altova XML Spy和它的代码生成功能。我已经尝试过了,而且非常有用。我不知道它是否可以反过来工作,但由于它还具有数据库连接和其他一些东西,我相信尝试一下并玩弄它不会有任何害处它。

他们还有另一个名为MapForce的应用程序(如在地图数据库中,而不是 GIS),我从未尝试过,但从他们那里我希望它真的很有用。

我希望您发现所有这些都非常有用,并且您可以对此发表评论,并详细说明它如何帮助您(或没有帮助)。

于 2012-07-05T19:29:20.307 回答