通过PHP使用XSLT的UTF-8编码问题

通过PHP使用XSLT的UTF-8编码问题,php,xslt,encoding,utf-8,Php,Xslt,Encoding,Utf 8,在通过PHP通过XSLT转换XML时,我面临着一个棘手的编码问题 这个问题可以概括/简化如下:当我使用XSLT样式表复制(UTF-8编码的)XHTML文件时,一些字符显示错误。当我只显示相同的XHTML文件时,所有字符都正确地显示出来 以下文件说明了该问题: XHTML 编码测试 这就是我们的工作方式ïßπλǽ ‘特殊字符’ XSLT PHP load($xml\u文件); $xsl_doc=新的DOMDocument('

在通过PHP通过XSLT转换XML时,我面临着一个棘手的编码问题

这个问题可以概括/简化如下:当我使用XSLT样式表复制(UTF-8编码的)XHTML文件时,一些字符显示错误。当我只显示相同的XHTML文件时,所有字符都正确地显示出来

以下文件说明了该问题:

XHTML

编码测试
这就是我们的工作方式ïßπλǽ ‘特殊字符’

XSLT

PHP
load($xml\u文件);
$xsl_doc=新的DOMDocument('1.0','utf-8');
$xsl\u doc->load($xsl\u文件);
$xp=新的XsltProcessor();
$xp->importStylesheet($xsl\u doc);
//alllow使用bypass=true请求参数绕过XSLT转换
如果($bypass=$\u GET['bypass'])){
echo file_get_内容($xml_文件);
}
否则{
echo$xp->transformToXML($xml\u-doc);
}
?>
当这样调用此脚本时(例如通过),转换后的XHTML文档中的所有字符都显示为ok,除了‘;和’;字符实体(它们是打开和关闭单引号)。我不是Unicode专家,但有两件事让我印象深刻:

  • 所有其他字符实体的解释都是正确的(这可能意味着
    ‘;
    ’;
    的UTF-8属性)
  • 然而,当XHTML文件以非中介方式显示时(例如,通过),所有字符都会正确显示
  • 我想我已经在任何可能的地方为输出声明了UTF-8编码。其他人是否知道什么是错的并且可以纠正

    提前谢谢

    罗恩·范登·布兰登
    没有可见的Unicode字符

    它们是单引号的旧HTML字符引用1,但当您使用XSLT处理器处理它们时,处理器看到的不是单引号,而是十进制代码为145和146的Unicode字符,即

    这些字符是私人使用的(即,Unicode联盟未定义用途)

    解决方案是使用正确的Unicode字符

    1事实上,这些代码映射到编码。它们通过浏览器显示,但实际上是:

    注意——上面的SGML声明与HTML2.0的声明类似, 指定字符号128到159(80到9F十六进制) 作为未使用的。这意味着数字字符引用 在该范围内(例如’;)在HTML中是非法的。ISO 8859-1和ISO 10646均不包含该格式的字符 范围,它是为控制字符保留的


    +1非常好的解释!对于其他字形参考,HTML5草案更进一步:“上述数字字符参考表单允许引用除U+0000、U+000D、永久未定义的Unicode字符(非字符)和除空格字符以外的控制字符以外的任何Unicode代码点。”呸,非常感谢!除了清楚的解释外,您还提供了一个有用的解决方案,真是太好了。
    <?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>
    
    <?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
      $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);
      }
    ?>