关于如何构建HTML Diff工具的建议?
在这篇文章中,我询问是否有任何工具可以比较2个HTML页面的结构(而不是实际内容)。 我问,因为我从设计师那里收到了HTML模板,并经常错过我的实现中的次要格式更改。 然后我浪费了几个小时的设计师时间筛选我的页面来发现我的错误。
该主题提供了一些很好的建议,但没有任何东西适合该法案。 “好吧,然后”,我想,“我只是自己动摇一下。我是一个不太合适的开发者,对吗?”
好吧,一旦我开始思考它,我就无法弄清楚如何去做。 我可以轻松地创建一个数据驱动的网站,或者进行CMS实施,或者整天将文档放入和放出BizTalk。 无法开始弄清楚如何比较HTML文档。
嗯,当然,我必须阅读DOM,并遍历节点。 我必须将结构映射到一些数据结构(如何??),然后比较它们(如何??)。 这是一项我从未尝试过的开发任务。
所以,既然我已经发现了自己的知识上的弱点,那我就更难以解决这个问题。 有关如何入门的任何建议?
澄清:实际内容不是我想要比较的 – 创意人用lorem ipsum填充他们的页面,我使用真实的内容。 相反,我想比较结构:
lorem ipsum与众不同
lorem ipsum
DOM是一种数据结构 – 它是一棵树。
通过以下Perl脚本运行这两个文件,然后使用diff -iw执行不区分大小写,忽略空格的diff。
#! /usr/bin/perl -w use strict; undef $/; my $html =
; while ($html =~ /\S/) { if ($html =~ s/^\s*/) { $html =~ s/^(.*?)>// or die "malformed HTML"; print "<$1>\n"; } else { $html =~ s/^([^<]+)//; print "(text)\n"; } } @Mike – 这将比较一切,包括页面的内容,这是不希望原始海报想要的。
假设您可以访问浏览器的DOM(通过编写Firefox / IE插件或其他内容),我可能会将所有HTML元素放入树中,然后比较两棵树。 如果标签名称不同,则节点不同。 您可能想要在某一点停止枚举(您可能不关心span,粗体,斜体等等 – 可能只关心div?),因为有些标签实际上是内容,而不是结构,页。
如果我要解决这个问题,我会这样做:
- 为html页面规划某种DOM。 从轻量级开始,然后根据需要添加更多。 我会使用复合模式作为数据结构。 即每个元素都有基类类型的子集合。
- 创建解析器来解析html页面。
- 使用解析器将html元素加载到DOM。
- 页面加载到DOM后,您将获得html页面结构的层次快照。
- 继续遍历两侧的每个元素,直到DOM结束。 当你遇到不匹配的元素类型时,你会在结构中找到差异。
在您的示例中,您将只在一侧加载div元素对象,在另一侧,您将有一个div元素对象加载1个子元素类型为paragraph元素。 启动你的迭代器,首先你将匹配div元素,第二个迭代器你将匹配段落什么都没有。 你有结构上的差异。
我认为上面的一些建议没有考虑到两个页面之间的HTML中存在其他文本不同的标记,但生成的HTML标记在function上是等效的。 Danimal列出控件ID作为示例。
以下两个标记function完全相同,但如果您只是比较标记,则会显示为不同:
foo我打算建议Danimal编写HTML翻译,查找HTML标签,并将两个文档转换为两者的简化版本,省略ID标签和您指定为无关的任何其他标签。 这可能必须是一项正在进行的工作,因为您忽略了某些属性/标签,然后遇到了您也想忽略的新属性/标签。
但是,我喜欢使用XmlSchemaInterface将其简化为XML模式,然后使用了解XML规则的diff工具。
有关由langauge语法参数化的工具,请参阅http://www.semdesigns.com/Products/SmartDifferencer/index.html ,并根据语言元素(标识符,表达式,语句,块,方法等)生成增量。插入,删除,移动,替换或标识符一致地替换它。 此工具忽略空格重新格式化(例如,不同的换行符或布局)和语义上无法区分的值(例如,它知道0x0F和15是相同的值)。 这可以使用HTML解析器应用于HTML。
编辑:9/12/2009。 我们使用HTML编辑器构建了一个实验性的SmartDiff工具。
http://www.mugo.ca/Products/Dom-Diff
适用于FF 3.5。 我还没有测试过FF 3.6。
请参阅此前的post和随附的答案 。
这是一个很好的开始。 还有一些澄清/评论:
- 我可能不关心ID,因为.net会破坏它们
- 一些结构将在转发器或其他此类控件中,因此我可能最终会有更多或更少的重复元素
进一步思考:我认为一个好的开始是假设html符合XHTML。 然后,我可以推断出模式(使用新的.net XmlSchemaInference方法),然后区分模式。 然后,我可以看看差异,并考虑它们是否重要。
我的建议只是这样做的基本方法……当然要解决你提到的问题,你必须在这里应用其他规则……在你的情况下,我们得到一个匹配的div元素,然后应用属性/属性匹配规则,什么不……
说实话,有许多复杂的规则需要应用于比较,而不仅仅是与另一个元素的简单匹配元素。 例如,如果您有重复项会发生什么。 例如,一侧为1 div元素,另一侧为2 div元素。 你将如何匹配哪些div元素匹配在一起?
你会在比较词中找到很多其他复杂的问题。 我根据经验说话(我的工作的一部分是保持我的公司文本比较引擎)。
看看超越比较。 它具有XML比较function,可以帮助您。
您可能还必须考虑“内容”本身可能包含额外的标记,因此在进行比较之前,可能需要删除某些元素中的所有内容(例如具有特定ID或类的
)。 例如:
lorem ipsum etc..
和
Here is some real content
- and
- some
- more..
Pretty Diff可以做到这一点。 它将仅比较代码结构,无论与空格,注释甚至内容的差异如何。 请务必选中“规范内容和字符串文字”选项。
我会使用(或贡献)
html5lib
及其SAX输出。 只需压缩2个SAX流即可查找不匹配项,并突出显示整个相应的子树。我不知道任何工具,但我知道有一个简单的方法可以做到这一点:
- 首先,使用正则表达式工具去除HTML文件中的所有文本。 您可以使用此正则表达式搜索文本(
?<=^|>)[^><]+?(?=<|$
)并将其替换为空字符串(""
),即删除所有文本。 完成此步骤后,您将拥有所有HTML标记标记。 那里有很多免费的正则表达式工具。- 然后,重复原始HTML文件的第一步。
- 最后,使用diff工具比较两组HTML标记。 这将显示一组与另一组之间缺少的内容。
如果我这样做,首先我会学习HTML。 (^ – ^)然后,我将构建一个工具,剥离所有实际内容,然后将其保存为文件,以便它可以通过WinDiff(或其他合并工具)进行管道传输。
在浏览器中打开每个页面并将其另存为.htm文件。 比较两个使用windiff。