2011-03-19 113 views
1

我正在編寫一個Perl腳本,需要從XML文件中提取一些數據。Perl XML ::解析器編碼問題

XML文件本身使用UTF-8編碼。但是,出於某種原因,我從文件中提取的內容最終被編碼爲ISO-8859-1。該文檔指出,無論傳遞給我的處理程序應該是UTF-8,但它不是。

解析器基本上是這樣的:

my $parser = XML::Parser->new(Handlers => { 
    # Some unrelated handlers here 
    Char => sub { 
     my ($expat, $string) = @_; 
     if (exists $data->{$curId}{$curField}) { 
      $data->{$curId}{$curField} .= $string; 
     } else { 
      $data->{$curId}{$curField} = $string; 
     } 
    } , 
}); 

我曾嘗試以下變量的實際解析:

  • 文件直接通過$parser->parsefile,沒有選項解析;
  • 文件通過$parser->parsefile直接解析,ProtocolEncoding選項;
  • 使用open($handle , "<file.xml")打開文件,然後通過$parser->parse解析;
  • 使用open($handle , '<:utf8' , "file.xml")打開文件,然後通過$parser->parse解析。

此外,我已經嘗試過每個版本有和沒有<?xml encoding="utf-8"?>頭在文件中。

在所有情況下,最終在$data->{$curId}{$curField}中使用ISO-8859-1進行編碼。

我在做什麼錯?

+3

剛剛嘗試過,似乎爲我工作得很好(在WinXP上的ActivePerl 5.12)。你可以檢查'$ string'是否被標記爲UTF-8,使用utf8; UTF8 :: is_utf8($字符串)'。如果你確實如此,那麼隨後的處理可能會出現問題。 – bvr 2011-03-19 11:33:23

+8

你確定它是ISO-8859-1嗎?你是怎麼測試這個的?因爲如果您在任何未以utf-8模式打開的文件(例如STDOUT或STDERR)上使用'print',並且您的字符在ISO-8859-1範圍內,那麼默認情況下Perl會將它們轉換爲ISO-8859-1爲了兼容性)。您可以使用'binmode STDOUT':utf8「'來確保轉換不會發生在STDOUT上。 – mirod 2011-03-19 11:36:20

+0

確實是這個問題 - 我不知道我必須改變STDOUT的模式,並假定它跟隨我的語言環境設置。多謝你們。 – 2011-03-19 11:54:16

回答

1

我知道你已經在評論中找到了Michel的回答,但我會添加一些內容。使用任何編碼,您必須嚴格瞭解您正在接收的內容以及您發送的內容。如果你需要什麼,不要依賴環境;最終別人會使用你的程序,並有一個搞砸的環境。

閱讀文件時,請勿使用':utf8'圖層。這不關心,如果八位字節實際上是UTF-8:

open my $fh, '<:encoding(UTF-8)', $filename or ...; 

無論你認爲你的輸出句柄是什麼,請明確設置它。有多種方法可以做到這一點:

use open ':encoding(utf8)'; 

在命令行,你可以使用-c開關與S標誌,使標準處理UTF-8:

perl -CS input.xml 

湯姆克里斯汀森has a long list of things you need to pay attention to

+0

謝謝 - 更多信息絕不是壞事:) – 2011-08-11 06:45:40

0

$data->{$curId}{$curField}是否有utf8標誌?

如果您將utf8標誌打開的字符串與utf8標誌關閉的字符串連接,則Perl將後者轉換爲Unicode。這是問題的常見來源。