Comment normaliser le HTML en JavaScript ou jQuery?

84

Les balises peuvent avoir plusieurs attributs. L'ordre dans lequel les attributs apparaissent dans le code n'a pas d'importance. Par exemple:

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

Comment puis-je "normaliser" le HTML en Javascript, pour que l'ordre des attributs soit toujours le même? Peu m'importe quel ordre est choisi, tant qu'il est toujours le même.

MISE À JOUR : mon objectif initial était de faciliter la comparaison (en JavaScript) de 2 pages HTML avec de légères différences. Étant donné que les utilisateurs peuvent utiliser différents logiciels pour modifier le code, l'ordre des attributs peut changer. Cela rend le diff trop verbeux.

RÉPONSE : Eh bien, d'abord merci pour toutes les réponses. Et OUI, c'est possible. Voici comment j'ai réussi à le faire. C'est une preuve de concept, elle peut certainement être optimisée:

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);
    }
  }
});

Même chose pour le deuxième élément de la diff $('#different'). Maintenant $('#original').html()et $('#different').html()affichez le code HTML avec les attributs dans le même ordre.

Julien
la source
59
Quel est le besoin de cela?
rahul
40
@rahul: en fait, il y a un besoin assez intéressant pour cela: cela peut grandement améliorer la compression gzip de vos pages.
haylem
11
ah, en Javascript ... tant pis pour la compression. Aucune idée de ce que le besoin est alors.
haylem
13
@Julien: Au moment où votre code JavaScript s'exécute, la page a déjà été envoyée au client. Je ne vois pas comment cela peut aider à la compression alors.
casablanca
22
Il y a en fait une utilisation valable pour essayer de faire ce que l'OP demande. Utilisation d'un éditeur WYSIWYG pour piloter un wiki. Le projet sur lequel je travaille fait exactement cela, et l'éditeur inverserait l'ordre des attributs à chaque fois que vous éditiez le wiki, ce qui entraînerait des différences inutiles. Je finis par trier par ordre alphabétique les attributs dans le HTML soumis sur le backend avant de sauvegarder pour éviter les différences; aurait pu tout aussi facilement faire ce tri en javascript avant de soumettre.
Frank Farmer

Réponses:

68

JavaScript ne voit pas réellement une page Web sous la forme de HTML basé sur du texte, mais plutôt sous la forme d'une arborescence connue sous le nom de DOM ou Document Object Model. L'ordre des attributs des éléments HTML dans le DOM n'est pas défini (en fait, comme le fait remarquer Svend, ils ne font même pas partie du DOM), donc l'idée de les trier au point où JavaScript s'exécute n'est pas pertinente.

Je ne peux que deviner ce que vous essayez d'accomplir. Si vous essayez de le faire pour améliorer les performances de JavaScript / page, la plupart des moteurs de rendu de documents HTML ont probablement déjà déployé beaucoup d'efforts pour optimiser l'accès aux attributs, il n'y a donc pas grand chose à gagner.

Si vous essayez de classer les attributs pour rendre la compression gzip des pages plus efficace lorsqu'elles sont envoyées via le réseau, sachez que JavaScript s'exécute après ce point dans le temps. Au lieu de cela, vous voudrez peut-être regarder les choses qui fonctionnent côté serveur à la place, bien que cela pose probablement plus de problèmes que cela ne vaut la peine.

Tung Nguyen
la source
8
JavaScript peut s'exécuter côté serveur.
Matt Kantor
Les attributs ne sont pas considérés comme faisant partie de l'arborescence du document (qui utilise le classement naturellement). Ainsi, tandis que Attr hérite de l'interface Node, DOM Core 2 spécifie que ces champs sont nuls pour les attributs w3.org/TR/DOM-Level-2-Core/core.html#ID-637646024
Svend
35

Prenez le HTML et analysez-le dans une structure DOM. Ensuite, prenez la structure DOM et réécrivez-la en HTML. Pendant l'écriture, triez les attributs en utilisant n'importe quel tri stable. Votre HTML sera maintenant normalisé en ce qui concerne les attributs.

C'est une manière générale de normaliser les choses. (analyser les données non normalisées, puis les réécrire sous forme normalisée).

Je ne sais pas pourquoi vous voudriez normaliser le HTML, mais vous l'avez. Les données sont des données. ;-)

Kim Bruning
la source
1
Avez-vous un exemple de code. J'ai essayé de faire quelque chose de similaire, cela n'a pas fonctionné.
Julien
12

C'est une preuve de concept, elle peut certainement être optimisée:

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);
    }
  }
 });

Même chose pour le deuxième élément du diff, $ ('# different'). Maintenant $ ('# original'). Html () et $ ('# different'). Html () affichent le code HTML avec les attributs dans le même ordre.

Julien
la source
Je pense que mieux si vous générez votre contenu html en XML puis le restituer en utilisant xslt. Vous obtiendrez sûrement une meilleure sortie.
Nasaralla
8

vous pouvez essayer d'ouvrir l'onglet HTML dans firebug, les attributs sont toujours dans le même ordre

Tsurahman
la source
4
Ce n'est pas vraiment utile en soi. C'est parce qu'il recrée le HTML à partir du DOM, et cependant cela se produit a un ordre d'itération d'attribut particulier (ou Firebug les trie manuellement). Julien pourrait en profiter et utiliser la même méthode pour écrire du HTML.
Matt Kantor
5

En fait, je peux penser à quelques bonnes raisons. L'une serait la comparaison pour la correspondance d'identité et pour une utilisation avec des outils de type «diff» où il est assez ennuyeux que des lignes sémantiquement équivalentes puissent être marquées comme «différentes».

La vraie question est "Pourquoi en Javascript"?

Cette question "sent" "j'ai un problème et je pense avoir une réponse ... mais j'ai aussi un problème avec ma réponse."

Si le PO expliquait pourquoi il veut faire cela, ses chances d'obtenir une bonne réponse augmenteraient considérablement.

Snowhare
la source
2

La question "Quel est le besoin de cela?" Réponse: Cela rend le code plus lisible et plus facile à comprendre.

Pourquoi la plupart des interfaces utilisateur sont nulles ... De nombreux programmeurs ne comprennent pas la nécessité de simplifier le travail des utilisateurs. Dans ce cas, le travail des utilisateurs est de lire et de comprendre le code. Une des raisons de commander les attributs est pour l'humain qui doit déboguer et maintenir le code. Une liste ordonnée, avec laquelle le programme se familiarise, facilite son travail. Il peut trouver plus rapidement des attributs, ou réaliser quels attributs sont manquants, et changer plus rapidement les valeurs d'attribut.

signébit
la source
Il me semble que vous n’avez pas réfléchi assez longtemps à la question; même une solution de travail à la question ne répondrait pas à ce que vous dites ici, aussi vrai que cela puisse être.
issa marie tseng
Pourquoi pensez-vous que l'OP voudrait faire cela avec Javascript? Il est possible qu'une solution Javascript côté serveur (temps de construction?) Soit à l'esprit, mais il est peu probable que quelqu'un suffisamment expérimenté pour le faire ait omis de le mentionner dans un article de Stackoverflow. Il est également possible que l'OP implémente un éditeur HTML dans le navigateur, mais cela semble également douteux.
Pointy
0

Cela n'a d'importance que lorsque quelqu'un lit la source, donc pour moi, ce sont d'abord les attributs sémantiques, les moins sémantiques ensuite ...

Il y a des exceptions bien sûr, si vous avez par exemple des <li> consécutifs, tous avec un attribut sur chacun et d'autres uniquement sur certains, vous pouvez vous assurer que les partagés sont tous au début, suivis de ceux individuels, par exemple .

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

(Même si l'attribut "b" est plus utile sémantiquement que "a")

Vous avez eu l'idée.

Ali
la source
0

il est en fait possible, je pense, si le contenu html est passé au format xml et rendu via xslt ... donc votre contenu original en XML peut être dans l'ordre que vous voulez.

Nasaralla
la source