Предложения о том, как создать инструмент HTML Diff?

В этот пост Я спросил, есть ли какие-либо инструменты, которые сравнивают структуру (а не фактическое содержимое) из двух HTML-страниц. Я спрашиваю, потому что я получаю HTML-шаблоны от наших дизайнеров и часто пропускаю незначительные изменения форматирования в моей реализации. Затем я трачу несколько часов дизайнерского времени на прохождение моих страниц, чтобы найти свои ошибки.

Тема предложила несколько хороших предложений, но ничего не соответствовало законопроекту. "Прекрасно, тогда", подумал я, "я просто провожу кого-то из себя. Я прилежный разработчик, верно?".

Хорошо, как только я начал думать об этом, я не мог понять, как это сделать. Я могу легко прокрутить управляемый данными веб-сайт или выполнить CMS или бросить документы в BizTalk и весь день. Не могу понять, как сравнивать документы HTML.

Ну, конечно, я должен прочитать DOM и перебрать узлы. Мне нужно сопоставить структуру с некоторой структурой данных (как?), А затем сравнить их (как?). Это задача разработки, как никто из моих попыток.

Итак, теперь, когда я обнаружил слабость в своих знаниях, мне еще более сложно понять это. Любые предложения о том, как начать работу?

пояснение: фактический контент - это не то, что я хочу сравнить - креативные парни заполняют свои страницы lorem ipsum, и я использую реальный контент. Вместо этого я хочу сравнить структуру:

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

отличается тем, что


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

Ответ 1

DOM - это структура данных - это дерево.

Ответ 2

Запустите оба файла с помощью следующего Perl script, затем используйте 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 в дерево, а затем сравнил два дерева. Если имя тега отличается, то node отличается. Возможно, вам захочется прекратить перечисление в определенный момент (возможно, вам небезразличен диапазон, полужирный, курсив и т.д. - может быть, только беспокоиться о divs?), Поскольку некоторые теги - это действительно контент, а не структура, стр.

Ответ 4

Если бы я решил эту проблему, я бы сделал следующее:

  • Планируйте какой-либо DOM для html-страниц. начинается с легкого веса, а затем добавляет больше по мере необходимости. Я бы использовал составную структуру для структуры данных. то есть каждый элемент имеет дочернюю совокупность типа базового класса.
  • Создайте парсер для разбора html-страниц.
  • Использование элемента hsml загрузки парсера для DOM.
  • После того, как страницы были загружены в DOM, у вас есть иерархический снимок структуры html-страниц.
  • Продолжайте повторять все элементы с обеих сторон до конца DOM. Вы обнаружите diff в структуре, когда вы нажмете несоответствие типа элемента.

В вашем примере у вас будет только объект элемента div, загруженный с одной стороны, с другой стороны у вас будет объект div-элемента, загруженный 1 дочерним элементом элемента абзаца типа. запустите свой итератор, сначала вы сравните элемент div, второй итератор, который вы соедините с абзацем ни с чем. У вас есть свои структурные различия.

Ответ 5

Я думаю, что некоторые из приведенных выше предложений не учитывают, что в HTML есть другие теги между двумя страницами, которые были бы текстовыми, но получающаяся разметка HTML функционально эквивалентна. В качестве примера перечислены контрольные идентификаторы Danimal.

Следующие две разметки функционально идентичны, но будут отображаться как разные, если вы просто сравнили теги:

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

Я собирался предложить Danimal написать HTML-перевод, который ищет HTML-теги и преобразует оба документа в упрощенную версию обоих, которые не пропускают теги идентификаторов и любые другие теги, которые вы обозначаете как несущественные. Это, вероятно, должно быть незавершенным, поскольку вы игнорируете определенные атрибуты/теги, а затем запускаете новые, которые вы также хотите игнорировать.

Однако мне нравится идея использования XmlSchemaInterface, чтобы свернуть ее до XML-схемы, а затем использовать инструмент diff, который понимает правила XML.

Ответ 6

См. http://www.semdesigns.com/Products/SmartDifferencer/index.html для инструмента, который параметризуется грамматикой langauge и производит дельта в терминах элементов языка (идентификаторы, выражения, операторы, блоки, методы,...) вставлены, удалены, перемещены, заменены или имеют одинаковые идентификаторы. Этот инструмент игнорирует переформатирование в виде пробелов (например, различные разрывы строк или макеты) и семантически неотличимые значения (например, он знает, что 0x0F и 15 являются одинаковым значением). Это можно применить к HTML, используя парсер HTML.

EDIT: 9/12/2009. Мы создали экспериментальный инструмент SmartDiff с помощью HTML-редактора.

Ответ 9

Я не знаю никакого инструмента, но я знаю, что есть простой способ сделать это:

  • Сначала используйте инструмент регулярного выражения, чтобы удалить весь текст в вашем HTML файле. Вы можете использовать это регулярное выражение для поиска текста (?<=^|>)[^><]+?(?=<|$) и заменить их пустой строкой (""), т.е. Удалить весь текст. После этого шага вы будете иметь все теги разметки HTML. Там есть много бесплатных инструментов регулярного выражения.
  • Затем вы повторяете первый шаг для исходного HTML файла.
  • Наконец, вы используете инструмент diff для сравнения двух наборов разметки HTML. Это покажет, что отсутствует между одним набором и другим.

Ответ 10

Это был отличный старт. Еще несколько пояснений/комментариев:

  • Мне, вероятно, не нужны идентификаторы, так как .net будет калечить их
  • какая-то структура будет в ретрансляторе или другом таком контроле, так что я могу в итоге получить больше или меньше повторяющихся элементов

подумал: Я думаю, что хорошим началом было бы предположить, что html соответствует XHTML. Затем я мог бы вывести схему (используя новые методы .net XmlSchemaInference), а затем разобрать схемы. Затем я могу разобраться в различиях и подумать, важны они или нет.

Ответ 11

Мое предложение - это просто основной способ сделать это... Конечно, чтобы решить проблему, о которой вы говорили, здесь должны применяться дополнительные правила... Что в вашем случае, мы получили соответствующий элемент div, а затем применяем атрибуты/правила сопоставления свойств, а что нет...

Честно говоря, существует множество и сложных правил, которые необходимо применять для сравнения, а также не только простой элемент соответствия для другого элемента. Например, что произойдет, если у вас есть дубликаты. например 1 div с одной стороны и 2 div-элемента на другой стороне. Как вы собираетесь совпадать с элементами div?

Есть и другие сложные проблемы, которые вы найдете в слове сравнения. Я говорю на основе опыта (часть моей работы заключается в том, чтобы maitain механизм сравнения текста моей компании).

Ответ 12

Взгляните на сравнение. Он имеет функцию сравнения XML, которая может помочь вам.

Ответ 13

Возможно, вам также придется учитывать, что сам "контент" может содержать дополнительную надбавку, поэтому, прежде чем выполнять сравнение, вам, возможно, стоит выделить все в определенных элементах (например, <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>

Ответ 14

Я бы использовал (или вносил вклад) в html5lib и его SAX-выход. Просто запустите через 2 потока SAX, ищите несоответствия и выделите все соответствующие поддеревы.

Ответ 15

Pretty Diff может это сделать. Он будет сравнивать структуру кода только независимо от различий с пробелами, комментариями или даже содержанием. Просто не забудьте проверить параметр "Нормализовать содержимое и литералы струн".

http://prettydiff.com/

Ответ 16

Если бы я сделал это, сначала я бы изучил HTML. (^ - ^) Тогда я бы построил инструмент, который удаляет все фактическое содержимое, а затем сохраняет это как файл, чтобы он мог быть передан через WinDiff (или другой инструмент слияния).

Ответ 17

Откройте каждую страницу в браузере и сохраните их как .htm файлы. Сравните их с использованием windiff.