• Publicidad

Error tratamiento ficheros XML con XML::Simple->XMLin

¿Ya sabes lo que es una referencia? Has progresado, el nível básico es cosa del pasado y ahora estás listo para el siguiente nivel.

Error tratamiento ficheros XML con XML::Simple->XMLin

Notapor coppeli » 2009-12-20 01:35 @107

Hola,

es la primera vez que publico un mensaje en el foro y quería felicitaros por la ayuda que prestáis a la gente.

Os comento el problema que tengo: me envían unos ficheros XML que, teóricamente, están en formato utf-8; cuando intento pasar el método XMLin del módulo XML::Simple y detecta acentos o caracteres raros el script me retorna error:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
not well-formed (invalid token) at line 31, column 89, byte 1946 at D:/Perl/site/lib/XML/Parser.pm line 187
        ...caught  
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Os pongo un ejemplo:
Sintáxis: [ Descargar ] [ Ocultar ]
Using xml Syntax Highlighting
<campo nombre="DESCRIPCION_LARGA">19/11/2009 - 14:22:45 - Rubén Doblado Lopezdesc</campo>
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


He intentado diferentes formas para tratar la información pero no me funciona ninguna de ellas, os detallo:

1.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. use XML::Simple;
  2. use Data::Dumper;
  3. use Encode;
  4.  
  5. $codificacion = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
  6.  
  7. $sNameFileOri = "D:/mensaje1258646652402.xml";
  8.  
  9. $sNameFileDes = "D:/mensaje1258646652402_new.xml";
  10.  
  11. $datos = $codificacion ."\n";
  12.  
  13. open  IN, $sNameFileOri ;
  14.  
  15. while ( <IN> )
  16. {
  17.         $datos .= $_;
  18. }
  19.  
  20. $data = decode("utf-8", $datos);
  21.  
  22. close IN;
  23.  
  24. open  OUT, "> $sNameFileDes" ;
  25.  
  26. print OUT $data;
  27.  
  28. close OUT;
  29.  
  30. # create object
  31. my $xml = new XML::Simple;
  32.                                        
  33. # read XML file
  34. my $data = $xml->XMLin($sNameFileDes);
  35.  
  36. print "=======================================================\n";
  37. print Dumper($data);
  38. print "=======================================================\n";
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


Resultado :
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
 {
   'content' => "19/11/2009 - 14:22:45 - Rub\x{fffd}n Doblado Lopezdesc",
   'nombre' => 'DESCRIPCION_LARGA'
 },
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


print() del valor por terminal :
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
nombre : data->solicitud->campo->DESCRIPCION_LARGA
content : data->solicitud->campo->19/11/2009 - 14:22:45 - Rub�n Doblado Lopezdesc
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


2. He intentado también abrirlo en utf y convertirlo a iso, pero tampoco

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
use open IN => ":utf8", OUT => ":encoding(iso-8859-15)";
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


3. Además he intentado utilizar los métodos del modulo Encode:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
from_to($datos, "iso-8859-1", "utf-8"); # from latin-1 to utf-8
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

y
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$octets = encode_utf8($datos);
$string = decode_utf8($octets);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


y tampoco me funciona.

Para intentar salir del paso y leyendo en el foro otro mensaje, me he creado una función para tratar la información, pero no es viable ya que no puedo modificar la información original del fichero:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
sub xml_parser_file
{
        $sNameFile = shift;
       
        my $linea = '';
        my $datos = '';
       
        open  IN, $sNameFile ;
                                       
        while ( <IN> )
        {
                $linea = $_;
                                               
                if ( $linea =~ /á|é|í|ó|ú|Á|É|Í|Ó|Ú|ñ|Ñ|«|»/ )
                {
                        $linea =~ tr/áéíóúÁÉÍÓÚñÑ«»/aeiouAEIOUnN""/;
                }
                                               
        $datos .= $linea;
                                               
        }

        close IN;

        open  OUT, "> $sNameFile" ;

        print OUT $datos;

        close OUT;
       
        return ( $defOK );
       
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Os agradecería me echarais un cable.

Gracias de antemano, un saludo.
coppeli
Perlero nuevo
Perlero nuevo
 
Mensajes: 2
Registrado: 2009-11-24 06:46 @323

Publicidad

Re: Error tratamiento ficheros XML con XML::Simple->XMLin

Notapor explorer » 2009-12-20 10:00 @458

Bienvenido a los foros de Perl en Español, coppeli.

He cargado tu línea, y la he puesto en un fichero xml, guardando el acento en formato UTF-8.

Luego, he ejecutado tu programa, que ha generado un nuevo fichero XML.

Me sale un error del XMLin() porque lo he creado con una cabecera que dice que lo que sigue está codificado en UTF-8, pero resulta que lo grabaste con codificación ISO-8859-1, la de por defecto que usa Perl, ya que no has indicado ninguna al hacer el open() de escritura. No me sale tu error, porque seguro que será debido a otra causa.

Si cambiamos la línea a
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. $codificacion = q(<?xml version="1.0" encoding="ISO-8859-1"?>);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

entonces no habrá problemas y obtendremos el resultado correcto:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
=======================================================
$VAR1 = {
          'campo' => {
                     'content' => "19/11/2009 - 14:22:45 - Rub\x{e9}n Doblado Lopezdesc",
                     'nombre' => 'DESCRIPCION_LARGA'
                   }
        };
=======================================================
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4
El acento está correctamente escrito en ISO-8859-1.

De todas maneras, lo normal es que al trabajar con XML, siempre trabajemos con UTF-8, ya que es la codificación por defecto de XML.

Utilizando la opción de pragma open: pues... quitamos el Encode y la línea de la llamada a la función decode(); cambiamos la línea 5 para que sea ISO-8859-15; agregamos la línea del use open tuya y cambiamos la línea 26 por
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. print OUT $datos;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

y el resultado es el mismo.

De todas maneras... repasando la documentación de XML::Simple, recomiendan el uso de la opción OutputFile para indicar en ese momento la codificación de salida, del fichero.

Así, supongamos que el fichero sea solo esa línea de prueba que has puesto. Entonces, con el siguiente programa:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use XML::Simple;
  3. use Data::Dumper;
  4.  
  5. my $xml_ref = XMLin('kk.xml', KeepRoot => 1);
  6. print Dumper $xml_ref;
  7.  
  8. open my $fh, '>:encoding(iso-8859-15)', 'kk_new.xml';
  9. XMLout( $xml_ref,
  10.     XMLDecl    => '<?xml version="1.0" encoding="ISO-8859-15"?>',
  11.     KeepRoot   => 1,
  12.     OutputFile => $fh,
  13. );
  14. close $fh;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

La salida sigue siendo la correcta: los acentos son transformados desde UTF-8 a la codificación interna de Perl:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
$VAR1 = {
          'campo' => {
                     'content' => "19/11/2009 - 14:22:45 - Rub\x{e9}n Doblado Lopezdesc",
                     'nombre' => 'DESCRIPCION_LARGA'
                   }
        };
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Y la salida del XML, se hace con codificación ISO-8859-15:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
explorer@casa:~/Documents/Desarrollo> cat kk.xml
<campo nombre="DESCRIPCION_LARGA">19/11/2009 - 14:22:45 - Rubén Doblado Lopezdesc</campo>
explorer@casa:~/Documents/Desarrollo> cat kk_new.xml
<?xml version="1.0" encoding="ISO-8859-15"?>
<campo nombre="DESCRIPCION_LARGA">19/11/2009 - 14:22:45 - Rub�n Doblado Lopezdesc</campo>
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4
(mi terminal está en UTF-8).

Fíjate también que no indicamos la codificación de entrada, porque XML::Simple supone que los XML siempre están en UTF-8.

Si... siempre siguiéramos la pauta de trabajar en formato UTF-8, entonces quedaría más simple:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use XML::Simple;
  3. use Data::Dumper;
  4.  
  5. my $xml_ref = XMLin('kk.xml', KeepRoot => 1);
  6. print Dumper $xml_ref;
  7.  
  8. XMLout( $xml_ref,
  9.     XMLDecl    => 1,
  10.     KeepRoot   => 1,
  11.     OutputFile => 'kk_new.xml',
  12. );
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Internamente sigue trabajando en ISO, porque así funcionarán mejor las operaciones de tratamiento de caracteres, pero a la hora de salida, al indicar un nombre de fichero a OutputFile (en lugar de un manejador de archivo), la salida la hará automáticamente a UTF8.

Todo esto también depende un poco de la versión de Perl que estés usando, claro. Lo normal es trabajar con versiones superiores a v5.8.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Error tratamiento ficheros XML con XML::Simple->XMLin

Notapor coppeli » 2009-12-21 09:32 @439

Hola explorer,

gracias por la respuesta. Respecto a la versión de Perl es la 5.8.3.

Te comento, he probado a realizar el cambio en la codificación a iso para la generación del nuevo fichero y funciona correctamente :D , este es el resultado:

fichero origen xml
21/12/2009 - 13:50:05 - ESTELA BODEGA ORTEGADESCRIPCION á é í ó ú Á É Í Ó Ú ñ Ñ « » ´

fichero destino xml
21/12/2009 - 13:50:05 - ESTELA BODEGA ORTEGADESCRIPCION á é í ó ú Á É Í Ó Ú ñ Ñ « » ´

Hasta ahí todo correcto, el problema me surge posteriormente, ya que esta información la introduzco en una base de datos y dicha información se está almacenando así:

21/12/2009 - 13:50:05 - ESTELA BODEGA ORTEGADESCRIPCION á é í ó ú Á É Í Ó Ú ñ Ñ « » ´

¿Podrías comentarme por donde tirar ahora?

Gracias de antemano, un saludo.
coppeli
Perlero nuevo
Perlero nuevo
 
Mensajes: 2
Registrado: 2009-11-24 06:46 @323

Re: Error tratamiento ficheros XML con XML::Simple->XMLin

Notapor explorer » 2009-12-21 10:28 @477

Las bases de datos suelen trabajar con una determinada codificación, que no sabemos, en tu caso, cuál es.

Por los datos que muestras, es claro que los ha guardado en formato UTF-8. Es posible que la base de datos, al recibir los caracteres, haya hecho una conversión.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España


Volver a Intermedio

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado

cron