Perl
如何使用 Perl 將 XML 文件轉換為 CSV?
我正在尋找一些將
.asn1
(CDR 數據)轉換為 CSV 以載入到表中的建議。根據目前的方法,我使用 informatica B2B 解析器將 ASN 文件解析為 XML,而不是使用 XSD 載入到 Greenplum 表。我希望 Perl 能夠以更好的方式完成這些操作;一天,我們收到了一個約 30k 的 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 中。
不要使用
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 中表示?