论坛首页 Java企业应用论坛

用连连看的方法比较XML文档

浏览 1700 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-04-10  
比较两个XML文档在语义上相等,比想的要难一点。例如,下面的两个XML文档
1.xml
<xml/><a><b>bb</b><c k='11'></c></a>
2.xml
<xml/><a><c k='11'></c><b>bb</b></a>
排列有些不同,但内容还是一样的.
如果用DOM比较的话,算法基本上就是,
1 解析第一个文档,构成一个结点树
2 遍历第二个文档结点,搜索第一个文档树,找到对应的结点,比较。
但问题是怎么找到对应的结点,首先是结点位置的层次问题,其次怎么确定对应关系。
对于层次问题,我们可以标记,在同一级的兄弟结点上比较。
但就算我们缩小了范围,对于没有特殊标记的结点,比如<li>这样的标签,还是很难确定对应关系,就算是想排序都没有关键字。
虽然我也知道,基于树都可以做递归,去简化设计,但真没想出来:<

最后还是连连看的灵感。打碎再比较.
基本的思路,
把结点分成两类,有BODY的和没有BODY的.
比如上面的XML文件,
就可以分成有BODY的<b>bb</b>;没有BODY的<xml/>, <a></a>, <c k='11'></c>,这几个结点.最终的目标就是比较这些打碎的TAG.
同时流式解析两个XML文件,,并为每一个文件生成相应的一个TAG栈.
把一个TAG压进栈,要分两次进行,第一次,压进<xx>,如果有BODY的话,把BODY也压进去.第二次,压入</xx>.
这样我们还需要一个指针栈,标记未完全压入栈的TAG.
同时把完全压入栈的元素,放到一个比较队列里.,每完全压入一个元素,就比较两个栈的比较队列.如果相同,就删除这个TAG.如果两个XML文件,基本相似的话,比较队列的SIZE都会保持比较小的值.节省很多的遍历开支.

完成XML的解析后,只要比较两个栈中比较队列的大小,如果都为空,那么这两个XML就是内容相等的.

但这个的算法,忽略了结点的位置信息.
比如,<a></a><a></a>和<a><a></a></a>也会被等同.
这里做了一个简单的扩展.为每一个TAG加一个ID属性,
第一个压入未完全压入栈的TAG的ID值为该TAG的<xx>和BODY字符串的hashCode值.
以后入栈的TAG的ID值是未完全压入栈栈顶元素ID值+该TAG的<xx>和BODY的hashCode值.比较时,先比较一个ID然后再比较内容.

目前只完成了一个很简单的实现.还不能比较不同排列的属性,但对于我的需求来说,已经足够了.
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics