Mie Jul 02, 2008 10:26 am
|
 |
chechoman
Perlero Nuevo

|
Registrado: 02 Jul 2008
Mensajes: 19
|
|
| Convertir XML en TXT |
|
|
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:
| XML: | <?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> |
y el código que he creado en Perl es el siguiente:
| Perl: | 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"; |
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. |
|
|
|


Mie Jul 02, 2008 12:25 pm
|
 |
chechoman
Perlero Nuevo

|
Registrado: 02 Jul 2008
Mensajes: 19
|
|
|
|
|
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:
| Perl: | 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; |
|
|

Mie Jul 02, 2008 3:26 pm
|
 |
monoswim
Vive para Perl en Español

|
Registrado: 18 Nov 2003
Mensajes: 691
Ubicación: Buenos Aires
|
|
|
|
|
Cuando cargas en un array los nombres de cada archivo tienes que hacer un bucle que ejecute tu código por cada archivo...
| Perl: | foreach my $file (@files){
my $datos = XMLin ("./directorio/$file");
...
close prueba;
} |
¿Me expliqué bien?
Saludos |
|

Mie Jul 02, 2008 3:49 pm
|
 |
chechoman
Perlero Nuevo

|
Registrado: 02 Jul 2008
Mensajes: 19
|
|
|
|
|
Casualmente se me había ocurrido hacer una solución similar a la que colocaste y quedo así:
| Perl: | 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 ); |
Sin embargo no funciona , da el siguiente error:
| bash: | read error at /usr/lib/perl5/XML/Parser/Expat.pm line 469. |
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. |
|

Mie Jul 02, 2008 4:29 pm
|
 |
explorer
Moderador

|
Registrado: 24 Jul 2005
Mensajes: 3823
Ubicación: Valladolid, España
|
|
|
|
|
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.
| Perl: | 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; |
Recuerda, también, que cuando trabajes con XML::Simple, Data::Dumper es tu amigo. |
|


Mie Jul 02, 2008 7:23 pm
|
 |
explorer
Moderador

|
Registrado: 24 Jul 2005
Mensajes: 3823
Ubicación: Valladolid, España
|
|
|
|
|
A mí el error que me da es que el namespace (espacio de nombres) xsi no ha sido declarado:
| Código: |
| 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:
| Perl: | #!/usr/bin/perl
use XML:: Simple;
use Data:: Dumper;
my $xml = XMLin ('kk.xml');
print Dumper ($xml); |
| Código: |
$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...) |
|

Mie Jul 02, 2008 10:03 pm
|
 |
chechoman
Perlero Nuevo

|
Registrado: 02 Jul 2008
Mensajes: 19
|
|
|
|
|
| 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. |
|


Jue Jul 03, 2008 8:32 am
|
 |
chechoman
Perlero Nuevo

|
Registrado: 02 Jul 2008
Mensajes: 19
|
|
|
|
|
Tengo que darles todas las gracias por la ayuda que me han prestado. Me he quedado impresionado en estos dos días por el uso de Perl; es un lenguaje demasiado potente y muy práctico, pude hacer el programita con una sola librería y sin necesidad de muchas líneas de código (37) y muy rápido.
Les adjunto el código por si alguien quiere un conversor de archivos xml a txt:
| Perl: | use XML:: Simple;
use Data:: Dumper;
opendir(DIR, "/home/principal/xml/xml1/");
my @files= readdir(DIR );
closedir(DIR );
open (xml, ">>", "/home/principal/xml/xml.txt") or (xml, ">", "/home/principal/xml/xml.txt");
foreach my $a (@files){
next if $a =~ /^\./;
print "Archivos Cargados";
print $a;
print "\n";
my $datos = XMLin ("/home/principal/xml/xml1/$a");
print xml 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 xml "\n";
}
print "Fin Carga";
print "\n";
close xml; |
|
|

Jue Jul 03, 2008 9:15 am
|
 |
explorer
Moderador

|
Registrado: 24 Jul 2005
Mensajes: 3823
Ubicación: Valladolid, España
|
|
|
|
|
Según lo que indica la página de manual de open, en el uso del modo de concatenar ('>>'), si el fichero no existe, es creado.
Así que la línea | Perl: | open (xml, ">>", "/home/principal/xml/xml.txt") or (xml, ">", "/home/principal/xml/xml.txt"); | se puede dejar en
| Perl: | open (xml, ">>/home/principal/xml/xml.txt") or die "$!\n"; |
|
|
Jue Jul 03, 2008 10:03 am
|
 |
chechoman
Perlero Nuevo

|
Registrado: 02 Jul 2008
Mensajes: 19
|
|
|
|
|
¡¡Cierto maestro!! Lo corregí y si no existe el archivo la aplicación lo crea; así quedó mejor el código; gracias otra vez  |
|

Vie Jul 11, 2008 10:18 pm
|
 |
chechoman
Perlero Nuevo

|
Registrado: 02 Jul 2008
Mensajes: 19
|
|
|
|
|
| Aparte del problema de colocar NULL en elementos que no tengan valores al leer el xml, ¡¡¡también encontré otra falla y mas grave!!!, y es cómo hacer para que el programa me procese aquellos datos con "caracteres especiales", ya que para Perl me arroja que el xml está mal formado, y es porque algunos valores tienen ñ o Ñ o acentos, entonces, ¿cómo hacer para poder leer estos datos o poder sustituirlos? |
|
Powered by phpBB © 2001, 2005 phpBB Group
|