微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

java – 如何在元素级别而不是属性上区分XML?

我需要在两个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 举报,一经查实,本站将立刻删除。