OVH Cloud OVH Cloud

caractere pas commun avec UTF-8 pour XML

32 réponses
Avatar
Seb
Bonjour,

Je galère depuis quelques jours sur un problème, et j'ai rien trouvé
d'intéressant sur Google que se soit sur le web ou dans les newsgroups.

Je génère un fichier XML encodé en utf-8, pour encoder les textes rentrées
j'y vais à coup de utf8_encode(htmlspecialchars($texte)) pour être conforme
à la fois à XML et au paramètre d'entrée de utf8_encode (utf8_encode
convertit de iso-8859-1 en utf-8).

Jusque là pas de problème avec la grande majorités des caractères
(&<>éèà...) mais je me suis aperçu : qu'avec celui-ci par exemple : right
single quote mark 92 &#146; &rsquo; --> '
Ni htmlspecialchars ou htmlentities et ni utf8_encode l'encode du coup je me
retrouve avec un document XML non valide !

J'aimerais savoir qu'elle est la meilleur stratégie à adopter à votre avis,
pour l'instant je fais un str_replace mais la solution me convient pas car
j'imagine que le problème peu se reposer avec d'autre caractère. Qu'elles
sont les caractères à problème et existe t-il une solution propre pour y
remédier ?

PS : v. PHP 4.3.2

D'avance un grand merci pour votre aide,

Séb

-- carpe diem --
Tout le monde savait que c'était impossible. Il est venu un imbécile qui ne
savait pas et qu'il l'a fait. Marcel Pagnol.

10 réponses

1 2 3 4
Avatar
Etienne SOBOLE
"Seb" a écrit dans le message de news:
40a4829d$0$17908$

php tiré de la class.wiki2whtml.php
# Copyright (c) 2004 Olivier Meunier and contributors. All rights reserved


Y a quand meme quelques chose de relou dans cette histoire,
c'est que c'est toujours pas des caractère UTF-8 !!!

Faudrai la meme fonction avec des resultat UTF-8 !

Etienne

Avatar
Seb
"Seb" a écrit dans le message de news:
40a2c112$0$17918$

Jusque là pas de problème avec la grande majorités des caractères
(&<>éèà...) mais je me suis aperçu : qu'avec celui-ci par exemple :
right


single quote mark 92 &#146; &rsquo; --> '
Ni htmlspecialchars ou htmlentities et ni utf8_encode l'encode du coup
je


me
retrouve avec un document XML non valide !


bon ben c'est complètement exacte ce que tu dis :)
tout les caractère 0x9? ne sont pas traduisible en UTF-8.
pourquoi je sais pas, mais je crois que c'est en grande partie due au fait
que la charset source est un charset windows.
moi je fais un str_replace parce que 'ai j'ai rien trouvé de mieux a
faire.


Es ce possible avec une expression régulière de filtrer en hexa ?

j'ai egalement des probleme avec le ? qui parfois n'est pas converti.

bref. si par hasard tu trouves la solution idéale, hésite pas a le dire.


J'hésiterais pas, mais je la cherche encore ;)

Merci

Séb
(pour les médiateur : enlever SVP -antispam pour me répondre , merci)


Avatar
nano
Seb wrote:

J'aimerais savoir qu'elle est la meilleur stratégie à adopter à votre avis,
pour l'instant je fais un str_replace mais la solution me convient pas car
j'imagine que le problème peu se reposer avec d'autre caractère. Qu'elles
sont les caractères à problème et existe t-il une solution propre pour y
remédier ?


Seb,

Me suis retrouvé face à un problème similaire dans lequel il s'agissait
de filtrer les données en vue de peupler une base MySQL.

Le problème résidait (plutôt, réside toujours) principalement, comme il
me semble que c'est ton cas, dans l'incompatibilité entre les jeux de
caractères win-1252 (et d'autres win-xxxx) avec iso-8859-1.

Je m'en étais sorti en mappant chacun des caractères du jeu cp-1252
situés dans la zone réservée (selon iso-8859-1) par leur équivalent
Unicode. Voici ce que ça donnait :

// Tableaux des caracteres speciaux Windows (cp-1252)
// dans la zoneinterdite 128-159

$inWinSpeChars = array(
chr(128), // euro
chr(129),
chr(130), // ** guillemet simple bas 9
chr(131), // florin
chr(132), // ** guillemet double bas 9
chr(133), // ellipse
chr(134), // obele
chr(135), // obele double
chr(136),
chr(137), // pour mille
chr(138), // S caron
chr(139), // chevron simple gauche
chr(140), // OE ligature
chr(141),
chr(142), // Z caron
chr(143),
chr(144),
chr(145), // ** guillemet simple haut 6
chr(146), // ** guillemet simple haut 9
chr(147), // ** guillemet double haut 6
chr(148), // ** guillemet double haut 9
chr(149), // point milieu
chr(150), // tiret n
chr(151), // tiret m
chr(152), // tilde
chr(153), // trademark
chr(154), // s caron
chr(155), // chevron simple droit
chr(156), // oe ligature
chr(157),
chr(158), // z caron
chr(159) // Y umlaut
);

$outWinSpeChars = array(
'&#8364;',
null,
"'",
'&#402;',
'&quot;',
'&#8230;',
'&#8224;',
'&#8225;',
'&#710;',
'&#8240;',
'&#352;',
'&#8249;',
'&#338;',
null,
'&#x17D;',
null,
null,
"'",
"'",
'&quot;',
'&quot;',
'&#183;',
'&#8211;',
'&#8212;',
'&#732;',
'&#8482;',
'&#353;',
'&#8250;',
'&#339;',
null,
'&#x17E;',
'&#376;'
);


// Test systeme agent utilisateur :
// si Windows, initialiser le drapeau $cp1252

$cp1252 = (eregi('windows', $_SERVER['HTTP_USER_AGENT'])) ? true:false;


// Filtrage de l'entrée

function filtrer($chaine)
{
if ($cp1252)
{
$chaine = strtr($chaine, $inWinSpeChars, $outWinSpeChars);
}
return $chaine;
}

Bon, c'est pas super robuste au niveau de la détection du système, mais
je n'ai pas trouvé mieux.

Si ça peut inspirer...

qça,

JJS.

Avatar
Etienne SOBOLE
J'ai compté 25 lignes dans cet exemple, alors qu'il y a 27 caractères
non grisés dans les lignes 80 et 90 de la page qui suit :
http://www.microsoft.com/globaldev/reference/sbcs/1252.htm


Merci pour ce lien.
il est tres utile...

Par contre, il donne la correspondance Unicode et non UTF-8... snif.
mais c'est deja plutot bien...

Etienne

Avatar
Seb
J'ai compté 25 lignes dans cet exemple, alors qu'il y a 27 caractères
non grisés dans les lignes 80 et 90 de la page qui suit :
http://www.microsoft.com/globaldev/reference/sbcs/1252.htm


Merci beaucoup !! Maintenant je les ai tous :)

Je suppose donc qu'il manque 2 traductions. Mais je ne peux pas te dire
lesquelles vu que, par définition, on ne peut pas les transmettre sur
usenet sans utiliser le codage propriétaire Microsoft ou utf-8, tous
deux interdits dans ce groupe.


Oui effectivement désolé !

Regarde quand même le bas de la page que je viens de citer. Elle
contient des lignes telles que celles-ci :

80 = U+20AC : EURO SIGN
82 = U+201A : SINGLE LOW-9 QUOTATION MARK
83 = U+0192 : LATIN SMALL LETTER F WITH HOOK
etc.

Il suffit de traduire les nombres en décimal pour avoir les bons codes.
Par exemple U+20AC = &#8364; pour l'euro (tiens, il fait partie des 2
qui manquent), U+201A = &#8218; (le premier de ta liste), U+0192 > &#402; (le second de ta liste), etc.


En faite il manquait :
8E = U+017D
9E = U+017E

Tout mes remerciements,

Séb

Avatar
Olivier Miakinen

J'ai compté 25 lignes dans cet exemple, alors qu'il y a 27 caractères
non grisés dans les lignes 80 et 90 de la page qui suit :
http://www.microsoft.com/globaldev/reference/sbcs/1252.htm


Merci pour ce lien.
il est tres utile...

Par contre, il donne la correspondance Unicode et non UTF-8... snif.
mais c'est deja plutot bien...


Il faut tout te faire ! :-)

http://people.w3.org/rishida/scripts/uniview/conversion.fr.html

Dans la case en haut à gauche, tu tapes :
20AC 201A 0192 201E 2026 2020 2021 02C6 2030 0160
2039 0152 017D 2018 2019 201C 201D 2022 2013 2014
02DC 2122 0161 203A 0153 017E 0178

Un petit coup de tabulation, et les autres cases se remplisssent. Par
exemple, la case juste en dessous :
E2 82 AC E2 80 9A C6 92 E2 80 9E E2 80 A6 E2 80 A0 E2 80 A1 CB 86 E2 80
B0 C5 A0 E2 80 B9 C5 92 C5 BD E2 80 98 E2 80 99 E2 80 9C E2 80 9D E2 80
A2 E2 80 93 E2 80 94 CB 9C E2 84 A2 C5 A1 E2 80 BA C5 93 C5 BE C5 B8

Bon, d'accord, c'est un peu dur de savoir où sont les limites des
caractères. Alors tu insères un 0 entre chaque numéro hexa de la case du
haut, qui se retrouvent sous forme de 00 en dessous. Tu remplaces les 00
par des espaces, et tu obtiens :

E2 82 AC E2 80 9A C6 92 E2 80 9E E2 80 A6 E2 80 A0 E2
80 A1 CB 86 E2 80 B0 C5 A0 E2 80 B9 C5 92 C5 BD E2
80 98 E2 80 99 E2 80 9C E2 80 9D E2 80 A2 E2 80 93 E2
80 94 CB 9C E2 84 A2 C5 A1 E2 80 BA C5 93 C5 BE C5
B8

C'est suffisant, ou il te les faut en décimal ? ;-)
(oui, je vais essayer de trouver le temps de le faire aussi, et en faire
une page web).

--
Olivier
(et avec ça, 100 balles et un mars ?)


Avatar
Olivier Miakinen

// Tableaux des caracteres speciaux Windows (cp-1252)
// dans la zoneinterdite 128-159

$inWinSpeChars = array(
chr(128), // euro
chr(129),
chr(130), // ** guillemet simple bas 9
[...]
chr(158), // z caron
chr(159) // Y umlaut
);


Cette façon de spécifier les caractères me semble la meilleure. Elle est
à la fois lisible et immune aux changements d'encodage du programme PHP
lui-même.

$outWinSpeChars = array(
'&#8364;',
null,
"'",
'&#402;',
'&quot;',
[...]


Ok pour les entités sous forme de nom (&quot;) ou de numéro décimal
(&#8364; ou &#402;).

En revanche :
'&#x17D;',
'&#x17E;',


Ces numéros en hexa ne seront pas reconnus par certains navigateurs.
Les remplacer par &#381; et &#382; respectivement.

Olivier

Avatar
Etienne SOBOLE
"Olivier Miakinen" <om+ a écrit dans le message de news:
c88p7e$5un$
Il faut tout te faire ! :-)


Ouai c'est vrai, mais hier je rentrai d'un week end à la mer ;)
Tous mes neuronnes étaient encore endormis par la forte calorimetrie
(pré-)estivale actuelle...

http://people.w3.org/rishida/scripts/uniview/conversion.fr.html


ah oui...

C'est suffisant, ou il te les faut en décimal ? ;-)


Non ca ca aller.
encore que si t'as envie de coder un nouveau module PHP pour encore les
caractères windows en UTF-8, faut pas ce génrer :) (je plaisante !!!)

(oui, je vais essayer de trouver le temps de le faire aussi, et en faire
une page web).


Merci en tout cas....
Etienne

Avatar
Olivier Miakinen

http://people.w3.org/rishida/scripts/uniview/conversion.fr.html


encore que si t'as envie de coder un nouveau module PHP pour encore les
caractères windows en UTF-8, faut pas ce génrer :) (je plaisante !!!)


Ce qui me surprend, c'est que tu aies besoin de coder en utf-8
spécifiquement les caractères windows.

Je suppose que ta page, si elle contient un euro microsoft, doit
contenir aussi au moins un e avec accent aigu ou un a avec accent grave.
Donc, si tu dois traduire toi-même le 80 (¤ win-1252) en E2 82 AC (¤
utf-8), alors tu dois aussi traduire le E9 (é iso-8859-1 ou win-1252) en
C3 A9 (é utf-8). Me trompé-je ?


Avatar
Seb

Bonjour,

Jusque là pas de problème avec la grande majorités des caractères
(&<>éèà...) mais je me suis aperçu : qu'avec celui-ci par exemple :
right



single quote mark 92 &#146; &rsquo; --> '
Ni htmlspecialchars ou htmlentities et ni utf8_encode l'encode


Pour vérification : même en jouant avec ENT_QUOTES etc... ?


Aucune chance, à mon avis.

En revanche, si le caractère est mis en dur (un seul octet de valeur
146, au lieu des six octets /&/#/1/4/6/;/), alors la fonction iconv avec
'CP1252' comme code d'entrée devrait fonctionner.
<http://fr2.php.net/manual/fr/ref.iconv.php>


J'ai essayé avec "Windows-1252" ou avec "CP1252" :
utf8_encode(iconv("Windows-1252", "ISO-8859-1", htmlspecialchars($txt))).
Mais le résultat n'est pas correcte ! j'ai des coupures de texte dès qu'il y
a des caractères spéciaux, mais je me suis peut-être planté.

Mon rêve aurait été de faire un : iconv(mb_http_input(), "UTF-8",
htmlspecialchars($txt))
Malheureusement le fonctionnement de mb_http_input() semble assez peu
fiable.

Comment faire pour encoder de manière "automatique" en utf-8 un
questionnaire par un utilisateur quelque soit le charset qu'il utilise ?

D'avance merci,

Séb



1 2 3 4