Choisir l'encodage de sortie d'un XSLT, et le vérifier
xsl:output encoding ne convertit pas toujours ce qu'on croit, et l'éditeur qui relit le fichier ment souvent sur le résultat.
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
Cette déclaration décide de deux choses, et de deux seulement : les octets que le sérialiseur écrit, et l'encodage annoncé dans la déclaration XML de tête. Elle ne dit rien de la lecture du document source, et 🔴 elle est ignorée quand ce n'est pas le sérialiseur qui écrit les octets.
C'est ce second cas qui produit les accents faux, et il est le seul des trois causes courantes qui laisse un fichier réellement corrompu.
Le piège du flux déjà encodé
Quand l'appelant fournit un Writer — un StringWriter, un OutputStreamWriter construit avec un
encodage —, la conversion caractères → octets a déjà été décidée en dehors de la feuille. Le
sérialiseur y écrit des caractères ; il n'a plus la main sur les octets.
⚠️ Mais il continue d'écrire la déclaration XML. Le fichier annonce donc encoding="UTF-8"
pendant que ses octets sont en CP1252 : un document qui ment sur lui-même, et que le prochain
analyseur rejettera ou lira de travers.
🔴 Le correctif tient en un mot : fournir un OutputStream, jamais un Writer. L'encodage
redevient la décision de xsl:output, et déclaration et octets ne peuvent plus diverger.
Les trois causes, et où elles se situent
| Cause | Où elle se situe | Le fichier est-il corrompu ? |
|---|---|---|
| source dont la déclaration ment sur son encodage | à l'entrée | oui, et souvent l'analyse échoue |
| sortie écrite via un flux déjà encodé | à la sérialisation | oui, et silencieusement |
| éditeur qui réinterprète le fichier | nulle part | non — seul l'affichage est faux |
⚠️ La troisième ligne fait perdre le plus de temps. L'éditeur devine l'encodage à l'ouverture, et il devine mal sur un fichier court ou peu accentué. Le fichier est correct, le rendu ne l'est pas, et on passe l'après-midi à corriger une feuille qui n'a rien.
Vérifier les octets, pas l'affichage
Le seul contrôle qui ne ment pas est le dump. Un é occupe deux octets en UTF-8 (c3 a9) et
un seul en Latin-1 (e9) :
head -c 200 sortie.xml | od -A d -t x1z
c3 a9avecencoding="UTF-8"déclaré : correct ;e9seul avecencoding="UTF-8"déclaré : le fichier ment, c'est le cas du flux déjà encodé ;c3 83 c2 a9: double encodage — les octets UTF-8 ont été relus comme du Latin-1 puis réencodés, et le fichier est passé deux fois par une conversion.
✅ Ces trois signatures se distinguent en un coup d'œil, et elles désignent chacune une cause différente. Aucune ne se lit dans un éditeur.
Ce que l'encodage ne règle pas
⚠️ Un caractère qui manque n'est pas un caractère mal encodé. Si la sortie perd du texte au lieu de l'abîmer, le problème est en amont : espaces conservés ou supprimés, modèle qui ne s'applique pas. Voir les espaces blancs, ou pourquoi la sortie a changé sans raison.
⚠️ Chaque document produit décide de son propre encodage. Un xsl:output global ne descend pas
dans les résultats secondaires : c'est le point détaillé dans
sorties multiples : ce que Saxon exige vraiment.
Ce que cet article ne couvre pas
method="html"et la balisemeta charsetque le sérialiseur injecte, qui ajoutent un troisième endroit où l'encodage est annoncé ;- les tables de caractères (
xsl:character-map), qui remplacent des caractères plutôt que de les encoder ; - l'indicateur d'ordre des octets (
byte-order-mark), utile en UTF-16 et nuisible en UTF-8 sur bien des chaînes de traitement.
Le chapitre transformer et exporter du manuel montre où se choisit le format de sortie et ce qui est écrit sur le disque.