我最近试图找出比较两个大型 XML 文档的最快方法,一位同事建议对它们进行散列,然后只比较散列字符串。
起初,这似乎是一个明显/绝妙的想法!但后来有件事本能地告诉我,这可能“好得令人难以置信”。
就像序列化 POJO 进行比较/克隆被广泛认为是“不好的做法”一样,这种技术也是如此吗?为什么或者为什么不?警告/陷阱等?
我最近试图找出比较两个大型 XML 文档的最快方法,一位同事建议对它们进行散列,然后只比较散列字符串。
起初,这似乎是一个明显/绝妙的想法!但后来有件事本能地告诉我,这可能“好得令人难以置信”。
就像序列化 POJO 进行比较/克隆被广泛认为是“不好的做法”一样,这种技术也是如此吗?为什么或者为什么不?警告/陷阱等?
首先让我说 XML 比较很棘手。这很棘手,因为正如您在问题标题中所说的那样,您正在比较 XML 实例。
XML 不仅仅是您可以比较的内容(文本文件、二进制文件等),以查看是否有不同之处;XML 是有含义的,不同的 XML 实例可以有相同的含义。
例如,考虑这个 XML 示例:
<sample a="foo" b="bar" />
那和这个不一样吗?
<sample b='bar' a='foo' />
或这个:
<sample
a="foo"
b="bar" />
甚至这个?:
<sample a="foo" b="bar"></sample>
答案是样本都是相等的。但是如果你对每一个进行哈希处理,你每次都会得到不同的哈希值。
如果要散列 XML 实例并使用散列进行比较,首先必须将它们转换为规范形式。如果 XML 不经常更改,您可以将散列存储在 XML 旁边,然后只比较散列。仅当发生变化时才计算消息摘要。这可能非常快。
另一种解决方案是进行XSLT转换并使用两个 XML 实例作为输入。然后你输出一些更简单的东西(可能是一个包含所有元素和属性名称和值的平面文件),它更容易比较。
有很多方法可以比较 XML文件,正如评论中提到的@violet313,这实际上取决于您要进行比较的原因以及您想要比较的具体内容。
计算哈希值无论如何都需要读取整个文件,并花费 CPU 周期来计算它,所以如果您不担心文件不同但语义相同,为什么不进行逐字节比较呢?
此外,您引用的两个哈希都有问题(MD5 更是如此),如果有人可能有任何动机创建具有相同哈希但不同的文档的任何风险,则不应使用(这对于完全损坏的 MD5 很容易实现)从密码学的角度来看,可能与 SHA1 相距不远)。
基本上你提出的(散列然后比较散列)可能比普通比较慢(除非你从一个真正寻求厌恶的媒体中读取)并且有它自己的问题。那和在 XML 文档的上下文中,您可能需要更高级的方法,因为 Bogdan 几乎把它钉牢了。