11

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

该线程提供了一些很好的建议,但没有什么符合要求。“那好吧,”我想,“我自己搞一个。我是个中庸的开发者,对吧?”。

好吧,一旦我开始考虑它,我就无法完全弄清楚如何去做。我可以很容易地创建一个数据驱动的网站,或者做一个 CMS 实施,或者整天把文档扔进和扔出 BizTalk。无法开始弄清楚如何比较 HTML 文档。

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

因此,既然我已经确定了自己知识的弱点,我将面临更大的挑战来解决这个问题。关于如何开始的任何建议?

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

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

不同的是


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

16 回答 16

2

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

于 2008-09-17T19:54:59.173 回答
2

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

#! /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";
  }
}
于 2008-09-17T20:13:35.150 回答
1

@Mike - 这将比较所有内容,包括页面内容,这不是原始海报想要的。

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

于 2008-09-17T19:54:20.330 回答
1

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

  1. 为 html 页面计划某种 DOM。从轻量级开始,然后根据需要添加更多。我会为数据结构使用复合模式。即每个元素都有基类类型的子集合。
  2. 创建一个解析器来解析 html 页面。
  3. 使用解析器将 html 元素加载到 DOM。
  4. 页面加载到 DOM 后,您将获得 html 页面结构的分层快照。
  5. 继续遍历两边的每个元素,直到 DOM 结束。当您遇到不匹配的元素类型时,您会在结构中找到差异。

在您的示例中,您将仅在一侧加载一个 div 元素对象,在另一侧您将加载一个 div 元素对象,其中加载了 1 个段落元素类型的子元素。启动你的迭代器,首先你将匹配 div 元素,第二个迭代器你将匹配没有任何内容的段落。你有你的结构差异。

于 2008-09-17T20:56:07.280 回答
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 工具。

于 2008-09-18T13:06:29.350 回答
1

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

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

于 2009-06-17T10:14:23.050 回答
1

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

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

于 2010-07-27T09:46:19.370 回答
0

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

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

您会在比较词中发现许多其他复杂的问题。我根据经验说话(我的部分工作是维护我公司的文本比较引擎)。

于 2008-09-20T11:35:13.257 回答
0

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

  • 首先,使用正则表达式工具去除 HTML 文件中的所有文本。您可以使用此正则表达式搜索文本 ( ?<=^|>)[^><]+?(?=<|$) 并将其替换为空字符串 ( ""),即删除所有文本。在此步骤之后,您将拥有所有 HTML 标记标签。有很多免费的正则表达式工具。
  • 然后,对原始 HTML 文件重复第一步。
  • 最后,您使用 diff 工具来比较两组 HTML 标记。这将显示一组和另一组之间缺少什么。
于 2008-09-17T20:01:59.890 回答
0

Pretty Diff 可以做到这一点。它只会比较代码结构,而不考虑空格、注释甚至内容的差异。请务必选中“规范化内容和字符串文字”选项。

http://prettydiff.com/

于 2012-01-06T18:49:16.140 回答
0

这是一个很好的开始。更多澄清/评论:

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

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

于 2008-09-17T20:39:24.387 回答
0

看看比比皆是。它有一个 XML 比较功能,可以帮助您。

于 2009-09-12T08:37:16.517 回答
0

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

<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>
于 2009-09-12T09:01:47.427 回答
0

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

于 2010-03-28T04:50:58.003 回答
-1

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

于 2009-09-12T08:29:40.087 回答
-2

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

于 2008-09-17T19:50:02.523 回答