• 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.

Convertir XML en TXT

Notapor chechoman » 2008-07-02 11:26 @518

Hola soy nuevo usando Perl y el asunto es que tengo que hacer un programita que me convierta un archivo XML en un archivo TXT. Estuve viéndolo hacer con Java, pero al parecer con Perl es mucho más sencillo; sin embargo, estoy atascado en varios puntos.

Primero que todo el archivo XML es muy sencillo, a continuación muestro como es:
Sintáxis: [ Descargar ] [ Ocultar ]
Using xml Syntax Highlighting
<?xml version="1.0" encoding="UTF-8"?>
<datos xsi:noNamespaceSchemaLocation="D:\Work\prueba.xsd" opr="0">
        <letra>V</letra>
        <cedula>123</cedula>
        <PNombre>nombre</PNombre>
        <SNombre>Segundo Nombre</SNombre>
        <PApellido>apellido</PApellido>
        <FechaNac>1980-07-25</FechaNac>
        <FechaCedOrg>2005-03-31</FechaCedOrg>
        <CodObjecion>00</CodObjecion>
        <CodOficina>AB</CodOficina>
        <CodEstadoCivil>2</CodEstadoCivil>
        <Naturalizado>0</Naturalizado>
        <Sexo>M</Sexo>
</datos>
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


y el código que he creado en Perl es el siguiente:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
use XML::Simple;

my $datos = XMLin('./prueba.xml');

print join q{|},
        $datos->{letra}          ,
        $datos->{cedula}         ,  
        $datos->{PNombre}        ,
        $datos->{SNombre}        ,
        $datos->{PApellido}      ,
        $datos->{FechaNac}       ,
        $datos->{FechaCedOrg}    ,
        $datos->{CodObjecion}    ,
        $datos->{CodOficina}     ,
        $datos->{CodEstadoCivil} ,
        $datos->{Naturalizado}   ,
        $datos->{Sexo};
print "\n";
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


Hasta ahora esto me está funcionando bien, sin embargo aún no es lo que deseo obtener, ya que necesito que el programa me lea el atributo "opr " del elemento datos; si este atributo es 0 me debe marcar la información para "insertar" y si es 1, lo debe marcar como "actualizar".

No he conseguido entonces cómo leer este atributo del elemento.

Además de ello, este archivo xml se encontrará en un carpeta con varios archivos xml más, con la misma estructura; tampoco entonces he encontrado una función o librería que me lea todo el folder y me vaya leyendo xml por xml y pienso que me los cargue en un array donde después los pueda vaciar en el txt.

Hasta ahora estoy muy básico en este asunto, lo bueno es que he podido apreciar la potencialidad de este lenguaje.
chechoman
Perlero nuevo
Perlero nuevo
 
Mensajes: 19
Registrado: 2008-07-02 11:14 @510

Publicidad

Notapor monoswim » 2008-07-02 12:11 @549

Programándolo a mano se puede hacer bien fácil... no necesitas módulos... vamos por partes.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my $opr;
if ($datos->{opr} == 0){
   $opr = 'insertar';
}else{
   $opr = 'actualizar';
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Ahora solo tienes que colocar a $opr en tu lista de join...

Y para abrir el directorio y cargarlo a un array:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
opendir(DIR, "directorio");
my @files = sort readdir(DIR);
closedir(DIR);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Y recuerda hacer un chop doble para eliminar los archivos . y ..

Espero que te sirva.

Saludos
PD: ¡¡¡ BIENVENIDO A LOS FOROS !!!
MonoSwim
Perl Programming Language
Avatar de Usuario
monoswim
Perlero nuevo
Perlero nuevo
 
Mensajes: 452
Registrado: 2003-11-18 16:13 @717
Ubicación: Buenos Aires

Notapor chechoman » 2008-07-02 13:25 @601

Hola, gracias por responderme. Lo de la variable $opr está funcionando de maravilla, al código le hice varios cambios ahora, y ya puede guardar la información en un archivo txt y hacer un salto de línea para el siguiente xml, sin embargo el problema que me falta resolver es que lea todos los xml que se encuentren en un directorio "x" y los cargue en un array, después, que este array sea guardado en el txt; ahora por un lado no veo cómo integrar el código que escribiste sobre la lectura del directorio dentro de mi código; aquí coloco el código nuevo:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
use XML::Simple;

my $datos = XMLin('./prueba.xml');
my $opr;
if ($datos->{opr} == 0){
        $opr = 'insertar';
}else{
        $opr = 'actualizar';
}
open (prueba, ">>","/home/principal/prueba.txt") or (prueba, ">", "/home/principal/prueba.txt");
print prueba join q{|},
        $opr ,
        $datos->{letra}          ,
        $datos->{cedula}         ,
        $datos->{PNombre}        ,
        $datos->{SNombre}        ,
        $datos->{PApellido}      ,
        $datos->{FechaNac}       ,
        $datos->{FechaCedOrg}    ,
        $datos->{CodObjecion}    ,
        $datos->{CodOficina}     ,
        $datos->{CodEstadoCivil} ,
        $datos->{Naturalizado}   ,
        $datos->{Sexo};
print prueba "\n";
close prueba;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
chechoman
Perlero nuevo
Perlero nuevo
 
Mensajes: 19
Registrado: 2008-07-02 11:14 @510

Notapor monoswim » 2008-07-02 16:26 @726

Cuando cargas en un array los nombres de cada archivo tienes que hacer un bucle que ejecute tu código por cada archivo...

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
foreach my $file (@files){
   my $datos = XMLin("./directorio/$file");
   ...
   close prueba;
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


¿Me expliqué bien?

Saludos
MonoSwim
Perl Programming Language
Avatar de Usuario
monoswim
Perlero nuevo
Perlero nuevo
 
Mensajes: 452
Registrado: 2003-11-18 16:13 @717
Ubicación: Buenos Aires

Notapor chechoman » 2008-07-02 16:49 @742

Casualmente se me había ocurrido hacer una solución similar a la que colocaste y quedo así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
use XML::Simple;
opendir(DIR, "/home/principal/xml/xml1/");
my @files=readdir(DIR);
foreach my $a (@files){
my $datos = XMLin("./$a");
my $opr;
open (prueba, ">>","/home/principal/xml/prueba.txt") or (prueba, ">", "/home/principal/xml/prueba.txt");
print prueba join q{|},
        $datos->{opr}            ,
        $datos->{letra}          ,
        $datos->{cedula}         ,
        $datos->{PNombre}        ,
        $datos->{SNombre}        ,
        $datos->{PApellido}      ,
        $datos->{FechaNac}       ,
        $datos->{FechaCedOrg}    ,
        $datos->{CodObjecion}    ,
        $datos->{CodOficina}     ,
        $datos->{CodEstadoCivil} ,
        $datos->{Naturalizado}   ,
        $datos->{Sexo};
print prueba "\n";
close prueba;
}
closedir(DIR);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Sin embargo no funciona :( , da el siguiente error:
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
read error at /usr/lib/perl5/XML/Parser/Expat.pm line 469.
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


P.D.: En la ruta de my $datos probé con varios opciones y tampoco funcionó, lo hice por si el error era producto de no conseguir el archivo.
chechoman
Perlero nuevo
Perlero nuevo
 
Mensajes: 19
Registrado: 2008-07-02 11:14 @510

Notapor explorer » 2008-07-02 17:29 @770

El error ha ocurrido en la interpretación del xml. Es posible que esté mal.

Esta variación es algo mejor: el open() solo se hace una vez.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
use XML::Simple;

opendir(DIR, "/home/principal/xml/xml1/");
my @files=readdir(DIR);
closedir(DIR);

my $opr;

open (prueba, ">","/home/principal/xml/prueba.txt") or die "$!\n";

foreach my $a (@files) {
    my $datos = XMLin("./$a");
    print prueba join q{|},
        $datos->{opr}            ,
        $datos->{letra}          ,
        $datos->{cedula}         ,
        $datos->{PNombre}        ,
        $datos->{SNombre}        ,
        $datos->{PApellido}      ,
        $datos->{FechaNac}       ,
        $datos->{FechaCedOrg}    ,
        $datos->{CodObjecion}    ,
        $datos->{CodOficina}     ,
        $datos->{CodEstadoCivil} ,
        $datos->{Naturalizado}   ,
        $datos->{Sexo};
    print prueba "\n";
}

close prueba;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Recuerda, también, que cuando trabajes con XML::Simple, Data::Dumper es tu amigo.
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

Notapor chechoman » 2008-07-02 19:12 @841

Hola, bueno hago dos veces el open porque con el primero agrego en caso de que el archivo exista, y el segundo es por si el archivo prueba.txt no ha sido creado y así lo crea y adjunta la información.

Estuve leyendo algo sobre el error y pareciera que fuera un problema con el archivo XML pero no le veo nada que esté mal; de todas formas aquí lo copio por si uds. observan algo errado.

Sintáxis: [ Descargar ] [ Ocultar ]
Using xml Syntax Highlighting
<?xml version="1.0" encoding="UTF-8"?>
<datos xsi:noNamespaceSchemaLocation="D:\Work\prueba.xsd" opr="0">
        <letra>V</letra>
        <cedula>123</cedula>
        <PNombre>nombre</PNombre>
        <SNombre>Segundo Nombre</SNombre>
        <PApellido>apellido</PApellido>
        <FechaNac>1980-07-25</FechaNac>
        <FechaCedOrg>2005-03-31</FechaCedOrg>
        <CodObjecion>00</CodObjecion>
        <CodOficina>AB</CodOficina>
        <CodEstadoCivil>2</CodEstadoCivil>
        <Naturalizado>0</Naturalizado>
        <Sexo>M</Sexo>
</datos>
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


También probé eliminarle al XML toda la ruta del xsi y siguió dando el problema, cosa que me hace dudar entonces que el problema sea el archivo XML.

Sin embargo aunque genera el error, el programa está creando el archivo prueba,txt. Lo malo es que solo está guardando los datos del primer archivo que consigue. Si hay más de uno no guarda el resto; revisé el bucle y no sé por qué sucede esto.
chechoman
Perlero nuevo
Perlero nuevo
 
Mensajes: 19
Registrado: 2008-07-02 11:14 @510

Notapor explorer » 2008-07-02 20:23 @891

A mí el error que me da es que el namespace (espacio de nombres) xsi no ha sido declarado:
Código: Seleccionar todo
Undeclared prefix: xsi at /usr/lib/perl5/site_perl/5.8.8/XML/NamespaceSupport.pm line 298.

Según la documentación de XML::Simple, debes usar el modo de interpretación con SAX.

Si eliminamos 'xsi:' del xml, entonces sí que funciona:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl
use XML::Simple;
use Data::Dumper;
my $xml = XMLin('kk.xml');

print Dumper($xml);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Código: Seleccionar todo
$VAR1 = {
          'opr' => '0',
          'CodEstadoCivil' => '2',
          'CodOficina' => 'AB',
          'letra' => 'V',
          'FechaCedOrg' => '2005-03-31',
          'noNamespaceSchemaLocation' => 'D:\\Work\\prueba.xsd',
          'SNombre' => 'Segundo Nombre',
          'cedula' => '123',
          'Sexo' => 'M',
          'PNombre' => 'nombre',
          'FechaNac' => '1980-07-25',
          'Naturalizado' => '0',
          'CodObjecion' => '00',
          'PApellido' => 'apellido'
        };


(Humm... los '\' en el valor de xsi me dan mala espina...)
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

Notapor chechoman » 2008-07-02 23:03 @002

Bueno, el error me sigue dando, sin embargo el programa está haciendo su función y lee todos los xml de un directorio especifico, los guarda en el array y después los vacía en un txt, ahora lo que no veo cómo hacer, es implementar la función "chop" para que me elimine el . y el .. del array.
chechoman
Perlero nuevo
Perlero nuevo
 
Mensajes: 19
Registrado: 2008-07-02 11:14 @510

Notapor explorer » 2008-07-03 03:15 @177

La línea siguiente al foreach, pones
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
next if $a =~ /^\./;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
que lo que hace es saltar al siguiente fichero si el actual ($a) comienza (^) por '.'.
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

Siguiente

Volver a Básico

¿Quién está conectado?

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