【问题标题】:Suggestions on how build an HTML Diff tool?关于如何构建 HTML Diff 工具的建议?
【发布时间】:2008-09-17 19:48:19
【问题描述】:

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

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

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

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

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

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

lorem ipsum

不一样



lorem ipsum


【问题讨论】:

    标签: c# html dom diff


    【解决方案1】:

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

    【讨论】:

      【解决方案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";
        }
      }
      

      【讨论】:

      • 这实际上是我会做的。它将两个文件简化为它们的基本元素,规范化您不关心的内容(在本例中为文本),然后利用现成的工具进行实际工作。
      【解决方案3】:

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

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

      【讨论】:

      • 不过,任何结构上的差异都会显示在风中。我想这会更难修复。
      • 确实如此。我想我只是假设 OP 希望能够隐藏/忽略页面的内容,以便更容易看到结构中的差异。
      【解决方案4】:

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

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

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

      【讨论】:

        【解决方案5】:

        我认为上面的一些建议没有考虑到两个页面之间的 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 工具。

        【讨论】:

          【解决方案6】:

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

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

          【讨论】:

            【解决方案7】:

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

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

            【讨论】:

              【解决方案8】:

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

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

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

              【讨论】:

                【解决方案9】:

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

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

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

                【讨论】:

                  【解决方案10】:

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

                  【讨论】:

                    【解决方案11】:

                    您可能还必须考虑“内容”本身可能包含额外的标记,因此在进行比较之前,可能值得去除某些元素中的所有内容(例如具有某些 ID 或类的&lt;div&gt;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>
                    

                    【讨论】:

                      【解决方案12】:

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

                      http://prettydiff.com/

                      【讨论】:

                        【解决方案13】:

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

                        【讨论】:

                          【解决方案14】:

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

                          • 首先,使用正则表达式工具去除 HTML 文件中的所有文本。您可以使用此正则表达式搜索文本 (?&lt;=^|&gt;)[^&gt;&lt;]+?(?=&lt;|$) 并将其替换为空字符串 (""),即删除所有文本。在此步骤之后,您将拥有所有 HTML 标记标签。市面上有很多免费的正则表达式工具。
                          • 然后,对原始 HTML 文件重复第一步。
                          • 最后,您使用差异工具来比较两组 HTML 标记。这将显示一组与另一组之间缺少的内容。

                          【讨论】:

                            【解决方案15】:

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

                            【讨论】:

                              【解决方案16】:

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

                              【讨论】:

                              • 我认为 OP 的问题是他在页面中添加了内容,并且在此过程中可能不小心更改了一些标记。因此,当他想要的只是标记差异时,差异会将所有内容视为差异。
                              猜你喜欢
                              • 2012-05-04
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 2011-01-19
                              • 1970-01-01
                              • 2012-09-20
                              • 1970-01-01
                              • 1970-01-01
                              相关资源
                              最近更新 更多