字符编码问题,无法使用 PERL API 解码 HTML 实体



我现在要对编码方案发疯了。我将在下面陈述我的问题,请提供您的意见。

问题:我有一些输入字符串,如下面的代码中所述。最终所需的输出是"Křižovnická 190"。[ 你可以在这里解码它 ]。我正在使用perl模块来解码这些字符串。以下是我的测试代码:

use HTML::Entities;
binmode STDOUT,":utf8";
$a = "Křižovnická 190";
decode_entities($a);
print $a."n";

但是,我得到的输出是"Křiovnická 19",这意味着"ř"被正确解码,但"没有。我的问题是为什么?然后我尝试了"_decode_entities"方法,我们提供 entity2char 哈希,但仍然没有成功。

PS :我一定会在这里使用 Perl,因为其他遗留 API,请在这里帮助我

字符"ž"对应于Unicode中的ž,而不是ž。 158 是 cp1252 中"ž"的编码。

顺便说一句,克莱门汀很好。

为清楚起见:

| Grapheme   |         ř         |         ž         |
|------------+-------------------+-------------------|
| Codepoint  | U+0159 (345)      | U+017E (382)      |
| Escape     | ř (ř) | ž (ž) |
|------------+-------------------+-------------------|
| UTF-8      | C5 99 (197 153)   | C5 BE (197 190)   | 
| cp1252     | -                 | 9E    (158)       |
| latin2     | F8    (248)       | BE    (190)       |

更新:

有关详细信息,请参阅维基百科上的 HTML 十进制字符呈现。重要的部分是:

(...) 对字符 128–159

的引用通常由宽松的 Web 浏览器解释为对 Windows-1252 字符编码中分配给字节 128–159(十进制)的字符的引用。这违反了 HTML 和 SGML 标准,并且字符已经分配给更高的代码点,因此 HTML 文档作者应始终使用更高的代码点。例如,对于商标标志 (™),请使用 ™ ,而不是 ™

ž

是指"ž"。 它是 U+009E 隐私消息,一个控制字符。(15810 = 9E16

"ž"是 U+017E 拉丁小写字母 Z 和卡隆,所以转义将是žž

某些 Web 浏览器错误地解释 80..9F 16 (128..15910) 中值为 of 的数字实体,将该数字视为 Unicode 代码点的Windows-1252 编码。

| Grapheme           |         ř         |         ž         |
+--------------------+-------------------+-------------------+
| Unicode Code Point | U+0159 (345)      | U+017E (382)      |
| Escape             | ř (ř) | ž (ž) |
+--------------------+-------------------+-------------------+
| cp1252 encoding    | ---               | 9E (158)          |
| Alternate escape*  | ---               | ž (ž)   |
* — Non-standard and buggy behaviour.

这种错误的行为是您想要的。我没有看到实现该行为的模块,因此我们必须编写自己的代码。

use strict;
use warnings;
use open ':std', ':encoding(UTF-8)';
use HTML::Entities qw( );
use Encode         qw( decode );
{
    my %fixes =
        map { chr($_) => decode('cp1252', chr($_)) }
          0x80..0x9F;
    sub decode_entities {
        my $s_ref = defined(wantarray())
            ? do { my ($s) = @_; $s }
            : $_[0];
        $$s_ref =~ s{(
            &#
            (?: 0*([1-9][0-9]*);?
            |   x0*([1-9A-Fa-f][0-9A-Fa-f]*);?
            )
        )}{
            if (defined($2) && length($2) == 3 && exists($fixes{chr($2)})) {
               $fixes{chr($2)}
            } elsif (defined($3) && length($3) == 2 && exists($fixes{chr(hex($3))})) {
               $fixes{chr(hex($3))}
            } else {
               $1
            }
        }exg;
        HTML::Entities::decode_entities($$s_ref);
        return $$s_ref;        
    }
}
print(decode_entities("Křižovnická 190"), "n");

最新更新