c# - script - Sugerencias sobre cómo construir una herramienta HTML Diff?
html comparator (17)
No conozco ninguna herramienta, pero sé que hay una manera simple de hacerlo:
- Primero, use una herramienta de expresión regular para quitar todo el texto en su archivo HTML. Puede usar esta expresión regular para buscar el texto (
?<=^|>)[^><]+?(?=<|$
) Y reemplazarlos por una cadena vacía (""
), es decir, eliminar todo el texto . Después de este paso, tendrá todas las etiquetas de marcado HTML. Hay muchas herramientas gratuitas de expresión regular por ahí. - Luego, repites el primer paso para el archivo HTML original.
- Por último, usa una herramienta diff para comparar los dos conjuntos de marcas HTML. Esto mostrará lo que falta entre un conjunto y el otro.
En esta publicación , pregunté si había alguna herramienta que comparara la estructura (no el contenido real) de 2 páginas HTML. Lo pido porque recibo plantillas HTML de nuestros diseñadores y con frecuencia me pierdo pequeños cambios de formato en mi implementación. Luego desperdicio algunas horas de tiempo de diseñador revisando mis páginas para encontrar mis errores.
El hilo ofreció algunas buenas sugerencias, pero no había nada que se ajustara a la ley. "Bien, entonces", pensé, "voy a sacar uno solo. Soy un desarrollador a mitad de camino, ¿cierto?".
Bueno, una vez que comencé a pensar en ello, no pude entender cómo hacerlo. Puedo generar un sitio web basado en datos con la suficiente facilidad, o realizar una implementación de CMS, o lanzar documentos dentro y fuera de BizTalk todo el día. No se puede comenzar a descubrir cómo comparar documentos HTML.
Bueno, claro, tengo que leer el DOM e iterar a través de los nodos. Tengo que asignar la estructura a alguna estructura de datos (¿cómo?), Y luego compararlos (¿cómo?). Es una tarea de desarrollo como ninguna que haya intentado.
Ahora que he identificado una debilidad en mi conocimiento, estoy aún más desafiado para resolver esto. ¿Alguna sugerencia sobre cómo comenzar?
aclaración: el contenido real no es lo que quiero comparar: los chicos creativos llenan sus páginas con lorem ipsum y yo uso contenido real. En cambio, quiero comparar la estructura:
<div class="foo">lorem ipsum<div>
es diferente que
<div class="foo">
<p>lorem ipsum<p>
<div>
@Mike: eso compararía todo, incluido el contenido de la página, que no es lo que quería el póster original.
Asumiendo que tienes acceso al DOM del navegador (escribiendo un complemento de Firefox / IE o lo que sea), probablemente pondría todos los elementos HTML en un árbol, luego compararía los dos árboles. Si el nombre de la etiqueta es diferente, entonces el nodo es diferente. Es posible que desee dejar de enumerar en un cierto punto (es probable que no le interese span, negrita, cursiva, etc., ¿tal vez solo se preocupe por los divs?), Ya que algunas etiquetas son realmente el contenido, en lugar de la estructura, del página.
Abra cada página en el navegador y guárdelas como archivos .htm. Compara los dos usando windiff.
Ejecute ambos archivos a través de la siguiente secuencia de comandos Perl, luego use diff -iw para hacer una distinción insensible a mayúsculas y espacios en blanco que ignore.
#! /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";
}
}
El DOM es una estructura de datos, es un árbol.
Este ha sido un excelente comienzo. Algunas aclaraciones / comentarios más:
- Probablemente no me importen las identificaciones, ya que .net las destruirá
- parte de la estructura estará en un repetidor u otro tipo de control, por lo que podría terminar teniendo más o menos elementos repetitivos
Pensamiento adicional: creo que un buen comienzo sería suponer que el html es compatible con XHTML. Pude inferir el esquema (utilizando los nuevos métodos .net XmlSchemaInference) y luego diferir los esquemas. Luego puedo ver las diferencias y considerar si son significativas o no.
Si tuviera que resolver este problema, haría esto:
- Planee algún tipo de DOM para páginas html. comienza en peso liviano y luego agrega más según sea necesario. Yo usaría un patrón compuesto para la estructura de datos. es decir, cada elemento tiene una colección de elementos secundarios del tipo de clase base.
- Crea un analizador para analizar páginas html.
- Usando el analizador carga el elemento html al DOM.
- Después de cargar las páginas hasta el DOM, tiene la instantánea jerárquica de la estructura de las páginas html.
- Siga iterando a través de cada elemento en ambos lados hasta el final del DOM. Encontrarás la diferencia en la estructura cuando tocas un tipo de elemento no coincidente.
En su ejemplo, usted solo tendría cargado un objeto div en un lado, en el otro lado tendría un objeto div elemento cargado con 1 elemento hijo de tipo elemento párrafo. encienda su iterador, primero emparejará el elemento div, el segundo iterador emparejará el párrafo con nada. Usted tiene su diferencia estructural.
Creo que algunas de las sugerencias anteriores no tienen en cuenta que hay otras etiquetas en el HTML entre dos páginas que serían textualmente diferentes, pero el marcado HTML resultante es funcionalmente equivalente. Danimal enumera las identificaciones de control como un ejemplo.
Las siguientes dos marcas son idénticas a las funciones, pero se mostrarían como diferentes si simplemente comparas las etiquetas:
<div id="ctl00_TopNavHome_DivHeader" class="header4">foo</div>
<div class="header4">foo</div>
Iba a sugerir a Danimal que escribiera una traducción HTML que buscara las etiquetas HTML y convirtiera ambos documentos en una versión simplificada de ambas que omite las etiquetas de identificación y cualquier otra etiqueta que designe como irrelevante. Es probable que tenga que ser un trabajo en progreso, ya que ignora ciertos atributos / etiquetas y luego se topa con otros nuevos que también desea ignorar.
Sin embargo, me gusta la idea de usar XmlSchemaInterface para reducirlo al esquema XML y luego usar una herramienta diff que entienda las reglas XML.
Mi sugerencia es solo la forma básica de hacerlo ... Por supuesto, para abordar el problema que mencionó, se deben aplicar reglas adicionales aquí ... que es en su caso, obtuvimos un elemento div correspondiente y luego aplicamos atributos / coincidencia de propiedad reglas y qué no ...
Para ser honesto, hay muchas reglas complicadas que se deben aplicar para la comparación, y no es simplemente un elemento de coincidencia simple con otro elemento. Por ejemplo, qué ocurre si tienes duplicados. por ejemplo, 1 div elemento en un lado, y 2 div elemento en el otro lado. ¿Cómo vas a unir los elementos div que coinciden?
Hay muchos otros problemas complicados que encontrará en la palabra de comparación. Im hablando basado en la experiencia (parte de mi trabajo es maitain mi motor de comparación de texto de la compañía).
Consulte http://www.semdesigns.com/Products/SmartDifferencer/index.html para obtener una herramienta que se parametriza mediante la gramática de idioma y produce deltas en términos de elementos de lenguaje (identificadores, expresiones, instrucciones, bloques, métodos, ... ) insertados, eliminados, movidos, reemplazados o con identificadores sustituidos en forma consistente. Esta herramienta ignora el reformateo del espacio en blanco (p. Ej., Diferentes saltos de línea o diseños) y valores semánticamente indistinguibles (p. Ej., Sabe que 0x0F y 15 tienen el mismo valor). Esto se puede aplicar a HTML usando un analizador HTML.
EDIT: 9/12/2009. Hemos construido una herramienta experimental SmartDiff utilizando un editor de HTML.
Echa un vistazo a más allá de comparar. Tiene una función de comparación XML que puede ayudarte.
Si tuviera que hacer esto, primero aprendería HTML. (^ - ^) Luego construiría una herramienta que elimine todo el contenido real y luego lo guarde como un archivo para que pueda ser canalizado a través de WinDiff (u otra herramienta de fusión).
También puede tener que considerar que el ''contenido'' en sí podría contener un margen adicional, por lo que probablemente valga la pena excluir todo dentro de ciertos elementos (como <div>
s con ciertos ID o clases) antes de hacer su comparación. Por ejemplo:
<div id="mainContent">
<p>lorem ipsum etc..</p>
</div>
y
<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>
http://www.mugo.ca/Products/Dom-Diff
Funciona con FF 3.5. Todavía no he probado FF 3.6.
Pretty Diff puede hacer esto. Comparará la estructura del código solo independientemente de las diferencias con el espacio en blanco, los comentarios o incluso el contenido. Solo asegúrate de marcar la opción "Normalizar contenido y cadenas literales".
html5lib
(o contribuiría a) html5lib
y su salida SAX. Solo deslícese por las 2 secuencias de SAX buscando desajustes y resalte todo el subárbol correspondiente.