2012-10-07 44 views
1

我正在使用XML :: Code从通过CGI模块接收的GET参数创建一些XML数据。网络服务器是Apache加上字符集设置为UTF-8和提交表单是在页面上用Perl cgi和XML ::代码双重编码问题

<!DOCTYPE html> 
<html lang="en-GB"> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 

报头。该CGI看起来像这样:

use CGI; 
use Encode; 
use XML::Code; 
binmode(STDOUT, ":utf8"); 
binmode(STDIN, ":utf8"); 

my $cgi = CGI->new(); 
print $cgi->header(-type => "text/xml", -charset => "utf-8"); 
my $object = $cgi->param("object"); 
$object = decode("utf-8", utf8::upgrade($object)); 

my $content = XML::Code->new("formdata"); 
$content->version ("1.0"); 
$content->encoding ("UTF-8"); 

my $sub_content = XML::Code->new("object"); 
$sub_content->set_text($object); 
$content->add_child($sub_content); 

$sub_content = XML::Code->new("isutf"); 
$sub_content->set_text(utf8::is_utf8($object)); 
$content->add_child($sub_content); 

print $content->code(); 

当调用与http://mydomain.com/cgi-bin/formdata.pl?object cgi的= O的输出(从萤火虫复制)是

<?xml version="1.0" encoding="UTF-8"?> 
<formdata> 
    <object>ö</object> 
    <isutf>1</isutf> 
</formdata> 

卸下binmode(STDOUT, “:UTF8”)从CGI给我什么,我找

<?xml version="1.0" encoding="UTF-8"?> 
<formdata> 
    <object>ö</object> 
    <isutf>1</isutf> 
</formdata> 

现在我知道如何解决这个问题,但我认为一切都设置为UTF-8的时候我会很安全。如果我不是这将意味着更多的测试。这是在perl库或我的想法中的错误?

最佳, 马库斯

回答

0

我认为以下行:

$object = decode("utf-8", utf8::upgrade($object)); 

可能没有帮助。在对字符串进行就地操作之后,utf8 :: upgrade returns a number of octets。如果您将其保留为:

$object = decode("utf-8", $object); 

那么您可能会有更多可理解的行为。

我想我已经想通了,一点多用这种简短的脚本的帮助:

#! /usr/bin/perl -w 
use Encode; 
binmode(STDOUT, ":utf8"); 
my $string = "\x{C3}\x{B6}"; 
print "$string\n"; 
my $decoded = decode("UTF8", $string); 
print "$decoded\n"; 

的输出是:

ö 
ö 

因此,这里是我相信发生了什么。上面的$ string声明是您从调用cgi-> param返回的内容,也就是说它是两个字节,代表UTF-8中的ö。当脚本第一次打印它时,Perl没有指示这是UTF-8,但知道它必须在打印之前先将其转换(由于binmode)。

Perl的默认行为是假设将被解释为字符串的八位字节流编码为Latin-1。因此,它需要第一个字节C3查找它在Latin-1中的内容,然后打印出等同于STDOUT的UTF-8。 B6一样。您可以仔细检查Wikipedia上的字节。

但是,解码调用会将字节解释为UTF-8并创建一个由字符ö组成的新字符串。不要认为字符串具有编码;进出的字节需要编码,但在你的程序中,一旦它们被正确解释,那么它们就是字符串。

现在,Perl已经解释了这些字节并转换为使用任何内部编码进行编码的字符串,当您下一次打印出来时,它知道要将字符转换为UTF-8,并且您得到正确的输出。

希望能够帮助您调试CGI。

+0

感谢您的快速响应! – Marcus