有关如何构建HTML Diff工具的建议?
在这篇文章中,我问是否有任何工具可以比较2个HTML页面的结构(不是实际内容)。我之所以这样问,是因为我从设计人员那里收到了HTML模板,并且经常错过实现中的细微格式更改。然后,我浪费了数小时的设计人员时间来浏览我的页面以查找错误。
该主题提供了一些很好的建议,但没有合适的建议。 "那么好吧,"我想,"我要自己动手。我是一个中等的开发人员,对吧?"
好吧,一旦我开始考虑它,我就不知道该怎么做。我可以很容易地创建一个数据驱动的网站,或者执行CMS实施,或者整天将文档丢入BizTalk或者从中丢出。无法开始弄清楚如何比较HTML文档。
好吧,当然,我必须阅读DOM并遍历节点。我必须将结构映射到某些数据结构(如何使用),然后将它们进行比较(如何使用)。这是我从未尝试过的开发任务。
因此,既然我已经确定了自己的知识上的弱点,那么要弄清这一点我就面临更大的挑战。有关如何入门的任何建议?
澄清:实际的内容不是我想要比较的-富有创造力的人用lorem ipsum填充他们的页面,而我使用真实的内容。相反,我想比较一下结构:
<div class="foo">lorem ipsum<div>
不同的是
<div class="foo"> <p>lorem ipsum<p> <div>
解决方案
回答
在浏览器中打开每个页面,并将它们另存为.htm文件。使用windiff比较两个。
回答
@Mike会比较所有内容,包括页面的内容,这是原始海报所不想要的。
假设我们有权访问浏览器的DOM(通过编写Firefox / IE插件或者其他工具),我可能会将所有HTML元素放入一棵树中,然后将两棵树进行比较。如果标签名称不同,则节点也不同。我们可能要在某个点停止枚举(我们可能不关心跨度,粗体,斜体等,也许只担心div?),因为某些标签实际上是页面的内容而不是结构。
回答
DOM是一个数据结构,它是一棵树。
回答
请参阅此以前的帖子和随附的答案。
回答
我不知道任何工具,但是我知道有一种简单的方法可以做到这一点:
- 首先,使用正则表达式工具删除HTML文件中的所有文本。我们可以使用此正则表达式搜索文本(
?<= ^ |>)[^> <] +?(?= <| $
)并将其替换为空字符串(""
),即删除所有文本。完成此步骤后,我们将拥有所有HTML标记标签。有很多免费的正则表达式工具。 - 然后,对原始HTML文件重复第一步。
- 最后,我们使用差异工具比较两组HTML标记。这将显示一组和另一组之间缺少的内容。
回答
通过以下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 "<>\n"; } else { $html =~ s/^([^<]+)//; print "(text)\n"; } }
回答
这是一个很好的开始。其他一些说明/意见:
- 我可能不在乎ID,因为.net会破坏它们
- 一些结构将在转发器或者其他类似控件中,因此我可能最终会拥有更多或者更少的重复元素
进一步思考:
我认为一个好的开始是假设html符合XHTML。然后,我可以推断出架构(使用新的.net XmlSchemaInference方法),然后比较架构。然后,我可以查看差异并考虑它们是否重要。
回答
如果我要解决这个问题,我会这样做:
- 为html页面计划某种DOM。从轻量级开始,然后根据需要添加更多内容。我将对数据结构使用复合模式。也就是说,每个元素都有基类类型的子级集合。
- 创建一个解析器来解析html页面。
- 使用解析器将html元素加载到DOM。
- 将页面加载到DOM之后,我们将获得html页面结构的层级快照。
- 不断迭代两侧的每个元素,直到DOM结束。当我们遇到元素类型不匹配的情况时,我们将在结构中找到差异。
在示例中,我们将只在一侧加载div元素对象,在另一侧,我们将加载div元素对象,该div对象对象带有1个段落元素类型的子元素。启动迭代器,首先将div元素匹配,第二个迭代器将段落完全匹配。我们在结构上有所不同。
回答
我认为上面的一些建议没有考虑到两个页面之间的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工具。
回答
我的建议只是执行此操作的基本方法...当然,要解决我们提到的问题,必须在此处应用其他规则...在情况下,我们得到了一个匹配的div元素,然后应用属性/属性匹配规则,还有什么...
坦白地说,有许多复杂的规则需要应用到比较中,而不仅仅是将其简单匹配到另一个元素。例如,如果重复,会发生什么。
例如一侧为1 div元素,另一侧为2 div元素。我们如何匹配哪些div元素匹配在一起?
在比较词中还会发现很多其他复杂的问题。我的演讲基于经验(我的工作之一是维护公司的文字比较引擎)。
回答
请参阅http://www.semdesigns.com/Products/SmartDifferencer/index.html,以了解由langauge语法参数化的工具,并根据语言元素(标识符,表达式,语句,块,方法等)产生增量。 )插入,删除,移动,替换,或者标识符始终被替换。此工具会忽略空格重新格式化(例如,不同的换行符或者布局)以及语义上无法区分的值(例如,它知道0x0F和15是相同的值)。
可以使用HTML解析器将其应用于HTML。
编辑:2009年9月12日。我们已经使用HTML编辑器构建了一个实验性的SmartDiff工具。
回答
如果我要这样做,首先我会学习HTML。 (^-^)然后,我将构建一个工具,该工具将去除所有实际内容,然后将其另存为文件,以便可以通过WinDiff(或者其他合并工具)通过管道进行传输。
回答
看看无与伦比的。它具有XML比较功能,可以为我们提供帮助。
回答
我们可能还必须考虑到"内容"本身可能包含其他标记,因此在进行比较之前,有必要去除某些元素(例如带有特定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>
回答
我会使用(或者贡献)" html5lib"及其SAX输出。只需浏览2个SAX流以查找不匹配项,然后突出显示整个相应的子树。
回答
http://www.mugo.ca/Products/Dom-Diff
适用于FF 3.5. 我尚未测试FF 3.6.