如何构建一个HTML Diff工具的建议?

11
这篇文章中,我问是否有工具可以比较两个HTML页面的结构(而不是实际内容)。我之所以问,是因为我们的设计师给我提供了HTML模板,但我在实现时经常错过一些微小的格式更改。然后我就要花费几个小时的设计师时间来查找我的错误。
这个帖子中提供了一些好的建议,但没有符合要求的工具。我想:“那好吧,我就自己写一个。我是一个还算不错的开发者,对吧?”
当我开始思考它时,我无法完全弄清楚该怎么做。我可以轻易地创建一个数据驱动的网站,或者进行CMS实现,或者整天在BizTalk中插入和删除文档,但无法开始比较HTML文档。
好吧,我必须读取DOM,并迭代节点。我必须将结构映射到某个数据结构中(如何?),然后进行比较(如何?)。这是我从未尝试过的开发任务。
既然我已经确定了自己知识上的缺点,我更加有挑战性地去解决它。有关如何入手的建议吗?
澄清一下:我不想比较实际的内容——创意人员用lorem ipsum填充他们的页面,而我使用真实的内容。相反,我想比较结构:
16个回答

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";
  }
}

这实际上是我会做的事情。它将两个文件简化为它们的基本元素,规范化您不关心的内容(在这种情况下是文本),然后利用现成的工具进行真正的工作。 - Will Hartung

2

DOM是一种数据结构,它是一颗树形结构。


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 规则的差异工具。


1

1
请参考http://www.semdesigns.com/Products/SmartDifferencer/index.html,这是一款由语言语法参数化的工具,它可以生成关于语言元素(标识符、表达式、语句、块、方法等)插入、删除、移动、替换或在其中一致地替换标识符的增量。该工具忽略空格重排(例如,不同的换行符或布局)和语义上无法区分的值(例如,它知道0x0F和15是相同的值)。这可以应用于使用HTML解析器的HTML。
编辑:2009年9月12日。我们已经使用HTML编辑器构建了一个实验性的SmartDiff工具。

1

@Mike - 那会比较所有东西,包括页面的内容,而不是原帖想要的。

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


任何结构上的差异都会在 Windiff 中显示出来。我想修复起来可能会更困难。 - Mike
没错。我想我只是假设OP想要隐藏/忽略页面的内容,以便更容易地看到结构上的差异。 - Andy

1
如果我要解决这个问题,我会这样做:
  1. 为 HTML 页面计划某种 DOM 结构。从轻量级开始,根据需要增加更多内容。我会使用组合模式来构建数据结构,即每个元素都有基类类型的子元素集合。
  2. 创建一个解析器来解析 HTML 页面。
  3. 使用解析器将 HTML 元素加载到 DOM 中。
  4. 在页面加载到 DOM 后,您就可以获得 HTML 页面结构的层次快照。
  5. 持续迭代两侧的每个元素,直到 DOM 的末尾。当您遇到元素类型不匹配时,就会发现它们之间的差异。

以您的示例为例,您只加载了一个 div 元素对象,在另一侧,您加载了一个带有 1 个段落元素子元素的 div 元素对象。启动迭代器,首先匹配 div 元素,第二个迭代器将无法匹配段落。您已经找到了结构上的差异。


0
你还需要考虑到 'content' 本身可能包含其他标记,所以在进行比较之前最好先去除特定元素(如具有特定ID或类的
)中的所有内容。例如:
<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>

0

我会使用(或贡献于)html5lib及其SAX输出。只需快速浏览两个SAX流,查找不匹配项并突出显示整个相应的子树。


0

看看Beyond Compare吧。它有一个XML比较功能,可以帮助你解决问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接