문제

이것은 정말 이상한 문제입니다. 문제를 완전히 보여주는 작은 실행 가능한 스크립트로 휘젓는 데 실제로 하루 종일 걸렸습니다.

문제 요약 : 사용 중입니다 XML :: Twig XML 파일에서 데이터 스 니펫을 가져 오려면 해당 데이터 스 니펫을 다른 데이터의 중간에 고수하고 부모 데이터라고합시다. 학부모 데이터는 시작할 때 처음 에이 이상한 인쇄 할 수없는 캐릭터가 있습니다. 공급 업체가 제공 한 데이터이므로 제어 할 수 없습니다. 내 문제는 데이터 스 니펫을 부모 데이터의 중간에 붙인 후에 최종 제품에 새로운 처음에는 인쇄 할 수없는 캐릭터 외에 원래 시작한 캐릭터입니다. 이 새로운 인쇄 할 수없는 캐릭터는 부모 데이터 나 아동 데이터 스 니펫에 있지 않았습니다. 나는 그것이 어디에서 왔는지, 어떻게 내 데이터에 들어가고 있는지 모른다.

the while 루프의 파일 핸들에서 줄을 읽는 동안 문자열 손상이 발생하기 때문에 xml :: 나뭇 가지 버그라는 것이 의심 스럽지만 xml :: Twig 코드를 제거 할 때 문제를 재현하는 데 실패했습니다. 내 스크립트를 남겨 두어야했습니다.

이것은 내가 처리하려는 문자열에서 인쇄 할 수없는 캐릭터에 대한 첫 경험입니다. 평범한 끈이나 무언가처럼 취급하는 대신 특별한 일을해야합니까?

Windows XP에서 ActiveState Perl 5.10.1 및 XML :: Twig 3.32 (최신) 및 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

수정 된 M의 바로 아래 데이터 앞에 추가 된 추가 문자를 볼 수 있습니다.

도움이 되었습니까?

해결책

그것은 문자에 대한 ISO-8859-1에서 UTF-8 인코딩 변환을 수행했습니다. \xBF -> \xC2\xBF.

XML :: Twig는 모든 입력을 UTF-8로 변환합니다 (여기를 봐).

Twig에게 입력 인코딩을 사용하여 keep_encoding 옵션 (XML :: Twig FAQ 참조 : 내 XML 문서/데이터는 유니 코드를 통화하지 않는 도구에 의해 생성되며, xml :: Twig가 도와 드릴까요?).

그러나 아마도 UTF-8을 유지하거나 정확히 무엇을 할 것인지에 따라 UTF-8을 유지하거나 조용히 캐릭터를 떨어 뜨리는 것이 더 나을 것입니다.

다른 팁

나는 당신의 코드를 실제로 이해할 수 없지만, 신속하게 디버깅하기에는 너무 복잡하지만 문제는 BOM과 관련이있을 수 있습니다 ( 유니 코드 BOM FAQ) XML 문서의 시작 부분에서 무시되지만 다른 문서의 중간에 복사 한 경우에는 그렇지 않습니까? XBF 값 때문에 여기에서 추측하면 UTF-8 문서의 BOM의 일부입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top