【问题标题】:UTF-8 encoding problem with XSLT via PHP通过 PHP 使用 XSLT 的 UTF-8 编码问题
【发布时间】:2010-09-08 10:07:16
【问题描述】:

在通过 PHP 通过 XSLT 转换 XML 时,我遇到了一个令人讨厌的编码问题。

问题可以总结/归纳如下:当我使用 XSLT 样式表复制(UTF-8 编码的)XHTML 文件时,某些字符显示错误。当我只显示同一个 XHTML 文件时,所有字符都正确显示。

以下文件说明了问题:

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);
  }
?>

当这个脚本被这样调用时(通过例如http://localhost/encoding_test/encoding_test.php),转换后的 XHTML 文档中的所有字符都正常,除了 ‘和 ’字符实体(它们是打开和关闭单引号)。我不是 Unicode 专家,但有两件事让我印象深刻:

  1. 所有其他字符实体都被正确解释(这可能暗示 &amp;#145;&amp;#146; 的 UTF-8 特性)
  2. 然而,当 XHTML 文件直接显示时(例如通过http://localhost/encoding_test/encoding_test.php?bypass=true),所有个字符都会正确显示。

我想我已经在任何可能的地方为输出声明了 UTF-8 编码。其他人可能看到了什么是错误的并且可以纠正吗?

提前致谢!

罗恩·范登·布兰登

【问题讨论】:

    标签: php xslt encoding utf-8


    【解决方案1】:

    &amp;#145;&amp;#146; 不是可见的 Unicode 字符。

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

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

    解决方案是使用正确的 Unicode 字符 &amp;#x2018;&amp;#x2019;

    1其实这些都是映射到Windows-1252编码的代码。它们由浏览器显示,但实际上是not valid in HTML:

    注意——上面的 SGML 声明,和 HTML 2.0 一样, 指定字符编号 128 到 159(80 到 9F hex) 未使用。这意味着数字字符引用 在该范围内(例如 ')在 HTML 中是非法的。 ISO 8859-1 和 ISO 10646 都不包含其中的字符 范围,为控制字符保留。

    【讨论】:

    • +1 很好的解释!其他字形参考en.wikipedia.org/wiki/Quotation_mark_glyphs
    • HTML 5 草案更进一步:“上述数字字符引用形式允许引用除 U+0000、U+000D、永久未定义的 Unicode 字符(非字符)和空格字符以外的控制字符。”
    • 唷,非常感谢!非常感谢您提供一个有用的解决方案,除了一个清晰的解释。
    猜你喜欢
    • 1970-01-01
    • 2010-12-15
    • 1970-01-01
    • 2010-11-26
    • 1970-01-01
    • 1970-01-01
    • 2010-12-01
    • 1970-01-01
    相关资源
    最近更新 更多