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

Java 如何在元素级别而不是属性级别区分XML?,java,xml,diff,Java,Xml,Diff,我需要在两个XML文档之间进行比较。我一直在研究这里提到的许多不同的xml扩散工具,这些工具通常是关于堆栈溢出的,但我的需求当然非常特殊,因此它们并不真正适合。简言之,我需要比较的不是整个文档,而是元素内容(同时考虑顺序),并且我需要非常具体的输出格式,而不是传统的diff补丁 请原谅这卷课文,但我觉得很难把它解释得更短 首先,我的局限性 解决方案必须是基于Java的,或者可以与命令行Java应用程序集成。它也必须是免费的,因为我不能在这上面花“真正的钱”,只能花我的工作时间(但当然不能太多;我

我需要在两个XML文档之间进行比较。我一直在研究这里提到的许多不同的xml扩散工具,这些工具通常是关于堆栈溢出的,但我的需求当然非常特殊,因此它们并不真正适合。简言之,我需要比较的不是整个文档,而是元素内容(同时考虑顺序),并且我需要非常具体的输出格式,而不是传统的diff补丁

请原谅这卷课文,但我觉得很难把它解释得更短

首先,我的局限性

解决方案必须是基于Java的,或者可以与命令行Java应用程序集成。它也必须是免费的,因为我不能在这上面花“真正的钱”,只能花我的工作时间(但当然不能太多;我的最后期限就要到了)。。。听起来熟悉吗?最后,我的目标不是传统的diff补丁结果,而是两个源文件的非直接组合

第二,我的数据说明

每个文档包含类型为
text
section
的节点;文本是简单的字符串,但节可以同时包含文本和更多节(它们还有一个名称,作为属性提供)。此外,每个节点都标记有修订信息

这是一个示例文档。请注意,为简洁起见,这似乎是一个列表;实际上,它更像散文——也就是说,元素顺序非常重要

<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>
因此,结果不是一个diff补丁,而是一个包含更新版本信息的完整文档

第三,我所做的工作——以及我的问题

我使用了一个自定义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>

苹果
橘子
苹果
樱桃
苹果
现在,让我们修改第二个“苹果”项:


苹果
橘子

香蕉+1问得好。除了前瞻,我想不出其他解决方法,但您可能会在diff算法文献中找到一些东西(检查)。您使用的算法是否基于该页面上描述的算法?如果没有,您可能想尝试这里描述的算法(Myers 1986)。它的设计似乎是为了在基于输入大小的限制范围内优化diff操作的数量

我尝试了Oxygen的XML diff程序(在去掉修订属性之后),但没有得到比您更好的结果,因此我怀疑这个解决方案是微不足道的。

事实证明,当时我的需求没有解决方案!同时,我开发了自己的XMLDiff例程,这是针对我的问题的,所以我最终找到了一个可行的解决方案

然后,在2011年末,这篇文章发表了:


达特茅斯计算机科学家介绍了grep和diff Unix命令行实用程序的变体,它们可以处理更复杂类型的数据。新程序称为上下文无关Grep和分层Diff,将提供解析数据块而不是单行的能力。这项研究部分由谷歌和美国能源部资助。

感谢+1,@LarsH。我已经在上面发布了我算法的摘要;它似乎与页面上列出的内容不同。我已经看了一眼迈尔斯的论文,同意它是“非常密集的阅读”。恐怕我没有“大约一个月的学习时间来完全理解”,所以我想我会尝试用一些前瞻性的东西来修补我的算法。
<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>
<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>