2010-09-08 6 views
2

Je suis confronté à un problème de codage désagréable lors de la transformation de XML via XSLT via PHP.Problème de codage UTF-8 avec XSLT via PHP

Le problème peut être résumé/réduit de la façon suivante: lorsque je copie un fichier XHTML (codé en UTF-8) avec une feuille de style XSLT, certains caractères sont affichés incorrectement. Quand je montre juste le même fichier XHTML, tous les caractères sortent correctement.

Les fichiers suivants illustrent le problème:

XHTML

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE html 
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
    <head> 
     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
     <title>encoding test</title> 
    </head> 
    <body> 
     <p>This is how we d&#239;&#223;&#960;&#955;&#509; &#145;special characters&#146;</p> 
    </body> 
</html> 

XSLT

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0"> 

    <xsl:output method="xml" encoding="UTF-8"/> 

    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

PHP

<?php 
    $xml_file = 'encoding_test.xml'; 
    $xsl_file = 'encoding_test.xsl'; 

    $xml_doc = new DOMDocument('1.0', 'utf-8'); 
    $xml_doc->load($xml_file); 

    $xsl_doc = new DOMDocument('1.0', 'utf-8'); 
    $xsl_doc->load($xsl_file); 

    $xp = new XsltProcessor(); 
    $xp->importStylesheet($xsl_doc); 

    // alllow to bypass XSLT transformation with bypass=true request parameter 
    if ($bypass = $_GET['bypass']) { 
    echo file_get_contents($xml_file); 
    } 
    else { 
    echo $xp->transformToXML($xml_doc); 
    } 
?> 

Lorsque ce script est appelé en tant que tel (par exemple http://localhost/encoding_test/encoding_test.php), tous les caractères dans le document XHTML transformé sortent ok, sauf pour le & # 145; et & # 146; entités de caractères (ils ouvrent et ferment des guillemets simples). Je ne suis pas un expert Unicode, mais deux choses me frappent:

  1. toutes les autres entités de caractère sont interprétées correctement (ce qui pourrait impliquer quelque chose sur l'UTF-8-ness de &#145; et &#146;)
  2. encore, quand le fichier XHTML est affiché sans intermédiaire (par exemple http://localhost/encoding_test/encoding_test.php?bypass=true), tous les caractères sont affichés correctement.

Je pense que j'ai déclaré le codage UTF-8 pour la sortie partout où je pouvais. Est-ce que les autres voient peut-être ce qui ne va pas et peuvent être redressés?

Merci d'avance!

den Ron Van Branden

Répondre

10

&#145; et &#146; sont pas de caractères Unicode visibles.

Ils sont vieux références caractère HTML pour des guillemets simples, mais quand vous les processus à l'aide d'un processeur XSLT le processeur ne voit pas de guillemets, mais les caractères Unicode avec les codes décimaux 145 et 146, à savoir U+0090 and U+0091.

Ces caractères sont à usage privé (c'est-à-dire que l'utilisation n'est pas définie par le consortium Unicode) C1 control codes. La solution consiste à utiliser les caractères Unicode corrects &#x2018; et &#x2019;.

En fait, ce sont des codes qui correspondent au codage Windows-1252. Ils sont affichés par les navigateurs, mais ils sont en fait not valid in HTML:

NOTE - la déclaration SGML ci-dessus, comme celle de HTML 2.0, spécifie les caractères de 128 à 159 (80 à 9F hex) utilisé.Cela signifie que les références de caractère numérique dans cette plage (par exemple ’) sont illégales en HTML. Ni ISO 8859-1 ni ISO 10646 ne contiennent de caractères dans la plage , qui est réservée aux caractères de contrôle.

+0

+1 très bonne explication! Pour d'autres glyphes référence http://en.wikipedia.org/wiki/Quotation_mark_glyphs –

+0

Le HTML 5 projet va plus loin: « Les formes de référence de caractères numériques décrits ci-dessus sont autorisés à faire référence à tout point de code Unicode autre que U + 0000, U + 000D, caractères Unicode indéfinis (non-caractères) et caractères de contrôle autres que les caractères espace. " – Artefacto

+0

Ouf, merci beaucoup! Très gentil de votre part pour fournir une solution utile en plus d'une explication claire. – rvdb