
Estoy buscando alguna sugerencia para convertir .asn1
(datos CDR) a CSV para cargarlos en tablas. Según el enfoque actual, estoy usando el analizador B2B de Informatica para analizar el archivo ASN a XML en lugar de usar la carga XSD en tablas Greenplum.
Espero que Perl pueda realizar estas operaciones mejor; durante un día recibimos un archivo ASN de ~30k, que es un archivo muy grande.
Para convertir XML a CSV (¿No sabes cómo convertir XML a CSV usando xmlstarlet en OS X?) No estoy seguro de que este enfoque funcione o si hay algún complemento en Perl.
Los archivos ASN son archivos binarios, el segundo paso es XML a CSV.
XML de muestra:
<?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>
Me gustaría que, aparte de la información de Cisco, el resto también esté en CSV.
Respuesta1
No lo uses XML::Simple
. Es unmala idea.
Pero fundamentalmente: XML es una estructura de datos jerárquica, CSV no lo es. Como resultado, es imposible resolver una traducción para el caso general.
Sin embargo, dada una estructura de registro estándar, no es demasiado difícil:
#!/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 );
}
Esto extrae la 'etiqueta' del nivel superior y luego los valores que coinciden con ellos, y los imprime.
Sin embargo, no es perfecto porque, como se dijo, sus datos son jerárquicos. Tiene cisco
registros y debe decidir qué quiere hacer con ellos: ¿cómo deben representarse en su CSV?
Respuesta2
Obtuve el siguiente código, para diferentes conjuntos de archivos XML a CSV.
Código:
#!/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" ;
}
Pero, ¿cómo recuperar los siguientes elementos si tengo más?