Questo è un problema davvero strano. Mi ci è voluto praticamente tutto il giorno per ridurlo a un piccolo script eseguibile che dimostra pienamente il problema.Corruzione delle stringhe e caratteri non stampabili utilizzando XML :: Twig in Win32 Perl
Problema Sommario: sto usando XML::Twig per tirare un frammento di dati da un file XML, quindi sto attaccando i dati snippet nel bel mezzo di un altro pezzo di dati, chiamiamolo dati padre. All'inizio, i dati principali hanno questo strano carattere non stampabile all'inizio. Sono dati forniti dal fornitore, quindi non posso controllarlo. Il mio problema è che dopo aver inserito lo snippet di dati nel mezzo dei dati principali, il prodotto finale ha un nuovo carattere nuovo non stampabile all'inizio, oltre a quello avviato originariamente. Questo nuovo carattere non stampabile non si trovava né nei dati padre né nello snippet di dati figlio. Non so da dove viene, né come si inseriscono nei miei dati.
Sono dubbioso che si tratti di un errore XML :: Twig perché la corruzione della stringa si verifica durante la lettura di una riga da un filehandle in un ciclo while, ma non sono riuscito a ricreare il mio problema quando rimuovo l'XML: : Codice Twig nei miei script, quindi ho dovuto lasciarlo.
Questa è la mia prima esperienza con caratteri non stampabili nelle stringhe che sto tentando di elaborare. Devo fare qualcosa di speciale invece di trattarli come stringhe ordinarie o qualcosa del genere?
Utilizzo ActiveState Perl 5.10.1 e XML :: Twig 3.32 (più recente) e l'IDE Eclipse 3.5.1 su Windows XP.
Ecco uno script che illustra il problema:
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;
}
Quando ho eseguito questo script, ottengo il seguente output:
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
si può vedere il carattere aggiuntivo che è stato aggiunto alla davanti ai dati proprio sotto la M in MODIFICATO.
I dati tornano direttamente all'applicazione di un fornitore, quindi il carattere speciale non stampabile nella parte anteriore dei dati deve rimanere esattamente come originariamente. –
In questo caso 'keep_encoding' dovrebbe fare il lavoro. – mercator