2009-11-09 5 views
5

これは本当に奇妙な問題です。それは問題を完全に示す小さな実行可能なスクリプトに徹底的に減らすために、私は実際上一日かかる。Win32 PerlでXML :: Twigを使用した文字列の破損と印刷できない文字

問題の概要:私は、私は、データがデータの別の部分の中央にスニペットことこだわってる、XMLファイルからのデータの断片をプルするXML::Twigを使用していますが、のは親のデータを呼び出してみましょう。私が始めたとき、親データにはこの奇妙な印刷不可能な文字が最初にあります。ベンダー提供のデータなので、制御できません。私の問題は、親データの途中にデータスニペットを貼り付けた後、元のデータで始まったものに加えて、新しい印刷不可能な文字が冒頭にあることです。この新しい印刷不可能な文字は、親データまたは子データスニペットのいずれにもありませんでした。私はどこから来ているのか、どのように自分のデータに入っているのか分かりません。

whileループでファイルハンドルから行を読み込んでいるときに文字列の破損が発生するため、XML :: Twigのバグではないかと疑いがありますが、XMLを削除すると問題が再現できませんでした。 :私のスクリプトの小枝のコードは残しておく必要がありました。

これは私が処理しようとしている文字列に印刷できない文字が入った私の最初の経験です。普通の弦などのように扱う代わりに、特別なことをする必要がありますか?

私はActiveState Perl 5.10.1とXML :: Twig 3.32(最新)とWindows XP上のEclipse 3.5.1 IDEを使用しています。ここで

は、問題を示しスクリプトです:

use strict; 
use warnings; 
use XML::Twig; 

my $FALSE = 0; 
my $TRUE = 1; 
my $name = 'KurtsProgram'; 
my $task = 'MainTask'; 
my $hidden_char = "\xBF"; 
my $data = $hidden_char . 
'(********************************************* 
    Data-File-Header-Junk 
**********************************************) 

    PROGRAM MainProgram() 
    END_PROGRAM 

    TASK SecondaryTask() 
    END_TASK 

    TASK MainTask() 
     MainProgram; 
    END_TASK 
'; 
my $new_data = insertProgram($name, $task, $data); 

# test to see if results start out as expected 
if ($new_data =~ m/^\Q$hidden_char\E/) { 
    print "SUCCESS\n"; 
} 
else { 
    print STDERR "ERROR: What happened?\n"; 
    print STDERR "ORIGINAL: \n$data\n"; 
    print STDERR "MODIFIED: \n$new_data\n"; 
} 

sub insertProgram { 
    my ($local_name, $local_task, $local_data) = @_; 

    # get program section from XML template 
    my $twig = new XML::Twig; 
    $twig->parse('<?xml version="1.0"?> 
<TemplateSet> 
    <PROGRAM>PROGRAM <Name>ProgramNameGoesHere</Name>() 
    END_PROGRAM</PROGRAM> 
    <TASK>TASK <Name>TaskNameGoesHere</Name>() 
    END_TASK</TASK> 
</TemplateSet> 
'); 
    my $program = $twig->root->first_child('PROGRAM'); 

    # replace program name in XML template 
    $program->first_child('Name')->set_text($local_name); 
    my $insert = $program->text(); 

    # stick modified program into data 
    if ($local_data =~ s/(\s+PROGRAM\s+[^\s]+\s+\()/\n\n $insert $1/) { 
     # found it and inserted new program 
    } 
    else { 
     # not found 
     return; 
    } 

    # add program name to task list 
    my $added_program_to_task = $FALSE; 
    my $found_start = $FALSE; 
    my $found_end = $FALSE; 
    my $new_data = ""; 
    # open string as a filehandle for line by line processing 
    my $filehandle; 
    open($filehandle, '<', \$local_data) 
     or die("Can't open string as a filehandle: $!"); 
    while (defined (my $line = <$filehandle>)) { 
     # look for start of our task 
     if ( 
       (!$found_start) && 
       ($line =~ m/\s+TASK\s+\Q$local_task\E\s+\(/) 
      ) { 
      # found the task! 
      $found_start = $TRUE; 
     } 

     # look for end of our task 
     if (
       ($found_start) && (!$found_end) && 
       ($line =~ m/\s+END_TASK/) 
      ) 
     { 
      # found the end tag for the task section! 
      $found_end = $TRUE; 

      # add the program name to the bottom of the list 
      $line = "  " . $local_name . ";\n" . $line; 
      $added_program_to_task = $TRUE; 
     } 

     # compile new data from processed line or original line 
     $new_data = $new_data . $line; 
    } 
    close($filehandle); 

    if ($added_program_to_task) { 
     # success 
    } 
    else { 
     # unable to find task 
     return; 
    } 

    return $new_data; 
} 

私はこのスクリプトを実行すると、私は次のような出力が得られます。

ERROR: What happened? 
ORIGINAL: 
¿(********************************************* 
     Data-File-Header-Junk 
    **********************************************) 

     PROGRAM MainProgram() 
     END_PROGRAM 

     TASK SecondaryTask() 
     END_TASK 

     TASK MainTask() 
      MainProgram; 
     END_TASK 

MODIFIED: 
¿(********************************************* 
     Data-File-Header-Junk 
    **********************************************) 

     PROGRAM KurtsProgram() 
     END_PROGRAM 

     PROGRAM MainProgram() 
     END_PROGRAM 

     TASK SecondaryTask() 
     END_TASK 

     TASK MainTask() 
      MainProgram; 
      KurtsProgram; 
     END_TASK 

あなたがに追加された余分な文字を見ることができますMODIFIEDのMの直下にあるデータの正面。

答えて

7

\xBF - >\xC2\xBFという文字に対して、ISO-8859-1からUTF-8へのエンコード変換が行われています。

XML :: Twigはすべての入力をUTF-8(see here)に変換します。

keep_encodingオプションを使用して入力エンコーディングを保持するようにTwigに指示できます(XML :: Twig FAQ:My XML documents/data are produced by tools that do not grok Unicode, will XML::Twig help me there?も参照してください)。

しかし、おそらく、UTF-8をそのまま使用する方が良いでしょう。また、正確に何をしようとしているのかによっては、文字を静かに落とす方がよいでしょう。

+0

データはベンダーのアプリケーションに直接戻されます。そのため、データの前面にある特殊な印刷不可能な文字は元のとおりに正確に保持する必要があります。 –

+0

その場合、 'keep_encoding'はジョブを行うべきです。 – mercator

1

私は実際にあなたのコードを理解することはできませんが、それはまだ複雑すぎてすぐにデバッグすることはできませんが、XMLの始めに無視されるBOM(Unicode BOM FAQ参照)あなたが他の文書の真ん中にそれをコピーしても、それはできません。 xBF値のためにここで推測すると、それはUTF-8文書のBOMの一部です。

関連する問題