如何将Unicode代码点转换为十六进制HTML实体?

3
我是一名有用的助手,可以为您翻译文本。
我有一个数据文件(确切地说,是苹果plist文件),其中包含Unicode 代码点,例如\U00e8\U2019。我需要使用PHP将它们转换为有效的十六进制HTML实体
我现在正在做的是一长串:
 $fileContents = str_replace("\U00e8", "è", $fileContents);
 $fileContents = str_replace("\U2019", "’", $fileContents);

这显然很糟糕。我可以使用正则表达式将\U和所有尾随的0s转换为&#x,然后添加尾随的;,但这似乎也太过武断。

有没有一种简洁明了的方法来将字符串中的所有Unicode代码点替换为HTML实体?


PCRE正则表达式非常快且安全,我会使用它们。(其他官方解决方案可能也会使用正则表达式。或者是查找表,这就是你现在拥有的东西。) - MvanGeest
2
根据此页面的说明,这些转义序列代表的是UTF-16代码单元,而不是Unicode代码点。这意味着如果它们形成了代理对,你可能需要组合两个连续的代码单元来形成一个HTML实体。 - Artefacto
2个回答

7
这是一个正确的答案,它考虑到了这些是代码单元而不是代码点,并且允许解码补充字符。
function unenc_utf16_code_units($string) {
    /* go for possible surrogate pairs first */
    $string = preg_replace_callback(
        '/\\\\U(D[89ab][0-9a-f]{2})\\\\U(D[c-f][0-9a-f]{2})/i',
        function ($matches) {
            $hi_surr = hexdec($matches[1]);
            $lo_surr = hexdec($matches[2]);
            $scalar = (0x10000 + (($hi_surr & 0x3FF) << 10) |
                ($lo_surr & 0x3FF));
            return "&#x" . dechex($scalar) . ";";
        }, $string);
    /* now the rest */
    $string = preg_replace_callback('/\\\\U([0-9a-f]{4})/i',
        function ($matches) {
            //just to remove leading zeros
            return "&#x" . dechex(hexdec($matches[1])) . ";";
        }, $string);
    return $string;
}

4
您可以使用 preg_replace 函数来实现此功能:
preg_replace('/\\\\U0*([0-9a-fA-F]{1,5})/', '&#x\1;', $fileContents);

测试正则表达式:

PS> 'some \U00e8 string with \U2019 embedded Unicode' -replace '\\U0*([0-9a-f]{1,5})','&#x$1;'
some &#xe8; string with &#x2019; embedded Unicode

似乎是正则表达式的一个明显用例。@Tina Marie,如果你需要更多的plist处理,请查看http://code.google.com/p/cfpropertylist/。 - Brandon Horsley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接