最近公司的新产品准备上线,因为涉及到多个系统之间的集成,所以要做几轮的模拟测试,以保证系统间的稳定运行以及数据的准确性。对于其中一个Batch Job,我们需要生成多种XML给其它系统使用,这个Batch并不是全新的,在之前的版本就有,但是这次数据模型有变动,一些业务逻辑也有少许变动,但期望生成的数据是一样的,所以就需要比较两个版本的系统所生成的XML。
现在真是越来越不喜欢XML,超过30M的文件,基本就不可能用NotePad++打开了(与我的机器配置太差也有关系)。通常对于一些小的文件,还可以用Beyond Compare之类的比较工具,而我们Batch生成的XML文件可能会超过100M,那就不可能通过一些桌面软件去做比较了,而且数量太大,肉眼比较的准确性也不能保证。这些XML文件中主要是金融产品信息,由于在生成文件的时候并没有做排序,因此每次生成的文件中,产品的顺序可能也是不同的,这样就更难用比较工具了。
对于这种情况,只能自己去写个比较工具了,在网上找了一下,也没找到满足要求的,现在代码已经完成,放在GitHub,可以生成比较详细的统计信息,如XML中的record数量,不同record的数量,不相同的field,处理时间等。在我那台破机器上,比较两个150M的文件,可以在两分钟内完成。
具体的用法可项目的主页上已经有描述了,这里简单说下实现的思路,因为实现的比较匆忙,有很多考虑不周的地方。实现的步骤如下:
- 通过SAX解析将源文件解析成一个Map,key为产品ID,可以为一个或多个element组合而成,value为该产品所对应的XML内容。
- 仍然通过SAX解析待比较的文件,每解析出一个产品信息,就从之前的Map中取出相同的产品信息,这时就得到了相同产品的两个版本的内容。如果产品只存在于待比较的文件中,则计入不同record的数量。
- 使用DOM解析两个XML片段,结果放在两个Map中,key为element的名字,value的element的值。这里需要考虑几种情况:如果element是可选的,则可能只出现在其中一个XML片段中;如果element是重复性的组合元素,则当作一个field。
- 在比较的过程中,每比较完一个XML片段就删除引用,以达到在内存不够时,可以通过GC释放内存。
- 当比较结束,第一步产生的Map中若还有产品存在,则为待比较的文件中没有的产品,计入不同record的数量。
- 统计比较结果,一并写入文件中。
暂时未考虑到更好的有效利用内存的方法,对于比较重复性的element,现在是通过配置来识别,一直在纠结要不要通过解析XSD来实现,但这种方式既增加了代码的复杂性,也很难去处理不同级别的重复性元素,比如root element是productList,下一级就是重复性的元素product,对于这种情况,是不应当视为重复性元素来处理的。
改进还要继续,提供给更多有相似需求的人使用。