1

XML :: Codeを使用して、CGIモジュールを介して受信したGETパラメーターからXMLデータを作成しています。Webサーバーは文字セットがUTF-8に設定されたApacheであり、送信フォームは

<!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を呼び出すと、出力(firebugからコピーされたもの)は次のようになります。

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

CGIからbinmode(STDOUT、 ":utf8")を削除すると、探しているものが得られます

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

これでこの問題を解決する方法がわかりましたが、すべてをUTF-8に設定する場合は安全だと思いました。そうでなければ、もっと多くのテストを意味するでしょう。それはperlライブラリまたは私の考えのバグですか?

最高、マーカス

4

1 に答える 1

0

私は次の行だと思います:

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

役に立たないかもしれません。utf8 :: upgradeは、文字列に対してインプレース操作を実行した後、オクテットの数を返します。そのままにしておくと:

$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でöを表す2バイトです。スクリプトが最初にそれを印刷するとき、PerlはこれがUTF-8にあることを示していませんが、印刷する前に最初に変換する必要があることを知っています(binmodeのため)。

Perlのデフォルトの動作は、文字列として解釈されるオクテットのストリームがLatin-1としてエンコードされていると想定することです。したがって、最初のバイトC3を取得し、Latin-1で何であるかを検索してから、STDOUTと同等のUTF-8を出力します。B6についても同じです。ウィキペディアでバイトを再確認できます。

ただし、decodeを呼び出すと、バイトがUTF-8として解釈され、文字öで構成される新しい文字列が作成されます。文字列をエンコーディングとは考えないでください。出入りするバイトにはエンコードが必要ですが、プログラムでは、正しく解釈されると、それらは単なる文字列になります。

Perlはこれらのバイトを解釈し、必要な内部エンコーディングを使用してエンコードされた文字列に変換したので、次にそれを印刷するときに、文字をUTF-8に変換することがわかり、正しい出力が得られます。

それがCGIのデバッグに役立つことを願っています。

于 2012-10-07T13:11:44.837 に答える