一种 XML2XML 格式之间转换的解决方案本文提供了一种 XML2XML 格式之间转换的通用解决方案。我们通过建立用以存储数据信息的数据模型,并应用优化器 (Optimizers),转换规则 (Rules) 对所存储的信息进行深入处理等操作,序列化或转换生成了 XML 格式的目标文件,从而完成了 XML 格式之间的转换工作。
一种 XML 格式之间转换的构架 不同 XML 格式之间的转换工作是如此之常见且又这般之重要。在 IT 领域,为了解决这一问题,各种新方法、新技术层出不穷。比如 XSL、XSLT 等技术,又比如 RDF/RDFS/OWL 技术(XML Schema 是用来定义 XML 文档结构 , 而 RDFS/OWL(本体描述语言)则定义了文档词汇,提供了一种共同的理解。当然本体 (Ontology),语义网络(Semantic Web)等相关的技术不单是为了解决 XML 格式之间转换的问题的。深入的知识,读者可参考有关的文档资料。) 本文也提出了一种 XML 格式之间转换的方案构架。如下图 1 所示: 图 1. XML 格式转换框架 原文件(XML 格式)通过解析器(Parser, 可以是任何一种 XML 解析技术 DOM, SAX, StAX etc.)解析生成数据信息,并存储在数据模型里。数据模型是整个构架的核心部分。数据模型主要是基于目标文件的 XML Schema 而构建的,也可以基于目标 XML 文件的领域知识(Domain Knowledge)构建。它可以是普通的数据模型(基于 POJO 的 Data Model), 也可以是基于 EMF(Eclipse Modeling Framework)的数据模型。关于数据模型,我们将在下一部分作详细的介绍。在对原 XML 文件进行解析的过程中,解析器要根据基于原文件和目标文件的 XML Schema 文件而生成的映射表中的信息,做相应的解析优化处理(比如,在电子表单领域,若目标文件的 Schema 中没有定义类似椭圆形(Oval)这样的元素,原文件中的 Oval 元素将全部被过滤掉,不进行解析。如果在目标文件的 Schema 中没有定义类似矩形的圆(round)这样的属性,那么原文件的矩形的圆(round)属性也将被过滤掉,不进行解析)。 在输出目标 XML 文件之前,优化器(Optimizer)和转换规则 (Rule) 先后对数据模型中的数据信息进行相应处理。配置文件 (Profile) 在构架中的作用是用来管理优化器和转换规则的。用户可以根据业务逻辑的需要通过配置文件来定制优化器和转换规则。在本文下面的部分中,我们将分别加以详细的论述。 经由上面对 XML 格式转换构架的简单介绍,读者就可以看出这种解决方案的简单灵活性,可复用性和可扩展性。只需为不同的原文件提供一个解析器 (Parser) 就扩展了构架的应用。 构建 XML 格式转换的数据模型(Data Model) 数据模型是用来存储解析进来的数据信息的,它是构架的核心部分。那么如何构建数据模型呢?有两种构建数据模型的办法——普通的数据模型和基于 EMF 技术构建的数据模型。 普通的数据模型是应用普通的 Java 类(POJO)来构建,主要是基于目标文件的领域知识,通常是结构化的数据模型。这种模型构建的优点是简单、通用,主要的缺点是需要构建输出模块从而把模型中的信息输出为满足目标 XML Schema 的 XML 文件。图 2 显示了在电子表单领域中应用的结构化数据模型示例片段。 图 2. 电子表单领域的结构化数据模型示例片段 基于 EMF 技术构建数据模型的技术已经相当成熟(读者可以参考 DW 上的有关文章)。在本文中,我们主要应用目标文件的 XML Schema 来构建 EMF 数据模型。基于 EMF 的数据模型具有事件通知机制和持久化方面的支持。因此,模型带来的最大的好处就是开发者不必自己动手构建输出模块。当然基于 EMF 构建数据模型需要开发者深入了解 EMF 建模机制。(IBM® Lotus Form 的 FOM(Form Object Model) 就是基于 EMF 技术构建的) 模型的构建是 XML 格式之间转换的关键。构建的模型应当满足应用程序的需求 ( 对照映射表,模型要完全支持原文件中的可匹配信息。也就是说,不能丢失可匹配数据信息 ),不要求模型囊括相关领域的所有通用知识,但模型提供给原文件解析器的 API 应该简单易用,模型要具有高可扩展性和良好的可维护性。 优化器(Optimizers)在解析原 XML 文件中的应用 当原 XML 文件中的信息被解析进来,并存储在已经建立的数据模型里,此时的数据模型称为原始数据模型,模型里面的数据信息称为原始数据信息。我们根据目标 XML 文件的特性,需要对原始数据信息进行优化处理。可以根据需要创建若干个 Optimizers。 图 3 显示了优化器(Optimizers)的构架。 图 3. 优化器(Optimizers)的构架 根据电子表单领域的实际需要,我们创建了很多 Optimizers。举例如下:
图 4. 线的对齐、连接示例
图 5. 标签的对齐、连接示例
图 6. 输入框的识别示例
图 7. 选择框的识别示例 我们通过对以上 Optimizers 的应用,使得 PDF 文件的转换效果更佳。 事实上,优化器的开发应用取决于两种格式文件之间的可匹配的程度。如果两种文件的可匹配性很高(比如系统早期的 XML 文件转换升级成系统现在的 XML 文件),基本上不用开发优化器。反之,为了使数据平滑输出,需要根据业务逻辑的需要进行相应的优化处理。 此外,如果某种原文件的解析器需要用户通过 UI 配置一些解析参数的话,我们也可以提供 Parser 阶段应用的“Optimizers”。举例来说,原 XML 文件的某个元素和可匹配的目标 XML 文件的相应元素是一对多的关系,那么 Parser 的解析就有了多种选择。这时候,让用户进行选择似乎是最合理的解析策略了。(当然这里的 Optimizers 加上了引号,因为它已经不是基于数据模型进行优化处理了) 。 转换规则(Rules)在生成目标 XML 文件格式中的应用 数据模型里面的信息经过优化后,就可以输出或者序列化为满足目标 XML Schema 的数据文件。在这个过程中,我们又可以根据用户的转换要求执行一些通用的转换规则。比如在电子表单领域,用户经常有这样的转换要求:对转换后的电子表单文件,要求统一更改标签(Label)的前景颜色(Font color),统一更改页面(Page)的背景颜色 (background color),所有转换后的文件都要加入一个标准的包含企业标志(Logo)的 Toolbar 模版等等。这些转换要求可以以转换规则的形式存在。用户可以开发定制并应用自己的转换规则来批量转换原文件。 对比 Optimizers, 我们知道转换规则主要是针对目标文件的通用操作的。用户对目标文件的常用的操作都可以以 Rules 的形式存在于转换框架里。这就极大的丰富了格式转换的框架。 应用配置文件(Profile)管理 Optimizers 和 Rules 配置文件就是一个 XML 格式的文件,用以持久化管理所有的 Optimizers 和 Rules。用户可以通过定制 Optimizers 和 Rules 来配置自己的 Profile(通常情况下,每一种原文件的解析器都对应一个缺省默认的 Profile。系统还为所有解析器(包括用户定制的解析器,既第三方解析器)提供了一个可扩展的通用的 Profile)。在转换的过程中,需要加载 Profile,进而应用里面的优化器和转换规则来对数据模型进行深入处理,从而完成转换工作。清单 1. 给出了 Profile 文件的示例片段。 清单 1. Profile 文件示例
基于 Eclipse PDE(Plug-in Development Environment), 我们开发出了灵活、可扩展的 XML 格式的电子表单文件转换框架。我们为解析器 (Parser), 优化器 (Optimizers) 和转换规则 (Rules) 都设置了扩展点(extension point)(读者可以看出,扩展点和 UI 框架都具有通用的价值)。用户可以通过插件机制开发定制自己的 Parser,Optimizers 和 Rules。如图 8 所示: 图 8. XML 格式转换的扩展点 清单 2. 框架的 Extension 示例
另外读者在开发自己的 Optimizers 的时候,可以根据领域知识或目标 XML Schema 文件的优化需要,在数据模型的基础上构建自己的优化模型。把 Optimizers 对数据模型的相关操作封装在这个优化模型里,从而不会因为 Optimizers 的动态需求使得数据模型变的复杂难懂。 图 9 展示了 XML 格式转换框架的主向导(Wizard)页面 ( 注:.itx 文件实际上就是基于 XML 语法的电子表单文件 )。用户可以选择解析器和解析器相应的配置文件对原文件进行批量的转换。 图 9. 转换框架示例 如果开发人员想要基于此框架开发插件,比如,用户想把一种新型的基于 XML 语法格式的电子表单文件转换生成 IBM ®Lotus Forms 电子表单文件。开发者只需了解数据模型所提供的 API,然后开发一个解析器的 extension 就可以了。 小结 本文提供了一种 XML2XML 格式之间转换的通用解决方案。该方案的主要特点是构架灵活、可扩展,可以用来解决复杂文件格式的转换问题。当然用户可以进一步扩展这个转换构架。只要为非 XML 格式的文件写一个解析器,NON-XML2XML 的问题就会迎刃而解了。倘若读者根据模型里边的数据信息,为某一特殊文件格式写一个输出器(Output Writer)的话,那么任何两种文件格式的转换问题都可以基于此框架来解决了。 |