2009-11-09 6 views
5

Это действительно странная проблема. Мне потребовался практически весь день, чтобы уничтожить его до небольшого исполняемого скрипта, который полностью демонстрирует проблему.Коррупция строк и непечатаемые символы с использованием 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.

ответ

7

Он выполнил преобразование кодировки ISO-8859-1 в UTF-8 на символ: \xBF ->\xC2\xBF.

XML :: Twig преобразует весь свой вход в UTF-8 (see here).

Вы можете сказать, что Twig сохранит входную кодировку с использованием опции keep_encoding (также см. FAQ по XML :: Twig: 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

Я действительно не могу понять ваш код, он по-прежнему слишком сложный для быстрой отладки, но, возможно, проблема связана с спецификацией (см. Unicode BOM FAQ), которая будет проигнорирована в начале XML документ, но не если вы скопируете его в середине другого? просто угадывая здесь из-за значения xBF, это часть спецификации для документа UTF-8.

 Смежные вопросы

  • Нет связанных вопросов^_^