Ответ 1
DOM - это структура данных - это дерево.
В этот пост Я спросил, есть ли какие-либо инструменты, которые сравнивают структуру (а не фактическое содержимое) из двух HTML-страниц. Я спрашиваю, потому что я получаю HTML-шаблоны от наших дизайнеров и часто пропускаю незначительные изменения форматирования в моей реализации. Затем я трачу несколько часов дизайнерского времени на прохождение моих страниц, чтобы найти свои ошибки.
Тема предложила несколько хороших предложений, но ничего не соответствовало законопроекту. "Прекрасно, тогда", подумал я, "я просто провожу кого-то из себя. Я прилежный разработчик, верно?".
Хорошо, как только я начал думать об этом, я не мог понять, как это сделать. Я могу легко прокрутить управляемый данными веб-сайт или выполнить CMS или бросить документы в BizTalk и весь день. Не могу понять, как сравнивать документы HTML.
Ну, конечно, я должен прочитать DOM и перебрать узлы. Мне нужно сопоставить структуру с некоторой структурой данных (как?), А затем сравнить их (как?). Это задача разработки, как никто из моих попыток.
Итак, теперь, когда я обнаружил слабость в своих знаниях, мне еще более сложно понять это. Любые предложения о том, как начать работу?
пояснение: фактический контент - это не то, что я хочу сравнить - креативные парни заполняют свои страницы lorem ipsum, и я использую реальный контент. Вместо этого я хочу сравнить структуру:
<div class="foo">lorem ipsum<div>
отличается тем, что
<div class="foo">
<p>lorem ipsum<p>
<div>
DOM - это структура данных - это дерево.
Запустите оба файла с помощью следующего 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";
}
}
@Mike - это будет сравнивать все, в том числе содержимое страницы, которое не хочет, чтобы оригинальный плакат хотел.
Предполагая, что у вас есть доступ к DOM браузера (написав плагин Firefox/IE или что-то еще), я бы, вероятно, поместил все элементы HTML в дерево, а затем сравнил два дерева. Если имя тега отличается, то node отличается. Возможно, вам захочется прекратить перечисление в определенный момент (возможно, вам небезразличен диапазон, полужирный, курсив и т.д. - может быть, только беспокоиться о divs?), Поскольку некоторые теги - это действительно контент, а не структура, стр.
Если бы я решил эту проблему, я бы сделал следующее:
В вашем примере у вас будет только объект элемента div, загруженный с одной стороны, с другой стороны у вас будет объект div-элемента, загруженный 1 дочерним элементом элемента абзаца типа. запустите свой итератор, сначала вы сравните элемент div, второй итератор, который вы соедините с абзацем ни с чем. У вас есть свои структурные различия.
Я думаю, что некоторые из приведенных выше предложений не учитывают, что в HTML есть другие теги между двумя страницами, которые были бы текстовыми, но получающаяся разметка HTML функционально эквивалентна. В качестве примера перечислены контрольные идентификаторы Danimal.
Следующие две разметки функционально идентичны, но будут отображаться как разные, если вы просто сравнили теги:
<div id="ctl00_TopNavHome_DivHeader" class="header4">foo</div>
<div class="header4">foo</div>
Я собирался предложить Danimal написать HTML-перевод, который ищет HTML-теги и преобразует оба документа в упрощенную версию обоих, которые не пропускают теги идентификаторов и любые другие теги, которые вы обозначаете как несущественные. Это, вероятно, должно быть незавершенным, поскольку вы игнорируете определенные атрибуты/теги, а затем запускаете новые, которые вы также хотите игнорировать.
Однако мне нравится идея использования XmlSchemaInterface, чтобы свернуть ее до XML-схемы, а затем использовать инструмент diff, который понимает правила XML.
См. http://www.semdesigns.com/Products/SmartDifferencer/index.html для инструмента, который параметризуется грамматикой langauge и производит дельта в терминах элементов языка (идентификаторы, выражения, операторы, блоки, методы,...) вставлены, удалены, перемещены, заменены или имеют одинаковые идентификаторы. Этот инструмент игнорирует переформатирование в виде пробелов (например, различные разрывы строк или макеты) и семантически неотличимые значения (например, он знает, что 0x0F и 15 являются одинаковым значением). Это можно применить к HTML, используя парсер HTML.
EDIT: 9/12/2009. Мы создали экспериментальный инструмент SmartDiff с помощью HTML-редактора.
http://www.mugo.ca/Products/Dom-Diff
Работает с FF 3.5. Я еще не тестировал FF 3.6.
Смотрите этот предыдущий пост и сопровождающие ответы.
Я не знаю никакого инструмента, но я знаю, что есть простой способ сделать это:
?<=^|>)[^><]+?(?=<|$
) и заменить их пустой строкой (""
), т.е. Удалить весь текст. После этого шага вы будете иметь все теги разметки HTML. Там есть много бесплатных инструментов регулярного выражения.Это был отличный старт. Еще несколько пояснений/комментариев:
подумал: Я думаю, что хорошим началом было бы предположить, что html соответствует XHTML. Затем я мог бы вывести схему (используя новые методы .net XmlSchemaInference), а затем разобрать схемы. Затем я могу разобраться в различиях и подумать, важны они или нет.
Мое предложение - это просто основной способ сделать это... Конечно, чтобы решить проблему, о которой вы говорили, здесь должны применяться дополнительные правила... Что в вашем случае, мы получили соответствующий элемент div, а затем применяем атрибуты/правила сопоставления свойств, а что нет...
Честно говоря, существует множество и сложных правил, которые необходимо применять для сравнения, а также не только простой элемент соответствия для другого элемента. Например, что произойдет, если у вас есть дубликаты. например 1 div с одной стороны и 2 div-элемента на другой стороне. Как вы собираетесь совпадать с элементами div?
Есть и другие сложные проблемы, которые вы найдете в слове сравнения. Я говорю на основе опыта (часть моей работы заключается в том, чтобы maitain механизм сравнения текста моей компании).
Взгляните на сравнение. Он имеет функцию сравнения XML, которая может помочь вам.
Возможно, вам также придется учитывать, что сам "контент" может содержать дополнительную надбавку, поэтому, прежде чем выполнять сравнение, вам, возможно, стоит выделить все в определенных элементах (например, <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, ищите несоответствия и выделите все соответствующие поддеревы.
Pretty Diff может это сделать. Он будет сравнивать структуру кода только независимо от различий с пробелами, комментариями или даже содержанием. Просто не забудьте проверить параметр "Нормализовать содержимое и литералы струн".
Если бы я сделал это, сначала я бы изучил HTML. (^ - ^) Тогда я бы построил инструмент, который удаляет все фактическое содержимое, а затем сохраняет это как файл, чтобы он мог быть передан через WinDiff (или другой инструмент слияния).
Откройте каждую страницу в браузере и сохраните их как .htm файлы. Сравните их с использованием windiff.