2017-12-18 17 views
-1

xml에서 "Grand Total"값을 가져와야합니다. 필자는 perl 스크립트를 작성했지만 총합에 대한 XML 태그 경로를 실수로 수정했습니다. 올바른 경로를 안내하십시오.Perl을 사용하여 XML 데이터 가져 오기

다음은 XML입니다.

<TotalForServiceSummary> 
    <GrandTotal><![CDATA[1246.00]]></GrandTotal> 
</TotalForServiceSummary> 

스크립트 :

my $salesOrderNumber =s hift @ARGV; 
my $billRunID = shift @ARGV; 
my $customerNodeID = shift @ARGV; 
my $invoiceID = shift @ARGV; 
my $billRunDate =shift @ARGV; 

my $filename = "So_".$salesOrderNumber."_".$billRunID."_".$customerNodeID."_".$invoiceID."_".$billRunDate; 

my $file = `ls /svw/svwsit2b/data/server/invoices/sap_equip_invoice/$filename\*.xml`; 

my $return; 

open(XML, $file) or die "Cannot open $file for reading: $!\n"; 

while (my $line = <XML>) { 

    if ($line =~ /\<EquipSalesTotalChargeIncTax\>/i) { 
     my $xml = new XML::Simple; 
     my $ref3 = $xml->XMLin($line); 
     $return = $return . $ref3; 
    }  
} 
+1

코드의 형식이 수정되었습니다 (누락 된'}'이 추가되었습니다). 환영합니다.하지만 장래에 직접하십시오. 당신이 낯선 사람들에게 당신의 코드를 읽고 이해하도록 요구한다면, 가능한 한 쉽게 그 일을 수행하는 것이 예의입니다. –

+1

분명한 실수는 예제 입력이 코드에서 찾고있는 것과 일치하지 않는다는 것입니다. –

+1

* "저는 ... 총액에 대한 xml 태그 경로를 실수로 수정했습니다"*하지만 코드는 표시되지 않습니다. 모든 "xml 태그 경로". 적절한 도움을 받으려면 실제 코드와 데이터를 보여줘야합니다. – Borodin

답변

4

오해 여기에 무슨 꽤 많이 있습니다.

한 번에 한 줄씩 XML 파일을 읽을 필요가 없습니다. XMLIn()은 모든 XML에 대해 한 번에 작업하게해야합니다. 실제로 파일 이름을 전달하면 파일이 열리고 XML이 모두 읽혀집니다. 새로운 코드에서이 모듈의 사용은 권장하지 않습니다이 모듈

상태 :

그러나, 당신은 또한 XML::Simple documentation에서이 부분을주의해야한다. 다른 모듈은 더 간단하고 일관성있는 인터페이스를 제공하는 입니다. . 특히 XML::LibXML을 사용하는 것이 좋습니다. XML::Twig은 훌륭한 대안입니다.

이 모듈의 주요 문제점은 많은 옵션 인 (일부에는 불행한 기본값이 있음)과 이러한 옵션이 상호 작용하는 임의의 방식 (예기치 않은 결과가 나오는 경우가 있음)입니다.

버그 수정 및 문서 수정이 포함 된 패치는 환영하지만 새로운 기능이 추가되지는 않습니다.

위에서 언급 한 대체 라이브러리 중 하나로 전환하는 것을 진지하게 고려해야합니다.

my $ref3 = $xml->XMLin($line); 
$return = $return . $ref3; 

$ref3가 (아마 해시)에 대한 참조를 포함합니다 :

또한,이 두 라인은 아무 의미가 없습니다. 그 문자열 표현은 HASH(0x12345678)처럼 보일 것이고 당신이 원하는 것일 확률은 매우 낮습니다.

업데이트 :이 문제를 XML :: LibXML로 해결하는 것은 다음과 같습니다. 그러나 귀하의 질문에 지나치게 단순화되어 있다고 생각합니다. 따라서이 솔루션은 귀하에게 적합하지 않을 수 있습니다.

#!/usr/bin/perl 

use strict; 
use warnings; 
use feature 'say'; 

use XML::LibXML; 

# My XML is in "total.xml". 
my $doc = XML::LibXML->new->parse_file('total.xml'); 

say $doc->findvalue('//TotalForServiceSummary/GrandTotal'); 

업데이트 2 : 코드에 대한 몇 가지 다른 점.

귀하의 라인 :

my $salesOrderNumber =shift @ARGV; 
my $billRunID = shift @ARGV; 

등등 ...ls 같은 외부 프로그램을 사용하지 않고 -

my ($salesOrderNumber, $billRunID, $customerNodeID, 
    $invoiceID, $billRunDate) = @ARGV; 

glob() 기능은 파일 이름의 목록을 얻을 수있는 크로스 플랫폼 방법 :

더 나은로 기록됩니다.

어휘 파일 핸들과 3 인수 버전 open()을 사용하십시오.

open my $xml_fh, '<', $file 
    or die "Can't open $file: $!\n"; 

생성자 (new XML::Simple)를 호출하는 "간접 객체"방법은 몇 가지 점에서 문제를 찾기 어려운 것입니다 잠재적 원인. 대신 을 사용하는 것이 좋습니다.

+0

OP 코드가 "EquipSalesTotalChargeIncTax"태그가 포함 된 라인을 찾고 있기 때문에 첫 번째 업데이트가 완전히 정확한지 확신 할 수 없습니다. –

+0

@ChrisTurner : 예, 코드가 아닌 샘플 데이터를 기반으로합니다. 그것이 내가 그 문제를 단순화 시켰다고 (그리고 아마 그 과정에서 자신을 혼란스럽게 만들었다 고) 말한 이유입니다. –

+0

Chris & Dave에게 모든 제안과 도움을 주신 데 대해 감사 드리며 사람들이 옳다는 것을 알려 주셨습니다. 샘플은 매우 큰 XML 파일의 일부이므로 지나치게 단순화하려고했는데 'GrandTotal'태그가 많이 있지만 가져올 필요가있었습니다. 하나는 에 있습니다. – Vijay