Это действительно странная проблема. Мне потребовался практически весь день, чтобы уничтожить его до небольшого исполняемого скрипта, который полностью демонстрирует проблему.Коррупция строк и непечатаемые символы с использованием XML :: Twig в Win32 Perl
Проблема Резюме: Я использую XML::Twig вытащить фрагмент данных из файла XML, то я придерживаюсь, что данные фрагмента кода в середину другой части данных, давайте назовем его родительскими данными. Родительские данные имеют этот странный непечатаемый символ в начале, когда я начинаю. Данные поставщика поставляются, поэтому я не могу его контролировать. Моя проблема заключается в том, что после того, как я прикрепляю фрагмент данных к середине родительских данных, у конечного продукта есть новый персонаж, не подлежащий печати, с самого начала в дополнение к тому, с которого он начинался первоначально. Этот новый непечатаемый символ не содержал ни родительские данные, ни детальный фрагмент данных. Я не знаю, откуда это происходит, и как он попадает в мои данные.
Я сомневаюсь, что это ошибка XML :: Twig, потому что повреждение строки происходит при чтении строки из дескриптора файла в цикле while, но я не увенчался успехом при восстановлении моей проблемы при удалении XML: : Код Twig в моих сценариях, поэтому мне пришлось оставить его.
Это мой первый опыт работы с непечатаемыми символами в строках, которые я пытаюсь обработать. Нужно ли мне делать что-то особенное вместо того, чтобы рассматривать их как обычные строки или что-то еще?
Я использую ActiveState Perl 5.10.1 и XML :: Twig 3.32 (последняя версия) и Eclipse 3.5.1 IDE в Windows XP.
Вот скрипт, который демонстрирует проблему:
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
Вы можете увидеть дополнительный символ, который был добавлен к перед данными прямо под M в MODIFIED.
Данные возвращаются обратно в приложение поставщика, поэтому особый непечатаемый символ в передней части данных должен оставаться таким, каким он был изначально. –
В этом случае 'keep_encoding' должен выполнять эту работу. – mercator