Perl을 사용하여 XML 파일을 CSV로 변환하는 방법은 무엇입니까?

Perl을 사용하여 XML 파일을 CSV로 변환하는 방법은 무엇입니까?

.asn1테이블에 로드하기 위해 (CDR 데이터)를 CSV로 변환하는 방법에 대한 조언을 찾고 있습니다. 현재 접근 방식에 따르면 XSD를 사용하여 Greenplum 테이블에 로드하는 대신 Informatica B2B 파서를 사용하여 ASN 파일을 XML로 구문 분석합니다.

Perl이 이 작업을 더 나은 방법으로 수행할 수 있었으면 좋겠습니다. 어느 날 우리는 매우 큰 파일인 약 30,000개의 ASN 파일을 받았습니다.

XML을 CSV로 변환하려면(OS X에서 xmlstarlet을 사용하여 XML을 CSV로 변환하는 방법에 대해 혼란스러우신가요?) 이 방법이 작동하는지 또는 Perl에 플러그인이 있는지 확실하지 않습니다.

ASN 파일은 바이너리 파일이고 두 번째 단계는 XML을 CSV로 변환하는 것입니다.

XML 예:

<?xml version="1.0" encoding="windows-1252"?>
<RadiusCDR_Parent>
<RadiusCDR>
<accountingRequest>
<userName>1200099344</userName>
<nasIPAddress>0A490010</nasIPAddress>
<nasPort>0</nasPort>
<serviceType>2</serviceType>
<framedProtocol>1</framedProtocol>
<framedIPAddress>64702E70</framedIPAddress>
<vendorSpecificExt>
<cisco>
<subAttributeID>1</subAttributeID>
<vendorLength>26</vendorLength>
<data>connect-progress=Call Up</data>
</cisco>
<cisco>
<subAttributeID>1</subAttributeID>
<vendorLength>19</vendorLength>
<data>portbundle=enable</data>
</cisco>
<cisco>
<subAttributeID>250</subAttributeID>
<vendorLength>17</vendorLength>
<data>S10.73.0.17:785</data>
</cisco>
<cisco>
<subAttributeID>253</subAttributeID>
<vendorLength>11</vendorLength>
<data>I0;153521</data>
</cisco>
<cisco>
<subAttributeID>253</subAttributeID>
<vendorLength>11</vendorLength>
<data>O0;559080</data>
</cisco>
</vendorSpecificExt>
<callingStationID>503c.c433.b8df</callingStationID>
<nasIdentifier>INMUNVMBXXXXNB0001AG3WAG001.ril.com</nasIdentifier>
<acctStatusType>3</acctStatusType>
<acctDelayTime>0</acctDelayTime>
<acctInputOctets>0257B1</acctInputOctets>
<acctOutputOctets>0887E8</acctOutputOctets>
<acctSessionID>009B51EC</acctSessionID>
<acctAuthentic>1</acctAuthentic>
<acctSessionTime>2012</acctSessionTime>
<acctInputPackets>1187</acctInputPackets>
<acctOutputPackets>1130</acctOutputPackets>
<eventTimeStamp>140E0A0F 123B0E</eventTimeStamp>
<nasPortType>5</nasPortType>
<nasPortID>0/0/0/902</nasPortID>
</accountingRequest>
</RadiusCDR>
<RadiusCDR_Parent>

Cisco 정보를 제외한 모든 정보도 CSV 형식으로 만들고 싶습니다.

답변1

사용하지 마십시오. XML::Simple입니다.나쁜 생각.

그러나 기본적으로 XML은 계층적 데이터 구조이고 CSV는 그렇지 않습니다. 따라서 일반적으로 번역 문제를 해결하는 것은 불가능합니다.

그러나 표준 레코드 구조를 고려하면 이는 그리 어렵지 않습니다.

#!/usr/bin/env perl

use strict;
use warnings;
use XML::Twig;
use Text::CSV;
use Data::Dumper;

my $twig = XML::Twig->new->parse( \*DATA );

#read heading from first record.
my @headings =
    map { $_->tag } $twig->findnodes( '//accountingRequest', 0 )->children;

my $csv_out = Text::CSV->new( { binary => 1, eol => "\n" } );
$csv_out->print( \*STDOUT, \@headings );

foreach my $accountingRequest ( $twig->findnodes('//accountingRequest') ) {
    my @row = map { $accountingRequest->first_child_text($_) } @headings;
    $csv_out->print( \*STDOUT, \@row );
}

이렇게 하면 최상위 "태그"를 추출한 다음 일치하는 값을 추출하고 해당 값을 인쇄합니다.

하지만 언급한 대로 데이터가 계층적이기 때문에 완벽하지는 않습니다. 기록이 있고 cisco이를 어떻게 처리할지 결정해야 합니다. 기록을 CSV에 어떻게 표시해야 합니까?

답변2

다양한 XML 파일 및 CSV 파일 세트에 대한 코드가 아래에 있습니다.

암호:

#!/usr/bin/perl

# Script to illustrate how to parse a simple XML file
# and pick out all the values for a specific element, in
# this case all the titles.

# use strict;
use XML::Simple;
use Data::Dumper;

# create object
$xml = new XML::Simple (KeyAttr=>[]);

# read XML file
$data = $xml->XMLin("test1.xml");


my $booklist = XMLin('test1.xml');    #booklist is the array 
# print Dumper($booklist);

foreach my $FreemanFees (@{$booklist->{FreemanFees}}) {


    print 
    $FreemanFees->{SdcLoanFacilityNumber} , "," , 
    $FreemanFees->{DealId} ,",", 
    $FreemanFees->{Tranche}->{SdcDealNumber} , "," , 
    $FreemanFees->{Tranche}->{ManagerFeeAndCredits}->{ManagerFeeAndCredit}->{FreemanFeesForManager}->{ManagerNumberForFreemanFee}, ",",
    $FreemanFees->{Tranche}->{ManagerFeeAndCredits}->{ManagerFeeAndCredit}->{FreemanFeesForManager}->{currencyId},",",
    $FreemanFees->{Tranche}->{ManagerFeeAndCredits}->{ManagerFeeAndCredit}->{FreemanFeesForManager}->{sdcCurrencyCode} , "," , 
    $FreemanFees->{Tranche}->{ManagerFeeAndCredits}->{ManagerFeeAndCredit}->{FreemanFeesForManager}->{scale}, ",",
    $FreemanFees->{Tranche}->{ManagerFeeAndCredits}->{ManagerFeeAndCredit}->{FreemanFeesForManager}->{content} , "," ,"\n" ;
    }

하지만 더 많은 요소가 있는 경우 다음 요소를 어떻게 얻을 수 있나요?

관련 정보