これは本当に奇妙な問題です。それは問題を完全に示す小さな実行可能なスクリプトに徹底的に減らすために、私は実際上一日かかる。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の直下にあるデータの正面。
データはベンダーのアプリケーションに直接戻されます。そのため、データの前面にある特殊な印刷不可能な文字は元のとおりに正確に保持する必要があります。 –
その場合、 'keep_encoding'はジョブを行うべきです。 – mercator