Предложения по созданию инструмента HTML Diff?

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

Тема предлагала несколько хороших предложений, но не было ничего, что отвечало бы всем требованиям. «Хорошо, тогда, — подумал я, — я просто сам прокачаю один. Я ведь наполовину приличный разработчик, верно?».

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

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

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

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

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

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


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

person Danimal    schedule 17.09.2008    source источник


Ответы (16)


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

person Hank Gay    schedule 17.09.2008

Запустите оба файла через следующий Perl-скрипт, затем используйте diff -iw, чтобы выполнить сравнение без учета регистра и пробелов.

#! /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";
  }
}
person raldi    schedule 17.09.2008
comment
Это эффективно то, что я бы сделал. Он сводит два файла к их основным элементам, нормализует то, что вам не нужно (текст в данном случае), а затем использует готовый инструмент для реальной работы. - person Will Hartung; 22.09.2008

@Mike - это сравнило бы все, включая содержимое страницы, чего не хотел оригинальный постер.

Предполагая, что у вас есть доступ к DOM браузера (написав плагин Firefox/IE или что-то еще), я бы, вероятно, поместил все элементы HTML в дерево, а затем сравнил два дерева. Если имя тега другое, то и узел другой. Возможно, вы захотите прекратить перечисление в какой-то момент (вам, вероятно, все равно на диапазон, полужирный шрифт, курсив и т. д. — может быть, вы беспокоитесь только о div?), поскольку некоторые теги на самом деле являются содержимым, а не структурой страница.

person Andy    schedule 17.09.2008
comment
Однако любые структурные различия проявятся в Windiff. Просто исправить будет сложнее, я полагаю. - person Mike; 17.09.2008
comment
Это правда. Думаю, я просто предположил, что ОП хотел иметь возможность скрывать/игнорировать содержимое страницы, чтобы было легче увидеть различия в структуре. - person Andy; 18.09.2008

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

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

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

person RWendi    schedule 17.09.2008

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

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

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

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

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

person Community    schedule 18.09.2008

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

РЕДАКТИРОВАТЬ: 12.09.2009. Мы создали экспериментальный инструмент SmartDiff с помощью редактора HTML.

person Ira Baxter    schedule 17.06.2009

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

Работает с ФФ 3.5. Я еще не тестировал FF 3.6.

person Philipp    schedule 27.07.2010

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

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

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

person Danimal    schedule 17.09.2008

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

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

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

person RWendi    schedule 20.09.2008

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

person Heiko Hatzfeld    schedule 12.09.2009

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

Красавчик Дифф может это сделать. Он будет сравнивать только структуру кода, независимо от различий в пробелах, комментариях или даже содержании. Просто обязательно установите флажок «Нормализовать содержимое и строковые литералы».

http://prettydiff.com/

person austincheney    schedule 06.01.2012

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

person hdhoang    schedule 28.03.2010

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

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

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

person RCIX    schedule 12.09.2009

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

person Mike    schedule 17.09.2008
comment
Я думаю, что проблема ОП в том, что он добавил контент на страницу и в процессе мог случайно изменить некоторую разметку. Таким образом, diff будет рассматривать весь контент как diff, когда все, что ему нужно, это различия в разметке. - person EBGreen; 17.09.2008