我需要在两个XML文档之间进行比较.我一直在寻找Stack Overflow上通常提到的许多不同的xml-diffing工具,但我的需求当然非常特殊,因此它们并不适合.简而言之,我需要比较整个文档,而不是元素内容(考虑到顺序),我需要一个非常具体的输出格式而不是传统的差异补丁.
请原谅这一卷文本,但我发现很难解释它.
首先,我的局限
解决方案必须基于Java,或者可以与命令行Java应用程序集成.它也必须是免费的,因为我不允许在这上面花费“真钱”,只有我的工作时间(但当然不是太多;我的最后期限迫在眉睫)…听起来很熟悉?最后,我的目标不是传统的差异补丁结果,而是两个源文件的非直接组合.
第二,我的数据的描述
每个文档包含文本或节类型的节点;文本是简单的字符串,但部分可以包含文本和更多部分(它们也有一个名称,作为属性给出).此外,每个节点都标有修订信息.
这是一份示例文档.请注意,为简洁起见,这似乎是一个列表;实际上它更像散文 – 也就是说,元素顺序非常重要.
<document diff="=" revision="1">
<text diff="=" revision="1">Apples</text>
<text diff="=" revision="1">Chxrries</text>
<section diff="=" revision="1" name="Blue ones">
<text diff="=" revision="1">Grapes</text>
<section diff="=" revision="1" name="More">
<text diff="=" revision="1">Blueberries</text>
</section>
<text diff="=" revision="1">Oranges</text>
</section>
</document>
这需要与新版本进行比较,新版本包含更改但没有修订信息(尚未!).在这个例子中,我修复了第二个元素中的拼写错误,并且我移动了另一个元素,但可能会有更广泛的更改,例如添加或删除整个部分.
<document>
<text>Apples</text>
<text>Oranges</text>
<text>Cherries</text>
<section name="Blue ones">
<text>Grapes</text>
<section name="More">
<text>Blueberries</text>
</section>
</section>
</document>
目标是创建包含所有信息的第三个XML文档.请注意,受影响元素的diff标记已更改(“*”表示元素内的更改)并且其修订号已被碰撞;未更改的元素保留其旧的修订信息.
<document diff="*" revision="2">
<text diff="=" revision="1">Apples</text>
<text diff="+" revision="2">Oranges</text>
<text diff="-" revision="2">Chxrries</text>
<text diff="+" revision="2">Cherries</text>
<sectio diff="*" revision="1"n name="Blue ones">
<text diff="=" revision="1">Grapes</text>
<section diff="=" revision="1" name="More">
<text diff="=" revision="1">Blueberries</text>
</section>
<text diff="-" revision="2">Oranges</text>
</section>
</document>
因此,结果不是差异补丁,而是具有更新版本信息的完整文档.
第三,我的工作 – 以及我的问题
我有大部分工作,使用自定义java函数进行逐行比较 – 除了它在一个特定用例中失败,即旧版本包含特定文本不止一次,而非最后一个在新版本中更改.这将“欺骗”比较器使旧版本文本与以下新版本文本匹配,而不是识别单文本更改.虽然结果在技术上是正确的,但是不必要的添加和删除的“噪音”掩盖了这一事实,对于人类来说,看起来很简单(并且顺便提一下,这个标记是为了人类的可读性).现在,正是由于我的逐行方法,我发现这很难解决.
<document diff="=" revision="1">
<text diff="=" revision="1">Apples</text>
<text diff="=" revision="1">Oranges</text>
<text diff="=" revision="1">Apples</text>
<text diff="=" revision="1">Cherries</text>
<text diff="=" revision="1">Apples</text>
</document>
现在,让我们改变第二个“苹果”项目:
<document>
<text>Apples</text>
<text>Oranges</text>
<text>Bananas</text> <--- I've only changed this
<text>Cherries</text>
<text>Apples</text>
<text>Grapes</text>
</document>
结果错误地变为:
<document diff="*" revision="2">
<text diff="=" revision="1">Apples</text>
<text diff="=" revision="1">Oranges</text>
<text diff="+" revision="2">Bananas</text> <--- Addition, okay
<text diff="+" revision="2">Cherries</text> <--- Incorrectly added
<text diff="=" revision="1">Apples</text> <--- Incorrectly matches the next occurrence
<text diff="-" revision="2">Cherries</text> <--- Incorrectly removed
<text diff="-" revision="2">Apples</text> <--- Incorrectly removed
<text diff="=" revision="1">Grapes</text> <--- Back on track, after the next occurrence of the changed element
</document>
没错,我可能会缓解这个问题,但是要实现某种形式的预测,但我无法分辨出前瞻性,因此听起来像是一个非常混乱的解决方案而不是真正的解决方案.
…所以最后,我迫切需要一个xml diff工具,它允许我分析数据内容并创建这个非常特殊的输出.无论是那个,还是我如何避免这个特殊陷阱的任何提示.
如果您有任何建议或问题需要详细说明,我非常希望收到您的来信.
这是一个previous question的重新声明.不幸的是,我无法提供任何奖励来宣传它,但希望我在这里的新解释会更好.
对于它的价值,这是我的算法,它似乎没有在@larsH链接到的DiffAlgorithm页面上列出:
比较两个列表:左手和右手称它们为lL和lR
两侧.创建两个“主要”指针iL和iR并将它们设置为
每个列表的第一个元素.对于循环,请使用这些主要指针
设置主要元素eL和eR,使得eL = lL(iL)和eR = 1R(iR).
比较eL和eR.如果eL与eR匹配,我们可以将eL复制到结果中
匹配并将两个主要指针推进一个插槽.如果是eL和eR
不匹配,创建一个辅助指针(iR2),将其初始化为
iR后的时隙(iR2 = iR 1)并扫描lR的剩余部分(设置
我们去的时候eR2 = lR(iR2).如果eL在lR的剩余部分不匹配,
eL必须已删除,我们可以将eL添加到结果中
删除并仅前进主指针iL(以便下一个
比较将比较下一个eL与相同的eR).如果找到了eL
匹配eR2(在位置iR2> iR),然后是该范围内的所有元素
[iR,iR2 [必须添加.然后我们可以添加每个元素
作为加法的结果的lR范围,并设置iR = iR2.我们也可以
将元素eL作为匹配项添加到结果中(因为它已匹配
在eR2),最后在新的主指针处重复比较
位置.在迭代两者中的较短者时执行所有这些操作
名单;然后,将剩余的lL添加为删除或添加
lR的剩余部分作为补充.
解决方法:
事实证明,我的需要当时没有解决方案!同时,我已经开发了我自己的xml-diff例程,这个例程特定于我的问题,所以我最终得到了一个有效的解决方案.
然后,在2011年底,这个发布:Slashdot: Researchers Expanding Diff, Grep Unix Tools
达特茅斯计算机科学家介绍了可以处理更复杂类型数据的grep和diff Unix命令行实用程序的变种.这些名为Context-Free Grep和Hierarchical Diff的新程序将提供解析数据块而不是单行的能力.该研究部分由谷歌和美国能源部资助.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。