关于如何构建HTML Diff工具的建议?

时间:2008-09-17 19:48:20

标签: c# html dom diff

this post中我询问是否有任何工具可以比较2个HTML页面的结构(而非实际内容)。我问,因为我从设计师那里收到HTML模板,并经常错过我的实现中的次要格式更改。然后我浪费了几个小时的设计师时间筛选我的页面来发现我的错误。

该主题提供了一些很好的建议,但没有任何东西适合该法案。 “好吧,然后”,我想,“我只是自己动摇一下。我是一个不太合适的开发者,对吧?”。

好吧,一旦我开始思考它,我就无法弄清楚如何去做。我可以轻松地创建一个数据驱动的网站,或者进行CMS实施,或者整天将文档放入和放出BizTalk。无法开始弄清楚如何比较HTML文档。

嗯,当然,我必须阅读DOM,并遍历节点。我必须将结构映射到一些数据结构(如何??),然后比较它们(如何??)。这是一项我从未尝试过的开发任务。

所以现在我已经发现了我的知识中的一个弱点,我更难以弄明白这一点。关于如何开始的任何建议?

澄清:实际的内容不是我想要比较的 - 创意人用 lorem ipsum 填充他们的页面,我使用真实的内容。相反,我想比较结构:

<div class="foo">lorem ipsum<div>

不同


<div class="foo">
<p>lorem ipsum<p>
<div>

17 个答案:

答案 0 :(得分:2)

DOM是一种数据结构 - 它是一棵树。

答案 1 :(得分:2)

通过以下Perl脚本运行这两个文件,然后使用diff -iw执行不区分大小写,忽略空格的差异。

#! /usr/bin/perl -w

use strict;

undef $/;

my $html = <STDIN>;

while ($html =~ /\S/) {
  if ($html =~ s/^\s*<//) {
    $html =~ s/^(.*?)>// or die "malformed HTML";
    print "<$1>\n";
  } else {
    $html =~ s/^([^<]+)//;
    print "(text)\n";
  }
}

答案 2 :(得分:1)

@Mike - 可以比较所有内容,包括页面内容,这不是原版海报所需要的。

假设您可以访问浏览器的DOM(通过编写Firefox / IE插件或其他内容),我可能会将所有HTML元素放入树中,然后比较两棵树。如果标记名称不同,则节点不同。你可能想要在某一点停止枚举(你可能不关心span,粗体,斜体等等 - 也许只关心div?),因为有些标签实际上是内容,而不是结构,页。

答案 3 :(得分:1)

http://www.mugo.ca/Products/Dom-Diff

适用于FF 3.5。我还没有测试过FF 3.6。

答案 4 :(得分:1)

有关由langauge语法参数化的工具,请参阅http://www.semdesigns.com/Products/SmartDifferencer/index.html,并根据插入,删除,移动,替换的语言元素(标识符,表达式,语句,块,方法等)生成增量,或者标识符一致地替换它。该工具忽略空白重新格式化(例如,不同的换行符或布局)和语义上不可区分的值(例如,它知道0x0F和15是相同的值)。 这可以使用HTML解析器应用于HTML。

编辑:9/12/2009。我们使用HTML编辑器构建了一个实验性SmartDiff工具。

答案 5 :(得分:1)

我认为上面的一些建议没有考虑到两个页面之间的HTML中存在其他文本不同的标记,但生成的HTML标记在功能上是等效的。 Danimal列出控件ID作为示例。

以下两个标记功能完全相同,但如果您只是比较标记,它们会显示为不同:

<div id="ctl00_TopNavHome_DivHeader" class="header4">foo</div>
<div class="header4">foo</div>

我打算建议Danimal编写HTML翻译,查找HTML标签并将两个文档转换为两者的简化版本,这些版本会省略ID标签和您指定为无关的任何其他标签。这可能必须是一项正在进行的工作,因为您忽略了某些属性/标签,然后遇到了您也想忽略的新属性/标签。

但是,我喜欢使用XmlSchemaInterface将其简化为XML模式,然后使用了解XML规则的diff工具。

答案 6 :(得分:1)

如果我要解决这个问题,我会这样做:

  1. 为html页面规划某种DOM。从轻量级开始,然后根据需要添加更多。我会使用复合模式的数据结构。即每个元素都有基类类型的子集合。
  2. 创建解析器来解析html页面。
  3. 使用解析器将html元素加载到DOM。
  4. 在将页面加载到DOM之后,您将获得html页面结构的层次快照。
  5. 继续遍历两侧的每个元素,直到DOM结束。当你遇到不匹配的元素类型时,你会在结构中找到差异。
  6. 在您的示例中,您将只在一侧加载div元素对象,在另一侧,您将有一个div元素对象加载1个子元素类型为paragraph元素。启动你的迭代器,首先你将匹配div元素,第二个迭代器你将匹配段落什么都没有。你有结构上的差异。

答案 7 :(得分:0)

这是一个很好的开始。还有一些澄清/评论:

  • 我可能不关心ID,因为.net会破坏它们
  • 某些结构将在转发器或其他此类控件中,因此我可能最终会有更多或更少的重复元素

进一步思考: 我认为一个好的开始是假设html符合XHTML。然后我可以推断出架构(使用新的.net XmlSchemaInference方法),然后对架构进行区分。然后,我可以看看差异,并考虑它们是否重要。

答案 8 :(得分:0)

我不知道任何工具,但我知道有一种简单的方法可以做到这一点:

  • 首先,使用正则表达式工具去除HTML文件中的所有文本。您可以使用此正则表达式搜索文本(?<=^|>)[^><]+?(?=<|$)并将其替换为空字符串(""),即删除所有文本。完成此步骤后,您将拥有所有HTML标记标记。那里有很多免费的正则表达式工具。
  • 然后,重复原始HTML文件的第一步。
  • 最后,使用diff工具比较两组HTML标记。这将显示一组与另一组之间缺少的内容。

答案 9 :(得分:0)

我的建议只是这样做的基本方法......当然要解决你提到的问题,你必须在这里应用其他规则......在你的情况下,我们得到一个匹配的div元素,然后应用属性/属性匹配规则和什么不...

说实话,有许多复杂的规则需要应用于比较,而不仅仅是与另一个元素的简单匹配元素。例如,如果您有重复项会发生什么。 例如一侧有1个div元素,另一侧有2个div元素。你将如何匹配哪些div元素匹配?

您会在比较字中找到很多其他复杂的问题。我根据经验说话(我的工作的一部分是保持我的公司文本比较引擎)。

答案 10 :(得分:0)

答案 11 :(得分:0)

看看超越比较。它具有XML比较功能,可以帮助您。

答案 12 :(得分:0)

您可能还必须考虑“内容”本身可能包含额外的标记,因此在进行比较之前,可能需要删除某些元素中的所有内容(例如具有特定ID或类的<div>) 。例如:

<div id="mainContent">
<p>lorem ipsum etc..</p>
</div>

<div id="mainContent">
<p>Here is some real content<img class="someImage" src="someImage.jpg" /></p>
<ul>
<li>and</li>
<li>some</li>
<li>more..</li>
</ul>
</div>

答案 13 :(得分:0)

我会使用(或贡献)html5lib及其SAX输出。只需压缩2个SAX流,寻找不匹配的内容,并突出显示整个相应的子树。

答案 14 :(得分:0)

Pretty Diff可以做到这一点。它将仅比较代码结构,无论与空格,注释甚至内容的差异如何。请务必选中“规范内容和字符串文字”选项。

http://prettydiff.com/

答案 15 :(得分:-1)

如果我这样做,首先我会学习HTML。 (^ - ^)然后我会构建一个剥离所有实际内容的工具,然后将其保存为文件,以便通过WinDiff(或其他合并工具)进行管道传输。

答案 16 :(得分:-2)

在浏览器中打开每个页面并将其另存为.htm文件。比较两个使用windiff。