2016-08-10 6 views
1

나는 Perl에 상대적으로 처음이다. 내가 뭘 잘못하고 있는지 확인하십시오.탭으로 구분 된 파일로 Perl에서 XML 작성하기

필자는 다음과 같은 입력 탭으로 구분 된 파일을 XML에 빌드해야합니다. 'pin'number는 고유 식별자입니다. 'PIN'이 일치하면 이 채워지고 보고서 아래에 여러 개의 'CHARGE'가 표시됩니다.

Reason1 Reason2 Reason3 Pin Name Zip Date Time 

data1 data2 data3 Pin 1 data5 data6 data7 data8 
data1 data2 data3 Pin 1 data5 data6 data9 data10 
data1 data2 data3 Pin 1 data5 data6 data11 data12 

는 나는 기본적으로 첫 번째 'CHARGE'는 다른 두하지 게재되고, XML

<XML_FILE> 
    <REPORT TYPE="AB"> 
    <REASON1>data1</REASON> 
    <REASON2>data2</REASON2> 
    <REASON3>data3</REASON3> 
    <PERSON> 
     <PIN>Pin 1</PIN> 
     <NAME>data5</NAME> 
     <ZIP>data6<ZIP> 
    </PERSON> 
    <CHARGE> 
     <DATE>data7</DATE> 
     <TIME>data8</TIME> 
    </CHARGE> 
    <CHARGE> 
     <DATE>data9</DATE> 
     <TIME>data10<TIME> 
    </CHARGE> 
    <CHARGE> 
     <DATE>data11</DATE> 
     <TIME>data12</TIME> 
    </CHARGE> 
    </REPORT> 
</XML_FILE> 


use strict; 
use XML::LibXML; 

my $READFILENAME = "SomeDir\\data.txt"; 
my $WRITEFILENAME = "SomeDir\\test.xml"; 

my $doc = XML::LibXML::Document->new('1.0'); 
my $root = $doc->createElement("XML_FILE"); 
open (FILEWRITE, ">$WRITEFILENAME"); 
open (READFILE, $READFILENAME); 
my $copy_person_pin = "XX"; 
foreach (<READFILE>) { 
    my $line = $_; chomp $line; 
    my @data = split(/\t/,$line); 
    my $reason1 = $data[0]; 
    my $reason2 = $data[1]; 
    my $reason3 = $data[2]; 
    my $person_pin = $data[3]; 
    my $name = $data[4]; 
    my $zip = $data[5]; 
    my $date = $data[6]; 
    my $time = $data[7]; 
    my $report = $doc->createElement("REPORT"); 
    if ($person_pin ne $copy_person_pin) 
    { 
     # Build the Report tags 
     # I had to put $report out of if loop so that $report is avalible in else statement 
     # my $report = $doc->createElement("REPORT"); 
     $report->setAttribute('TYPE'=>'AB'); 
     my @sortedReportTag = qw (REASON1 
       REASON2 
       REASON3 
       ); 

     my %reportHashTags; 
     @reportHashTags { @sortedReportTag } = ($reason1, 
        $reason2, 
        $reason3 
         );                    
     buildXMLElements(\@sortedReportTag, \%reportHashTags, $report); 

     $root-> appendChild($report); 

     # Build the element for Person Tag 
     my $person = $doc->createElement("PERSON"); 
     my @sortedPersonTag = qw (PIN 
       NAME 
       ZIP); 
     my %personHashTags; 
     @personHashTags { @sortedPersonTag } = ($person_pin, 
        $name, 
        $zip 
         ); 
     # Build the elements for Person Tag           
     buildXMLElements(\@sortedPersonTag, \%personHashTags, $person); 
     $report-> appendChild($person); 


     # Build the elements for Charge Tag 
     my $charge = $doc->createElement("CHARGE");  
     my @sortedChargeTag = qw (DATE 
       TIME 
       ); 
     my %chargeHashTags; 
     @chargeHashTags { @sortedChargeTag } = ($date, 
        $time 
        ); 
     # Build the elements for Charge Tag          
     buildXMLElements(\@sortedChargeTag, \%chargeHashTags, $charge); 
     $report-> appendChild($charge); 
     $copy_person_pin = $person_pin; 
    } 
    else { 
     my $charge = $doc->createElement("CHARGE");  
     my @sortedChargeTag = qw (DATE 
       TIME 
       ); 
     my %chargeHashTags; 
     @chargeHashTags { @sortedChargeTag } = ($date, 
        $time 
        ); 
     # Build the elements for Charge Tag          
     buildXMLElements(\@sortedChargeTag, \%chargeHashTags, $charge); 
     $report-> appendChild($charge); 
    } 
} 

$doc->setDocumentElement($root); 

# Write the XML to a file 
print FILEWRITE ($doc->toString()); 
close FILEWRITE; 

sub buildXMLElements() { 
    my($elementTags, $hashTags, $parentElement) = @_; 
    for my $name (@$elementTags) { 
    my $reportTag = $doc->createElement($name); 
    my $reportValue = $hashTags->{$name}; 
    $reportTag->appendTextNode($reportValue); 
    $parentElement->appendChild($reportTag); 
    } 
} 

내가 얻을 출력은 다음 구축하고자합니다.

<XML_FILE> 
<REPORT TYPE="AB"> 
    <REASON1>data1</REASON> 
    <REASON2>data2</REASON2> 
    <REASON3>data3</REASON3> 
    <PERSON> 
    <PIN>Pin 1</PIN> 
    <NAME>data5</NAME> 
    <ZIP>data6<ZIP> 
    </PERSON> 
    <CHARGE> 
    <DATE>data7</DATE> 
    <TIME>data8</TIME> 
    </CHARGE> 
    </REPORT> 
    </XML_FILE> 

@stevenl 감사합니다. 그러나 그것은 효과가 없습니다. 처음에 빈 $ report를 선언하면 스크립트가 실행되지만 두 번째 및 세 번째 요금이 계속 추가되지는 않습니다. 그것은 여전히 ​​위의 출력과 같습니다.

+0

내가 나를 – stevenl

+0

위대한 일 전체 코드를 추가! Stevenl it woks 고마워. 모든 노력을 주셔서 감사합니다 ... 나는 당신의 대답을 투표했습니다 :) – sannag

답변

1
  • 문제는 else 블록에 $report$root에 추가되지 않은 새로 생성 된 요소 것입니다.
  • 을 수행해야하는 것은 새로운 을 생성하는 대신 기존의 $report 요소를 재사용하는 것입니다.

그래서 나는 다음과 같이 코드를 수정 것 같습니다

use strict; 
use warnings; 
use XML::LibXML; 

my $READFILENAME = "data.txt"; 
my $WRITEFILENAME = "test.xml"; 

my $doc = XML::LibXML::Document->new('1.0'); 
my $root = $doc->createElement("XML_FILE"); 
open my $FILEWRITE, '>', $WRITEFILENAME; 
open my $READFILE, '<', $READFILENAME; 
my $copy_person_pin = "XX"; 
my $report; 
while (my $line = <$READFILE>) { 
    chomp $line; 
    my @data = split(/\s+/,$line); 
    my $reason1 = $data[0]; 
    my $reason2 = $data[1]; 
    my $reason3 = $data[2]; 
    my $person_pin = $data[3]; 
    my $name = $data[4]; 
    my $zip = $data[5]; 
    my $date = $data[6]; 
    my $time = $data[7]; 

    if ($person_pin ne $copy_person_pin) 
    { 
     $report = $doc->createElement("REPORT"); 
     # Build the Report tags 
     # I had to put $report out of if loop so that $report is avalible in else statement 
     # my $report = $doc->createElement("REPORT"); 
     $report->setAttribute('TYPE'=>'AB'); 
     my @sortedReportTag = qw (REASON1 
        REASON2 
        REASON3 
       ); 

     my %reportHashTags; 
     @reportHashTags { @sortedReportTag } = ($reason1, 
         $reason2, 
         $reason3 
          );                    
     buildXMLElements(\@sortedReportTag, \%reportHashTags, $report); 

     $root-> appendChild($report); 

     # Build the element for Person Tag 
     my $person = $doc->createElement("PERSON"); 
     my @sortedPersonTag = qw (PIN 
        NAME 
        ZIP); 
     my %personHashTags; 
     @personHashTags { @sortedPersonTag } = ($person_pin, 
         $name, 
         $zip 
          ); 
     # Build the elements for Person Tag           
     buildXMLElements(\@sortedPersonTag, \%personHashTags, $person); 
     $report-> appendChild($person); 


     # Build the elements for Charge Tag 
     my $charge = $doc->createElement("CHARGE");  
     my @sortedChargeTag = qw (DATE 
        TIME 
       ); 
     my %chargeHashTags; 
     @chargeHashTags { @sortedChargeTag } = ($date, 
         $time 
         ); 
     # Build the elements for Charge Tag          
     buildXMLElements(\@sortedChargeTag, \%chargeHashTags, $charge); 
     $report-> appendChild($charge); 
     $copy_person_pin = $person_pin; 
    } 
    else { 
     my $charge = $doc->createElement("CHARGE");  
     my @sortedChargeTag = qw (DATE 
        TIME 
       ); 
     my %chargeHashTags; 
     @chargeHashTags { @sortedChargeTag } = ($date, 
         $time 
         ); 
     # Build the elements for Charge Tag          
     buildXMLElements(\@sortedChargeTag, \%chargeHashTags, $charge); 
     $report-> appendChild($charge); 
    } 
} 

$doc->setDocumentElement($root); 

# Write the XML to a file 
print $FILEWRITE ($doc->toString()); 
close $FILEWRITE; 

sub buildXMLElements { 
    my($elementTags, $hashTags, $parentElement) = @_; 
    for my $name (@$elementTags) { 
    my $reportTag = $doc->createElement($name); 
    my $reportValue = $hashTags->{$name}; 
    $reportTag->appendTextNode($reportValue); 
    $parentElement->appendChild($reportTag); 
    } 
} 
+0

파일을 라인 단위로 처리하려고한다면, 그것을 버리지 마십시오. 사용할 변수를 읽으십시오. 물론 어휘 파일 핸들을 사용하십시오. 'while (my $ line = <$READFILE>) {chomp $ line; ...}' –

+0

고마워! for 루프를 while 루프로 바꿀 것입니다. – sannag

+0

또 다른 Perl 팁 :'use warnings' – stevenl