305 votes

Décodage des entités HTML

Comment coder et décoder des entités HTML en utilisant JavaScript ou JQuery ?

var varTitle = "Chris' corner";

Je veux que ça le soit :

var varTitle = "Chris' corner";

16 votes

Voir cette réponse . Semble meilleur que ce qui est proposé ci-dessous.

1 votes

Voir aussi le module ent (sur npm !) github.com/substack/node-ent

1 votes

Je pense que @ringø (wow, nom d'utilisateur étrangement similaire...) voulait faire un lien vers cette réponse

301voto

Robert K Points 14893

Je vous déconseille d'utiliser le code jQuery qui a été accepté comme réponse. Bien qu'il n'insère pas la chaîne à décoder dans la page, il entraîne la création d'éléments tels que des scripts et des éléments HTML. C'est beaucoup plus de code que ce dont nous avons besoin. Je suggère plutôt d'utiliser une fonction plus sûre et plus optimisée.

var decodeEntities = (function() {
  // this prevents any overhead from creating the object each time
  var element = document.createElement('div');

  function decodeHTMLEntities (str) {
    if(str && typeof str === 'string') {
      // strip script/html tags
      str = str.replace(/<script[^>]*>([\S\s]*?)<\/script>/gmi, '');
      str = str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi, '');
      element.innerHTML = str;
      str = element.textContent;
      element.textContent = '';
    }

    return str;
  }

  return decodeHTMLEntities;
})();

http://jsfiddle.net/LYteC/4/

Pour utiliser cette fonction, il suffit d'appeler decodeEntities("&amp;") et il utilisera les mêmes techniques sous-jacentes que la version jQuery, mais sans la surcharge de jQuery, et après avoir nettoyé les balises HTML dans l'entrée. Voir Commentaire de Mike Samuel sur la réponse acceptée pour savoir comment filtrer les balises HTML.

Cette fonction peut être facilement utilisée comme un plugin jQuery en ajoutant la ligne suivante dans votre projet.

jQuery.decodeEntities = decodeEntities;

0 votes

Quelqu'un peut-il me dire ce que str.replace(/<\/ ? \w (? :[^"'>]|"[^"]*"|'[^']*')*>/gmi, '') ; does ?

0 votes

@PoeHaH Il supprime toutes les balises html, qu'elles soient ouvrantes ou fermantes.

9 votes

Remarque : textContent n'est pas pris en charge dans IE8, donc si c'est toujours l'un de vos navigateurs cibles, vous devez trouver une autre solution. Je viens de perdre une heure à essayer de comprendre cela, puisque nous devons décoder les entités spécifiquement pour compenser un autre bug d'IE8.

247voto

David Thomas Points 111253

Vous pourriez essayer quelque chose comme :

var Title = $('<textarea />').html("Chris&apos; corner").text();
console.log(Title);

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

JS Fiddle .

Une version plus interactive :

$('form').submit(function() {
  var theString = $('#string').val();
  var varTitle = $('<textarea />').html(theString).text();
  $('#output').text(varTitle);
  return false;
});

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="#" method="post">
  <fieldset>
    <label for="string">Enter a html-encoded string to decode</label>
    <input type="text" name="string" id="string" />
  </fieldset>
  <fieldset>
    <input type="submit" value="decode" />
  </fieldset>
</form>

<div id="output"></div>

JS Fiddle .

0 votes

Cool, ça marche. Par curiosité, le $('div />') est utilisé pour créer un élément <div> autour du varTitle ?

6 votes

@chris et @david - Ce code crée un div vide (détaché du DOM) et définit son innerHTML, puis le récupère en tant que texte normal. Ce n'est pas en l'entourant d'un DIV mais le mettre dans un div . J'insiste sur ce point car il est essentiel de comprendre le fonctionnement de jQuery.

38 votes

Ne l'utilisez PAS avec des données non fiables, voir le commentaire de Mike ici : stackoverflow.com/questions/1147359/

120voto

Alan Hamlett Points 1041

Comme l'a dit Robert K, n'utilisez pas jQuery.html().text() pour décoder les entités html, car cela n'est pas sûr, l'entrée utilisateur ne devant jamais avoir accès au DOM. Lire à ce sujet XSS pour expliquer pourquoi ce n'est pas sûr.

Essayez plutôt le Underscore.js la bibliothèque de courroies utilitaires qui est fournie avec s'échapper y s'évader méthodes :

_.escape(string)

Échappe une chaîne de caractères pour l'insérer dans le HTML, en remplaçant & , < , > , " , ` y ' des personnages.

_.escape('Curly, Larry & Moe');
=> "Curly, Larry &amp; Moe"

_.unescape(string)

Le contraire de l'évasion, remplace &amp; , &lt; , &gt; , &quot; , &#96; y &#x27; avec leurs équivalents non encodés.

_.unescape('Curly, Larry &amp; Moe');
=> "Curly, Larry & Moe"

Pour prendre en charge le décodage d'un plus grand nombre de caractères, il suffit de copier l'Underscore s'évader et ajouter d'autres personnages à la carte.

0 votes

Erreur de type : _.unescape n'est pas une fonction

2 votes

@chovy, utilisez la dernière version de Underscore.js >= 1.4.2 et vous n'obtiendrez pas de TypeError.

0 votes

C'est en gros la seule chose qui fonctionne pour moi. J'ai besoin de trouver les balises script contenant des modèles, puis de les parcourir pour trouver les sous-sections de ces modèles. En faisant cela avec jQuery, jQ convertit tout le html "invalide" (aka les balises de modèle) en entités. Pour récupérer les sous-sections, il faut les désencapsuler à nouveau, et pour cela, aucune des autres réponses ne fonctionne.

52voto

William Lahti Points 129

Voici une méthode rapide qui ne nécessite pas la création d'un div et qui décode les caractères échappés HTML les plus courants :

function decodeHTMLEntities(text) {
    var entities = [
        ['amp', '&'],
        ['apos', '\''],
        ['#x27', '\''],
        ['#x2F', '/'],
        ['#39', '\''],
        ['#47', '/'],
        ['lt', '<'],
        ['gt', '>'],
        ['nbsp', ' '],
        ['quot', '"']
    ];

    for (var i = 0, max = entities.length; i < max; ++i) 
        text = text.replace(new RegExp('&'+entities[i][0]+';', 'g'), entities[i][1]);

    return text;
}

15 votes

Votre réponse ne fonctionne pas du tout pour la plupart des entités html, et l'étendre pour les inclure serait plutôt répétitif et source d'erreurs. Par exemple, il existe une entité pour chaque caractère japonais kanji, qui se compte par milliers. De plus, à ce stade, je ne serais pas surpris que votre réponse soit plus lente que certaines des autres ici, puisque vous auriez à exécuter des milliers de replaces avec des milliers de regex pour chaque chaîne à décoder.

2 votes

Cela dépend vraiment du BUT que vous poursuivez en encodant ces chaînes de caractères. Si votre objectif est de ne pas déclencher de traitement HTML via des éléments tels que < ou >, il n'est absolument pas nécessaire d'encoder les autres caractères via la syntaxe des entités de caractères. La grande quantité d'entités de caractères sert principalement d'outil pratique. Les entités que j'ai énumérées sont le strict minimum de celles auxquelles vous devez échapper pour éviter que les données soient mélangées avec le HTML. [Suite dans le commentaire suivant]

1 votes

Pour ce qui est de la rapidité, il est bon d'avoir exécuté plusieurs regex. Mais bien sûr, puisque votre idée de mettre chaque entité de caractère dans ce code est inutile et franchement, vraiment stupide, ce n'est pas un problème. On pourrait cependant générer la regex en utilisant d'abord le caractère | et faire un seul appel à replace(). Je pense qu'il faudrait faire un test pour voir ce qui est le plus rapide, mais mon intuition me dit que ce sera plus rapide d'utiliser | avec un seul replace() en raison de la surcharge des appels de fonction qui est élevée en Javascript.

21voto

mattcasey Points 111

Inspirée de la solution de Robert K, cette version ne supprime pas les balises HTML et est tout aussi sûre.

var decode_entities = (function() {
    // Remove HTML Entities
    var element = document.createElement('div');

    function decode_HTML_entities (str) {

        if(str && typeof str === 'string') {

            // Escape HTML before decoding for HTML Entities
            str = escape(str).replace(/%26/g,'&').replace(/%23/g,'#').replace(/%3B/g,';');

            element.innerHTML = str;
            if(element.innerText){
                str = element.innerText;
                element.innerText = '';
            }else{
                // Firefox support
                str = element.textContent;
                element.textContent = '';
            }
        }
        return unescape(str);
    }
    return decode_HTML_entities;
})();

6 votes

Ces escape() y unescape() sont dépréciées. developer.mozilla.org/fr/US/docs/Web/JavaScript/Référence/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X