• Publicidad

Convertir XML en TXT

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Re: Convertir XML en TXT

Notapor explorer » 2012-10-29 19:12 @842

Necesitas aprender mucho más, pero casi lo tenías.

Con esto lo resuelves:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use v5.14;
  3.  
  4. use XML::Simple;
  5.  
  6. my $xml = XMLin('kk.xml', KeepRoot => 1);
  7.  
  8. say $xml->{Comprobante}->{xmlns};
  9. say $xml->{Comprobante}->{Emisor}->{rfc};
  10. say $xml->{Comprobante}->{Emisor}->{nombre};
  11. say $xml->{Comprobante}->{Emisor}->{domicilio}->{calle};
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4

Para guardarlo en un archivo de texto, solo tienes que agregar las órdenes de open() y close(), y agregar en los say() el gestor de archivo inicializado por open().

Más información en perlopentut.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Publicidad

Re: Convertir XML en TXT

Notapor adrian blind » 2012-10-29 21:58 @956

Buenas noches, Sensei explorer.

Estuve leyendo los problemas anteriores que tuvo chechoman. Es la misma idea y ya elaboré el código con respecto al que le ayudaste a hacer a chechoman y me quedó igual que al de él,

#!/usr/bin/perl

use XML::Simple;
use Data::Dumper;

opendir(DIR,"C:/pruebas/xml/");
my @files=readdir(DIR);
closedir(DIR);

open (FacElec, ">>","C:/pruebas/FacElec.txt") or (FacElec, ">","C:/pruebas/FacElec.txt");
foreach my $a (@files){
next if $a =~ /^\./;
print "Archivos cargados";
print $a;
print \n;

my $factura = XMLin("C:/pruebas/xml/$a");

print FacElec join q{|},
$factura->{xmlns},
$factura->{'xmlns:xsi'},
$factura->{'xsi:schemaLocation'},
$factura->{version},
$factura->{serie},
$factura->{folio},
$factura->{fecha},
$factura->{metodoDePago},
$factura->{tipoDeComprobante},
$factura->{NumCtaPago},
$factura->{TipoCambio},
$factura->{Moneda},
$factura->{Emisor}{nombre},
$factura->{Receptor}{rfc},
$factura->{Conceptos}{Concepto}{cantidad},
$factura->{Emisor}{DomicilioFiscal}{calle},
print FacElec "\n";
}
print "Fin Carga";
print "\n";
close FacElec;

pero a la hora de ejecutarlo me manda el siguiente mensaje de error:

not well-formed (invalid token) at line 55, column 34, byte 2993 at C:/Perl/lib/
XML/Parser.pm line 187
Archivos cargadosprueba.xmlSCALAR(0x1577b84)Archivos cargadosprueba2.xmlSCALAR(0x324638c)

Lo ejecuto en Windows y para Linux solo me manda a imprimir "Fin Carga".

¿Cuál sería mi problema?

Este es el código que he elaborado conforme a mis necesidades y al código elaborado por chechoman y usted.

Y disculpe las molestias, es que no había trabajado con Perl y me parece maravilloso.

Gracias por todo, Sensei explorer.
adrian blind
Perlero nuevo
Perlero nuevo
 
Mensajes: 6
Registrado: 2012-09-18 21:26 @935

Re: Convertir XML en TXT

Notapor explorer » 2012-10-30 08:37 @401

El error 'not well-formed' indica que en esa posición, el xml no es realmente un archivo con formato XML. Es otra cosa o está mal escrito o hay un error en su confección.

Yo sí veo que entra en el bucle, porque sale el texto 'Archivos cargados'.

Debes cambiar

print $a;
print \n;

por

print "$a\n";

Te falta un open después del 'or'.

Te recomiendo que cuando publiques código Perl en estos foros, le pongas las marcas de código Perl, que aparecen cuando editar tus mensajes, en la parte superior de la caja de edición.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Convertir XML en TXT

Notapor adrian blind » 2012-10-30 14:43 @655

Muchísimas gracias, Sensei.

Ya ha quedado.

De verdad que es una maravilla esto de Perl y me voy a estar adentrándome más a esta programación.

Saludos y que este bien, Sensei.
adrian blind
Perlero nuevo
Perlero nuevo
 
Mensajes: 6
Registrado: 2012-09-18 21:26 @935

Re: Convertir XML en TXT

Notapor adrian blind » 2012-11-02 23:45 @031

Buenas tardes, amigos.

Otra vez yo con otra molestia. Para que me entiendan les pongo primero el código del xml y del pl para que me dé a entender.

Sintáxis: [ Descargar ] [ Ocultar ]
Using xml Syntax Highlighting
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <cfdi:Comprobante
  3.         LugarExpedicion="Cuajimalpa de Morelos México, D.F."
  4.         metodoDePago="No identificado"
  5.         tipoDeComprobante="ingreso"
  6.         total="9993"
  7.         subTotal="8614.66"
  8.         formaDePago="PAGO EN UNA SOLA EXHIBICION"
  9.         fecha="2012-09-01T14:10:15">
  10.  
  11.   <cfdi:Emisor
  12.         nombre="BEST BUY STORES S. DE R.L. DE C.V."
  13.         rfc="BBS070606D33">
  14.     <cfdi:DomicilioFiscal
  15.                 codigoPostal="05349"
  16.                 pais="MEXICO"
  17.                 estado="D.F."
  18.                 municipio="CUAJIMALPA DE MORELOS"
  19.                 colonia="CRUZ MANCA SANTA FE"
  20.                 calle="AVENIDA SANTA FE 485 PISO 2" />
  21.   </cfdi:Emisor>
  22.  
  23.   <cfdi:Receptor
  24.         nombre="PUBLICO EN GENERAL"
  25.         rfc="XAXX010101000">
  26.     <cfdi:Domicilio
  27.                 codigoPostal="05349"
  28.                 pais="MEXICO"
  29.                 estado="D.F."
  30.                 municipio="CUAJIMALPA DE MORELOS"
  31.                 colonia="CRUZ MANCA SANTA FE"
  32.                 calle="AVENIDA SANTA FE 485 PISO 2" />
  33.   </cfdi:Receptor>
  34.  
  35.   <cfdi:Conceptos>
  36.     <cfdi:Concepto importe="7843.97" valorUnitario="7843.97" descripcion="NUEVO IPAD 32GB WIFI B" noIdentificacion="000000001000169630" unidad="PZA" cantidad="1" />
  37.     <cfdi:Concepto importe="0" valorUnitario="0.00" descripcion="KIT REWARD ZONE" noIdentificacion="000000001000019784" unidad="PZA" cantidad="1" />
  38.     <cfdi:Concepto importe="81.9" valorUnitario="81.90" descripcion="MEMORIA USB 4GB ANGRY BIRDS AZUL" noIdentificacion="000000001000169010" unidad="PZA" cantidad="1" />
  39.     <cfdi:Concepto importe="688.79" valorUnitario="688.79" descripcion="SMART CASE APPLE ROJO" noIdentificacion="000000001000172673" unidad="PZA" cantidad="1" />
  40.   </cfdi:Conceptos>
  41.  
  42. </cfdi:Comprobante>
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2.  
  3. use XML::Simple;
  4. use Data::Dumper;
  5.  
  6. opendir( DIR, "C:/pruebas/prueba/" );
  7. my @files = readdir(DIR);
  8. closedir(DIR);
  9.  
  10. open( FacElec, ">>", "C:/pruebas/FacElec.txt" ) or open( FacElec, ">", "C:/pruebas/FacElec.txt" );
  11. foreach my $a (@files) {
  12.     next if $a =~ /^\./;
  13.     print "Archivos cargados";
  14.     print "$a\n";
  15.  
  16.     my $factura = XMLin("C:/pruebas/prueba/$a");
  17.  
  18.     print FacElec join q{|},
  19.  
  20.         $factura->{LugarExpedicion},
  21.         $factura->{metodoDePago},
  22.         $factura->{tipoDeComprobante},
  23.         $factura->{total},
  24.         $factura->{subTotal},
  25.         $factura->{fecha},
  26.         $factura->{formaDePago},
  27.  
  28.         $factura->{'cfdi:Emisor'}{nombre},
  29.         $factura->{'cfdi:Emisor'}{rfc},
  30.         $factura->{'cfdi:Emisor'}{'cfdi:DomicilioFiscal'}{codigoPostal},
  31.         $factura->{'cfdi:Emisor'}{'cfdi:DomicilioFiscal'}{pais},
  32.         $factura->{'cfdi:Emisor'}{'cfdi:DomicilioFiscal'}{estado},
  33.         $factura->{'cfdi:Emisor'}{'cfdi:DomicilioFiscal'}{municipio},
  34.         $factura->{'cfdi:Emisor'}{'cfdi:DomicilioFiscal'}{colonia},
  35.         $factura->{'cfdi:Emisor'}{'cfdi:DomicilioFiscal'}{calle},
  36.  
  37.         $factura->{'cfdi:Receptor'}{nombre},
  38.         $factura->{'cfdi:Receptor'}{rfc},
  39.         $factura->{'cfdi:Receptor'}{'cfdi:Domicilio'}{codigoPostal},
  40.         $factura->{'cfdi:Receptor'}{'cfdi:Domicilio'}{pais},
  41.         $factura->{'cfdi:Receptor'}{'cfdi:Domicilio'}{estado},
  42.         $factura->{'cfdi:Receptor'}{'cfdi:Domicilio'}{municipio},
  43.         $factura->{'cfdi:Receptor'}{'cfdi:Domicilio'}{colonia},
  44.         $factura->{'cfdi:Receptor'}{'cfdi:Domicilio'}{calle},
  45.  
  46.         $factura->{'cfdi:Conceptos'}{'cfdi:Concepto'}{importe},
  47.         $factura->{'cfdi:Conceptos'}{'cfdi:Concepto'}{valorUnitario},
  48.         $factura->{'cfdi:Conceptos'}{'cfdi:Concepto'}{descripcion},
  49.         $factura->{'cfdi:Conceptos'}{'cfdi:Concepto'}{noIdentificacion},
  50.         $factura->{'cfdi:Conceptos'}{'cfdi:Concepto'}{unidad},
  51.         $factura->{'cfdi:Conceptos'}{'cfdi:Concepto'}{cantidad},
  52.  
  53.         print FacElec "\n";
  54. }
  55. print "Fin Carga";
  56. print "\n";
  57. close FacElec;
  58.  
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4



Lo que me sucede es que al momento de correr el programa no me trae la información de los conceptos.

Tengo idea de poner un ciclo en donde empiezan los conceptos a imprimir pero no sé si sea correcto.

Espero puedan ayudarme.

Gracias.
adrian blind
Perlero nuevo
Perlero nuevo
 
Mensajes: 6
Registrado: 2012-09-18 21:26 @935

Re: Convertir XML en TXT

Notapor explorer » 2012-11-03 01:38 @109

En la línea 52 falta un ';' para cerrar el print de la línea 18.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Convertir XML en TXT

Notapor adrian blind » 2012-11-04 23:41 @029

Muchas gracias, explorer.

En los conceptos no me visualiza la información en mi txt y quisiera que me aparecieran todos en cada línea.

No sé si esté bien pero ¿se puede poner solo en los conceptos un ciclo for?
adrian blind
Perlero nuevo
Perlero nuevo
 
Mensajes: 6
Registrado: 2012-09-18 21:26 @935

Re: Convertir XML en TXT

Notapor explorer » 2012-11-05 12:37 @567

Hay dos problemas.

El primero es que el XML está mal formado. En concreto, las etiquetas tienen un prefijo, 'cfdi', pero NO está definido como espacio de nombres dentro del XML, por lo que XML::Simple, al pasarlo al analizador de XML, se encuentra con el problema de que el analizador devuelve un error, indicando que ese prefijo no está declarado:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
Uncaught exception from user code:
        Undeclared prefix: cfdi at /usr/lib/perl5/vendor_perl/5.16.0/XML/NamespaceSupport.pm line 298.
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Esto se soluciona arreglando el XML, con solo incorporar un atributo a la marca raíz:
Sintáxis: [ Descargar ] [ Ocultar ]
Using xml Syntax Highlighting
  1. <cfdi:Comprobante  xmlns:cfdi="http://www.w3.org/TR/html4/"
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Si nosotros no somos los que generamos el XML, lo que podemos hacer es leer primero el xml como un archivo de texto normal, con una operación de sustitución (una expresión regular) añadimos ese atributo, y el resultado ya se lo podemos pasar al XMLin().

El segundo problema son los Conceptos. Muestras que quieres sacar toda la información del XML en una sola línea de texto (una línea por cada xml encontrado. ¿Eso quiere decir que todos los conceptos de cada xml deben ir también en esa misma línea? ¿Da lo mismo que haya un solo concepto o veinte?

Supongamos que eso es lo que queremos: en la línea, primero están los datos de Emisor, Receptor y Comprobante, y luego sigue en secuencia los datos de todos los conceptos.

Aquí hay un pequeño problema añadido. XML::Simple, cuando se encuentra con un XML en el que una marca se repite varias veces en el mismo nivel -caso de Concepto-, crea un array donde cada elemento es un hash que contiene a su vez los datos de cada marca. Pero... si solo hay UNA marca, no crea el array.

Ejemplo: con el XML que pusiste, crea una estructura así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.           'cfdi:Conceptos' => {
  2.                               'cfdi:Concepto' => [
  3.                                                  {
  4.                                                    'valorUnitario' => '7843.97',
  5.                                                    'noIdentificacion' => '000000001000169630',
  6.                                                    'unidad' => 'PZA',
  7.                                                    'descripcion' => 'NUEVO IPAD 32GB WIFI B',
  8.                                                    'importe' => '7843.97',
  9.                                                    'cantidad' => '1'
  10.                                                  },
  11.                                                  {
  12.                                                    'valorUnitario' => '0.00',
  13. ...
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
y vemos que 'cfdi:Concepto' es una referencia a un array, y cada elemento, un hash con los datos del Concepto.

Pero... si solo hay UN Concepto, por defecto se genera esta estructura:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.           'cfdi:Conceptos' => {
  2.                               'cfdi:Concepto' => {
  3.                                                  'valorUnitario' => '7843.97',
  4.                                                  'noIdentificacion' => '000000001000169630',
  5.                                                  'unidad' => 'PZA',
  6.                                                  'descripcion' => 'NUEVO IPAD 32GB WIFI B',
  7.                                                  'importe' => '7843.97',
  8.                                                  'cantidad' => '1'
  9.                                                }
  10.                             },
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
No hay array. Sigue siendo un hash de hash.

Estaríamos obligados, en nuestro programa, en contemplar los dos casos, pues los dos se leen de dos formas diferentes (sería poner un if(), un for() en una parte, y un acceso directo en otra).

Lo mejor es decirle a XML::Simple que SIEMPRE ponga los Concepto en forma de array. Para eso, modificamos el XMLin() añadiendo el atributo ForceArray => [ 'cfdi:Concepto' ], y ya sale igual que antes, aunque solo haya un elemento.

El programa queda al final así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. #use diagnostics;
  5.  
  6. use XML::Simple;
  7. #use Data::Dumper;
  8.  
  9. chdir 'C:/pruebas/prueba' or die "ERROR: No puedo entrar en C:/pruebas/prueba: $!\n";
  10.  
  11. opendir( DIR, '.' );
  12. my @files = readdir(DIR);
  13. closedir(DIR);
  14.  
  15. open( FacElec, '>>', 'C:/pruebas/FacElec.txt' );
  16.  
  17. foreach my $a (@files) {
  18.     next if $a =~ /^\./;
  19.     print "Archivo cargado: [$a]\n";
  20.  
  21.     my $factura = XMLin( $a, ForceArray => ['cfdi:Concepto'], NSExpand => 0, KeepRoot => 0 );
  22.  
  23.     print FacElec join q{|},
  24.  
  25.         $factura->{LugarExpedicion},
  26.         $factura->{metodoDePago},
  27.         $factura->{tipoDeComprobante},
  28.         $factura->{total},
  29.         $factura->{subTotal},
  30.         $factura->{fecha},
  31.         $factura->{formaDePago},
  32.  
  33.         $factura->{'cfdi:Emisor'}{nombre},
  34.         $factura->{'cfdi:Emisor'}{rfc},
  35.         $factura->{'cfdi:Emisor'}{'cfdi:DomicilioFiscal'}{codigoPostal},
  36.         $factura->{'cfdi:Emisor'}{'cfdi:DomicilioFiscal'}{pais},
  37.         $factura->{'cfdi:Emisor'}{'cfdi:DomicilioFiscal'}{estado},
  38.         $factura->{'cfdi:Emisor'}{'cfdi:DomicilioFiscal'}{municipio},
  39.         $factura->{'cfdi:Emisor'}{'cfdi:DomicilioFiscal'}{colonia},
  40.         $factura->{'cfdi:Emisor'}{'cfdi:DomicilioFiscal'}{calle},
  41.  
  42.         $factura->{'cfdi:Receptor'}{nombre},
  43.         $factura->{'cfdi:Receptor'}{rfc},
  44.         $factura->{'cfdi:Receptor'}{'cfdi:Domicilio'}{codigoPostal},
  45.         $factura->{'cfdi:Receptor'}{'cfdi:Domicilio'}{pais},
  46.         $factura->{'cfdi:Receptor'}{'cfdi:Domicilio'}{estado},
  47.         $factura->{'cfdi:Receptor'}{'cfdi:Domicilio'}{municipio},
  48.         $factura->{'cfdi:Receptor'}{'cfdi:Domicilio'}{colonia},
  49.         $factura->{'cfdi:Receptor'}{'cfdi:Domicilio'}{calle},
  50.         ;
  51.  
  52.     for my $concepto ( @{ $factura->{'cfdi:Conceptos'}{'cfdi:Concepto'} } ) {
  53.         print FacElec '|', join q{|},
  54.             $concepto->{importe},
  55.             $concepto->{valorUnitario},
  56.             $concepto->{descripcion},
  57.             $concepto->{noIdentificacion},
  58.             $concepto->{unidad},
  59.             $concepto->{cantidad},
  60.             ;
  61.     }
  62. }
  63.  
  64. print "Fin Carga\n";
  65. close FacElec;
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Anterior

Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 27 invitados