¿Cómo normalizar HTML en JavaScript o jQuery?

84

Las etiquetas pueden tener varios atributos. El orden en que aparecen los atributos en el código no importa. Por ejemplo:

<a href="#" title="#">
<a title="#" href="#">

¿Cómo puedo "normalizar" el HTML en Javascript, para que el orden de los atributos sea siempre el mismo? No me importa qué orden se elija, siempre que sea el mismo.

ACTUALIZACIÓN : mi objetivo original era facilitar la diferenciación (en JavaScript) de 2 páginas HTML con ligeras diferencias. Dado que los usuarios pueden utilizar un software diferente para editar el código, el orden de los atributos podría cambiar. Esto hace que el diff sea demasiado detallado.

RESPUESTA : Bueno, primero gracias por todas las respuestas. Y SÍ, es posible. Así es como me las arreglé para hacerlo. Esta es una prueba de concepto, ciertamente se puede optimizar:

function sort_attributes(a, b) {
  if( a.name == b.name) {
    return 0;
  }

  return (a.name < b.name) ? -1 : 1;
}

$("#original").find('*').each(function() {
  if (this.attributes.length > 1) {
    var attributes = this.attributes;
    var list = [];

    for(var i =0; i < attributes.length; i++) {
      list.push(attributes[i]);
    }

    list.sort(sort_attributes);

    for(var i = 0; i < list.length; i++) {
      this.removeAttribute(list[i].name, list[i].value);
    }

    for(var i = 0; i < list.length; i++) {
      this.setAttribute(list[i].name, list[i].value);
    }
  }
});

Lo mismo para el segundo elemento del diff, $('#different'). Ahora $('#original').html()y $('#different').html()muestre el código HTML con los atributos en el mismo orden.

Julien
fuente
59
¿Cuál es la necesidad de esto?
rahul
40
@rahul: en realidad hay una necesidad bastante interesante para esto: puede mejorar en gran medida la compresión gzip de sus páginas.
haylem
11
ah, en Javascript ... tanto para la compresión. No tengo idea de cuál es la necesidad entonces.
haylem
13
@Julien: Para cuando se ejecuta su código JavaScript, la página ya se ha enviado al cliente. Entonces no veo cómo puede ayudar en la compresión.
casablanca
22
De hecho, hay un uso válido para intentar hacer lo que pide el OP. Usando un editor WYSIWYG para manejar un wiki. El proyecto en el que estoy trabajando hace exactamente eso, y el editor invierte el orden de los atributos cada vez que edita el wiki, lo que genera diferencias innecesarias. Termino ordenando alfabéticamente los atributos en el HTML enviado en el backend antes de guardar para evitar diferencias; podría haberlo hecho con la misma facilidad en javascript antes de enviarlo.
Frank Farmer

Respuestas:

68

JavaScript en realidad no ve una página web en forma de HTML basado en texto, sino más bien como una estructura de árbol conocida como DOM o Document Object Model. El orden de los atributos de los elementos HTML en el DOM no está definido (de hecho, como comenta Svend, ni siquiera forman parte del DOM), por lo que la idea de ordenarlos en el punto donde se ejecuta JavaScript es irrelevante.

Solo puedo adivinar lo que estás tratando de lograr. Si está tratando de hacer esto para mejorar el rendimiento de JavaScript / página, la mayoría de los procesadores de documentos HTML presumiblemente ya se esfuerzan mucho en optimizar el acceso a los atributos, por lo que hay poco que ganar allí.

Si está tratando de ordenar atributos para hacer que la compresión gzip de las páginas sea más efectiva a medida que se envían por cable, comprenda que JavaScript se ejecuta después de ese momento. En cambio, es posible que desee ver las cosas que se ejecutan en el lado del servidor, aunque probablemente sea más problemático de lo que vale la pena.

Tung Nguyen
fuente
8
JavaScript puede ejecutarse en el lado del servidor.
Matt Kantor
Los atributos no se consideran parte del árbol del documento (que utiliza el orden de forma natural). Entonces, aunque Attr hereda la interfaz de nodo, DOM Core 2 especifica que estos campos sean nulos para los atributos w3.org/TR/DOM-Level-2-Core/core.html#ID-637646024
Svend
35

Tome el HTML y analícelo en una estructura DOM. Luego tome la estructura DOM y escríbala nuevamente en HTML. Mientras escribe, ordene los atributos usando cualquier orden estable. Su HTML ahora se normalizará con respecto a los atributos.

Esta es una forma general de normalizar las cosas. (analice los datos no normalizados y luego vuelva a escribirlos en forma normalizada).

No estoy seguro de por qué querría normalizar HTML, pero ahí lo tiene. Los datos son datos. ;-)

Kim Bruning
fuente
1
¿Tiene un ejemplo de código? Intenté hacer algo similar, no funcionó.
Julien
12

Esta es una prueba de concepto, ciertamente se puede optimizar:

function sort_attributes(a, b) {
  if( a.name == b.name) {
    return 0;
  }

  return (a.name < b.name) ? -1 : 1;
 }

$("#original").find('*').each(function() {
  if (this.attributes.length > 1) {
    var attributes = this.attributes;
    var list = [];

    for(var i =0; i < attributes.length; i++) {
      list.push(attributes[i]);
    }

     list.sort(sort_attributes);

    for(var i = 0; i < list.length; i++) {
      this.removeAttribute(list[i].name, list[i].value);
    }

     for(var i = 0; i < list.length; i++) {
       this.setAttribute(list[i].name, list[i].value);
    }
  }
 });

Lo mismo para el segundo elemento de la diferencia, $ ('# different'). Ahora $ ('# original'). Html () y $ ('# diferente'). Html () muestran el código HTML con atributos en el mismo orden.

Julien
fuente
Creo que es mejor si genera su contenido html en XML y luego lo renderiza usando xslt. Seguramente obtendrá un resultado mejor.
Nasaralla
8

puede intentar abrir la pestaña HTML en firebug, los atributos siempre están en el mismo orden

tsurahman
fuente
4
Esto no es realmente útil por sí solo. Eso es porque está recreando el HTML desde el DOM, y sin embargo esto sucede tiene un orden de iteración de atributo particular (o Firebug los ordena manualmente). Julien podría aprovechar esto y usar el mismo método para escribir HTML.
Matt Kantor
5

De hecho, puedo pensar en algunas buenas razones. Una sería la comparación para la coincidencia de identidades y para su uso con herramientas de tipo 'diff' donde es bastante molesto que las líneas semánticamente equivalentes puedan marcarse como "diferentes".

La verdadera pregunta es "¿Por qué en Javascript"?

Esta pregunta "huele" a "Tengo un problema y creo que tengo una respuesta ... pero también tengo un problema con mi respuesta".

Si el OP explicara por qué quieren hacer esto, sus posibilidades de obtener una buena respuesta aumentarían drásticamente.

Snowhare
fuente
2

La pregunta "¿Cuál es la necesidad de esto?" Respuesta: Hace que el código sea más legible y más fácil de entender.

Por qué la mayoría de las interfaces de usuario apestan ... Muchos programadores no comprenden la necesidad de simplificar el trabajo de los usuarios. En este caso, el trabajo de los usuarios es leer y comprender el código. Una razón para ordenar los atributos es para el humano que tiene que depurar y mantener el código. Una lista ordenada, con la que el programa se familiariza, facilita su trabajo. Puede encontrar atributos más rápidamente o darse cuenta de qué atributos faltan y cambiar más rápidamente los valores de los atributos.

bit firmado
fuente
Me parece que no ha pensado en la cuestión el tiempo suficiente; incluso una solución funcional a la pregunta no abordaría lo que dice aquí, por cierto que sea.
issa marie tseng
¿Por qué supone que el OP querría hacer esto con Javascript? Es posible que tuviera en mente una solución de Javascript del lado del servidor (¿tiempo de compilación?), Pero es poco probable que alguien con la experiencia suficiente para hacer eso no lo haya mencionado en una publicación de Stackoverflow. También es posible que el OP esté implementando un editor HTML en el navegador, pero eso también parece dudoso.
Puntiagudo
0

Esto solo importa cuando alguien está leyendo la fuente, así que para mí son los atributos semánticos primero, luego los menos semánticos ...

Por supuesto, hay excepciones, si tiene, por ejemplo, <li> consecutivos, todos con un atributo en cada uno y otros solo en algunos, es posible que desee asegurarse de que los compartidos estén todos al principio, seguidos de los individuales, p. Ej. .

<li a = "x"> A </li>
<li a = "y" b = "t"> B </li>
<li a = "z"> C </li>

(Incluso si el atributo "b" es más útil semánticamente que "a")

Entiendes la idea.

Ali
fuente
0

De hecho, creo que es posible si el contenido html se pasa como xml y se representa a través de xslt ... por lo tanto, su contenido original en XML puede estar en el orden que desee.

Nasaralla
fuente