代码之家  ›  专栏  ›  技术社区  ›  Danimal

关于如何构建html diff工具的建议?

  •  11
  • Danimal  · 技术社区  · 18 年前

    在 this post 我问是否有任何工具可以比较两个html页面的结构(而不是实际内容)。我这样问是因为我从我们的设计人员那里收到了html模板,并且经常在我的实现中遗漏一些小的格式更改。然后,我浪费了几个小时的设计师时间来筛选我的网页,以找出我的错误。

    这条线提出了一些很好的建议,但没有什么符合这项议案。”“那好吧,”我想,“我自己去弄一个。我是个相当不错的开发人员,对吧?”.

    好吧,一旦我开始思考,我就不知道该怎么做了。我可以很容易地创建一个数据驱动的网站,或者进行cms实现,或者整天在biztalk中进出文档。无法开始计算如何比较HTML文档。

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

    所以现在我已经发现了自己知识上的一个弱点,要想弄清楚这一点,我面临着更大的挑战。对如何开始有什么建议吗?

    澄清:实际 内容 不是我想比较的——那些有创造力的人在他们的书页上写满了 乱数假文 ,我使用真正的内容。相反,我想比较一下结构:

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

    不同的是


    <div class="foo">
    <p>lorem ipsum<p>
    <div>
    17 回复  |  直到 10 年前
        1
  •  2
  •   Hank Gay    18 年前

    dom是一个数据结构-它是一棵树。

        2
  •  2
  •   raldi    18 年前

    通过以下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";
      }
    }
    
        3
  •  1
  •   Andy    18 年前

    @迈克-这会比较所有的东西,包括页面的内容,这是不想要的原始海报想要的。

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

        4
  •  1
  •   RWendi    18 年前

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

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

    在您的示例中,一侧将只加载一个div element对象,另一侧将加载一个div element对象,其中包含一个paragraph element类型的子元素。启动迭代器,首先匹配div元素,然后匹配段落。你有你的结构差异。

        5
  •  1
  •   mike    18 年前

    我认为上面的一些建议没有考虑到HTML中两个页面之间的其他标记在文本上是不同的,但是得到的HTML标记在功能上是等价的。danimal以控件id为例。

    以下两个标记在功能上是相同的,但如果您只是比较标记,则会显示为不同:

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

    我打算建议danimal编写一个html翻译,它可以查找html标记,并将这两个文档转换为两个文档的简化版本,其中省略id标记和您指定为不相关的任何其他标记。这可能是一个正在进行的工作,因为您忽略了某些属性/标记,然后遇到了您也希望忽略的新属性/标记。

    但是,我喜欢使用xmlschemanterface将其归结为xml schema的想法,然后使用理解xml规则的diff工具。

        6
  •  1
  •   Ira Baxter    17 年前

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

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

        7
  •  1
  •   Philipp    16 年前

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

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

        8
  •  0
  •   Community Mohan Dere    9 年前
        9
  •  0
  •   Danimal    18 年前

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

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

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

        10
  •  0
  •   RWendi    18 年前

    我的建议只是做这件事的基本方法…当然,为了解决这个问题,你提到的附加规则必须在这里应用…在你的例子中,我们得到了一个匹配的div元素,然后应用属性/属性匹配规则,还有什么不…

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

    在比较词中还有很多其他复杂的问题。我是根据经验说的(我的部分工作是维护我的公司文本比较引擎)。

        11
  •  0
  •   Heiko Hatzfeld    17 年前

    看一看无与伦比的。它有一个xml比较特性,可以帮助您解决这个问题。

        12
  •  0
  •   Nick    17 年前

    您可能还必须考虑“内容”本身可能包含额外的标记,因此可能值得将某些元素(如 <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
  •   austincheney    14 年前

    很难做到。它只会比较代码结构,而不考虑与空白、注释甚至内容的差异。请确保选中“规范化内容和字符串文本”选项。

    http://prettydiff.com/

        14
  •  0
  •   Adrian Frühwirth    10 年前

    我会利用(或贡献) html5lib 以及它的sax输出。只需在2个sax流中寻找不匹配项并突出显示整个对应的子树。

        15
  •  0
  •   Adrian Frühwirth    10 年前

    我不知道什么工具,但我知道有一个简单的方法:

    • 首先,使用正则表达式工具去除html文件中的所有文本。可以使用此正则表达式搜索文本( ?<=^|>)[^><]+?(?=<|$ )用空字符串替换它们( "" ),即删除所有文本。在这一步之后,您将拥有所有的html标记标记。有很多免费的正则表达式工具。
    • 然后,对原始html文件重复第一步。
    • 最后,使用diff工具比较两组html标记。这将显示一组和另一组之间缺少什么。
        16
  •  -1
  •   RCIX    17 年前

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

        17
  •  -2
  •   Mike    18 年前

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

    推荐文章