Encoder des accents sans toucher aux balises HTML

…Et surtout sans tableau de conversion!
Cette opération (à priori très simple) peut poser problème, notamment à cause de l’encodage des caractères.

Faisons le test avec une chaîne de caractères contenant des balises HTML et des accents.

$chaine = "Le <em>péHpé</em> çaÿ <strong>biên</strong>.";

Nous souhaitons obtenir la chaîne suivante:

Le <em>p&eacute;Hp&eacute;</em> &ccedil;a&yuml; <strong>bi&ecirc;n</strong>.

Commençons donc par faire appel à la fonction htmlentities. Pour rappel, cette fonction « convertit tous les caractères éligibles en entités HTML ». Donc les accents seront effectivement encodés… ainsi que les balises HTML (contrairement à la fonction htmlspecialchars qui elle n’aurait pas encodé les accents). N’oubliez pas de préciser le « jeu de caractères », exemple si vous êtes comme moi en UTF-8:

//encodage des accents ET des balises
 echo htmlentities($chaine, ENT_NOQUOTES, 'UTF-8');

Heureusement il existe une fonction capable de faire l’inverse, sans toucher aux accents: htmlspecialchars_decode. Nous obtenons donc:

echo htmlspecialchars_decode(htmlentities($chaine, ENT_NOQUOTES, 'UTF-8'));

Et le tour est joué!

Et si je veux obtenir l’effet inverse?

Là c’est plus simple:

//convertir les &eacute; en é sans toucher aux balises HTML
echo html_entity_decode($chaine, ENT_NOQUOTES, "UTF-8");
14 commentaires
  1. Akemi dit :

    Merci beaucoup pour cette astuce, elle m’a rendue grand service !

  2. Elg dit :

    YES merci beaucoup, j’ai galéré longtemps sur plein de forums et de sites, et voilà, cette astuce a marché 🙂

  3. Ben dit :

    ravi d’avoir pu aider 🙂

  4. Elg dit :

    Ah, je reviens : une remarque, ça marche pour les accents, mais pas les apostrophes ni le signe euro.

    Texte original :

    « Cuisine équipée d’un bloc évier avec plaques électriques et réfrigérateur, installation pour lave linge.
    Loyer mensuel 325€.Dépôt de garantie 325€. »

    Texte obtenu sans ta méthode (brut) :

    « Cuisine �quip�e d�un bloc �vier avec plaques �lectriques et r�frig�rateur, installation pour lave linge.
    Loyer mensuel 325�.D�p�t de garantie 325�. »

    Texte obtenu avec ta méthode :

    « Cuisine équipée d�un bloc évier avec plaques électriques et réfrigérateur, installation pour lave linge.
    Loyer mensuel 325�.Dépôt de garantie 325�. »

    C’est mieux mais pas parfait 🙂 Est-il possible de corriger les derniers caractères?

  5. Ben dit :

    si ton document est encodé en utf-8, cela fonctionne parfaitement.
    – l’apostrophe est transformée en &rsquo;
    – le symbole Euro est transformé en &euro;

  6. Elg dit :

    Hélas non. C’est une page externe que je récupère, et elle est encodée en iso-8859-15. C’est bien le problème. Je suis en train de fouiller partout pour trouver comment encoder correctement les derniers caractères.

  7. Ben dit :

    tu peux donc utiliser:
    echo htmlspecialchars_decode(htmlentities($chaine, ENT_NOQUOTES, ‘ISO-8859-1’));

    doc ici:
    http://fr.php.net/manual/fr/function.htmlentities.php

  8. Elg dit :

    Merci de ta réponse. J’avais déjà essayé avec cette méthode, que j’avais trouvée sur la même page, mais hélas toujours les � à la place des € et des apostrophes. Même résultat. Je continue de chercher, mais avec de moins en moins d’espoir…

  9. Elg dit :

    Me revoilà. Un peu tard, mais j’ai une solution. En fait c’est un bricolage : ne pouvant pas réussir à importer correctement la page, j’ai fait un petit script analysant le caractère précédant chaque �. Si c’est un chiffre ou un espace, alors le � est probablement un € et je le remplace. Si c’est une lettre, alors le � est probablement une apostrophe.

    Voilà le script (avec jQuery, mais faisable en PHP ou autre) :

    $.each(texte, function(index, value){ /* Analyse le texte, lettre par lettre */
    if(value== »� »){
    prevChar = texte.charAt(index-1);

    if( prevChar== » « ){ /* Le caractère précédent est un espace, donc le caractère mystère est probablement un euro */
    texte = texte.replace(« � », »€ »);
    } else {
    prevChar = parseInt(prevChar);
    if( prevChar>-1 && prevChar <10 ) { /* Le caractère précédent est un chiffre, donc le caractère mystère est probablement un euro */
    texte = texte.replace("�","€");
    } else {
    texte = texte.replace("�","'"); /* sinon c'est probablement une apostrophe */
    }
    }
    }
    });

    Et voilà le texte correctement importé 🙂

  10. Ludovi dit :

    Impossible de trouver un tool en ligne qui propose la simple option d’encoder sans toucher au HTML.

  11. catou dit :

    super !!! enfin !!! apres avoir cherché des heures, tu nous offres LA solution !!!

  12. swat dit :

    Mieux vaut tard que jamais !!
    @ELG -> pour résoudre ton problème sans javascript :
    htmlentities($chaine, ENT_QUOTES, ‘UTF-8’);
    Remplace ENT_NOQUOTES par ENT_QUOTES

Laisser une réponse