2008-09-17 112 views
11

this post我问是否有任何工具比较2个HTML页面的结构(不是实际内容)。我问,因为我收到来自我们的设计师的HTML模板,并经常错过我的实现中的小的格式更改。然后,我浪费了几个小时的设计师时间筛选我的页面,以查找我的错误。关于如何构建HTML Diff工具的建议?

该主题提供了一些很好的建议,但没有什么符合该法案。 “好吧,那么”,我想,“我会自己动手一个,我是一个中等体面的开发者,对吧?”

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

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

所以现在我已经发现了我的知识中的一个弱点,我更加想要解决这个问题。有关如何开始的任何建议?

澄清:实际内容是不是我想要的比较 - 创造性的球员填补他们的页面与 Lorem存有,我用真正的内容。相反,我想比较结构:

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

不同的是

 

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

回答

-2

打开浏览器中的每一页,并将其保存为.htm文件。比较两个使用windiff。

+0

我觉得OP的问题是,他已经添加内容到页面,在这个过程中可能会意外地改变了一些标记。所以当他想要的是标记差异时,差异会将所有内容视为差异。 – EBGreen 2008-09-17 19:51:49

1

@Mike - 这将比较一切,包括页面的内容,这是不希望的原始海报通缉。

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

+0

虽然任何结构性差异都会出现在windiff中。我认为这会更难解决。 – Mike 2008-09-17 19:56:55

+0

的确如此。我想我只是假设OP希望能够隐藏/忽略页面内容,以便更容易地看到结构的差异。 – Andy 2008-09-17 23:43:03

2

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

0

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

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

这实际上是我会做的。它将这两个文件缩减为其基本元素,将您不关心的内容(本例中的文本)规范化,然后利用现成的工具进行实际工作。 – 2008-09-22 02:21:19

0

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

  • 我可能不关心的ID,因为.NET会损坏它们
  • 一些结构将是一个中继器或其他这样的控制,所以我可能最终不得不更多或更少的重复元素

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

1

如果我是TACKE这个问题,我会做到这一点:

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

在你的例子中,你只能在一边加载一个div元素对象,另一方面你会有一个div元素对象加载1个子元素类型为paragraph元素。激发你的迭代器,首先你会匹配div元素,第二个迭代器,你会匹配段没有。你有你的结构差异。

1

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

以下两个标记是functionlly相同,但会出现,如果你只是比较标签不同:

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

我要建议Danimal编写一个HTML转换看起来对HTML标签和转换都docs转化为两者的简化版本,省略ID标签和您指定为不相关的任何其他标签。这可能必须是一个正在进行的工作,因为您忽略了某些属性/标签,然后运行到您也不想忽略的新属性。然而,我喜欢使用XmlSchemaInterface将其归结为XML模式,然后使用了解XML规则的diff工具。

0

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

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

还有很多其他复杂的问题,你会发现比较词。我根据经验说话(我的工作的一部分是保持我的公司文本比较引擎)。

1

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

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

-1

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

0

看看超越比较。它有一个XML比较功能,可以帮助你。

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> 
0

我会使用(或向)html5lib及其SAX输出。只需通过2个SAX流查找不匹配,并突出显示整个相应的子树。

0

Pretty Diff可以做到这一点。它只会比较代码结构,而不考虑空白区域,评论甚至内容的差异。只需确保选中“Normalize Content and String Literals”。

http://prettydiff.com/