Perl en Español

  1. Home
  2. Tutoriales
  3. Foro
  4. Artículos
  5. Donativos
  6. Publicidad
 

Convertir XML en TXT
Ir a página Anterior  1, 2
 
Publicar nuevo tema   Responder al tema    Foros de discusión -> Básico
Mensaje Sab Jul 12, 2008 6:13 am
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4143
Ubicación: Valladolid, España
Responder citando

Cuando XML::Simple lee esas marcas, las convierte a un hash vacío:
Código:
$VAR1 = \{
            'opr' => '0',
            'CodEstadoCivil' => '2',
            'CodOficina' => {},
            'letra' => 'V',
            'FechaCedOrg' => '2005-03-31',
            'SNombre' => 'Segundo Nombre',
            'cedula' => '123',
            'Sexo' => 'M',
            'PNombre' => 'nombre',
            'FechaNac' => '1980-07-25',
            'Naturalizado' => {},
            'CodObjecion' => '00',
            'PApellido' => 'apellido'
          };


Lo que se puede hacer es preguntar antes si tenemos un dato o es un hash vacío:
Perl:
my $CodOficina = 'NULL';
if ( exists $datos->{CodOficina} ) {
    if ( ref($datos->{CodOficina}) ne 'HASH' ) {
        $CodOficina = $datos->{CodOficina};
    }
}

my $Naturalizado = 'NULL';
if ( exists $datos->{Naturalizado} ) {
    if ( ref($datos->{Naturalizado}) ne 'HASH' ) {
        $Naturalizado = $datos->{Naturalizado};
    }
}


Y ya solo queda pintarlo:
Perl:
print join q{|},
        $datos->{opr}            ,
        $datos->{letra}          ,
        $datos->{cedula}         ,
        $datos->{PNombre}        ,
        $datos->{SNombre}        ,
        $datos->{PApellido}      ,
        $datos->{FechaNac}       ,
        $datos->{FechaCedOrg}    ,
        $datos->{CodObjecion}    ,
        $CodOficina     ,
        $datos->{CodEstadoCivil} ,
        $Naturalizado   ,
        $datos->{Sexo};
print "\n";
Sale:
Código:
0|V|123|nombre|Segundo Nombre|apellido|1980-07-25|2005-03-31|00|NULL|2|NULL|M
Mensaje Sab Jul 12, 2008 11:13 am
chechoman
Perlero Nuevo
Perlero Nuevo
Registrado: 02 Jul 2008
Mensajes: 19
Responder citando

Sí funciono, gracias. Solo me está faltando que el programa en Perl pueda leer valores como 'ñ', 'Ñ' y palabras acentuadas, que algunos nombres incluyen estos datos y vienen en el XML, y Perl al leerlo no los reconoce y cuando empieza a procesar me arroja el error:
Código:
not well-formed (invalid token) at line 1, column 214, byte 214 at /usr/local/lib/perl/5.8.8/XML/Parser.pm line 187


Me puse a averiguar y averiguar dándome cabezazos y resulta que es efectivamente porque se necesita una forma para parsear estos caracteres :s.

Instalé entonces en el sistema la librería "expat" y después a través del CPAN instalé la librería XML::Parser, pero no me sirvió de mucho, pensé que quizás debería leer todo el xml y por cada símbolo que consiga lo cambie por un valor "x" y después cuando lo vaya a guardar el valor "x" lo transforme en el que corresponde, pero me pareció algo super enrollado ademas de que me puede saturar el servicio con tantos cálculos que realiza, ya que este programa en Perl está realizando varias cosas como por ejemplo leer muchos .zip y verificar la integridad a través de sha1 y compararla, después descomprimirlos y hacer un respaldo del zip, posteriormente leer los xml y procesarlos y es ahí donde me arroja el error con los caracteres, de verdad no sé qué hacer por ahí :s
Mensaje Sab Jul 12, 2008 11:49 am
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4143
Ubicación: Valladolid, España
Responder citando

Tienes que ver cómo está codificado el carácter que está en la posición de fallo que te indica (línea 1, columna 214). Debe coincidir la codificación con la indicada en la cabecera del xml.
Mensaje Sab Jul 12, 2008 12:32 pm
chechoman
Perlero Nuevo
Perlero Nuevo
Registrado: 02 Jul 2008
Mensajes: 19
Responder citando

No, pues la codificación del xml es utf-8, y como estos son caracteres que no están dentro de esta configuración es que arroja el error.
Mensaje Sab Jul 12, 2008 1:07 pm
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4143
Ubicación: Valladolid, España
Responder citando

Precisamente. No es un error lo que te sale en el mensaje. Si la codificación interna de los caracteres no coincide con lo que pone en la cabecera, entonces el xml no está bien formado (not well-formed), y por eso es rechazado.

Deberás decidir qué hacer:
* cambiar la cabecera para que refleje la codificación de esos caracteres
* cambiar la codificación de esos caracteres, en origen (no tú)
* cambiar la codificación de esos caracteres tú mismo.

La más cómoda es la primera: solo tienes que cambiar una línea.
La más idónea es la segunda: no es problema tuyo recibir xml que están mal formados
La más horrible es la tercera: convertirá el proyecto informático en una inmensa chapuza.


P.D. Hablando de acentos, se te escapan algunos, cuando escribes aquí Smile

Ultima edición por explorer el Dom Jul 13, 2008 5:49 am, editado 1 vez
Mensaje Sab Jul 12, 2008 11:03 pm
chechoman
Perlero Nuevo
Perlero Nuevo
Registrado: 02 Jul 2008
Mensajes: 19
Responder citando

Es correcto, lo que dices es cierto, pero la realidad es que los xml van a llegar siempre con este esquema (mal formado en este caso), la verdad es que el origen debería entregarme cada xml con los datos correctos, es decir en caso de una 'ñ' que tenga '&#241' pero eso no va a suceder, entonces lo que he pensado hacer es leer cada XML y que me busque los caracteres especiales, es decir 'ñ', 'Ñ', 'í', 'ó', 'ú', 'á', 'é', etc. y los reemplace por el código correspondiente, es decir la 'ñ' por '&#241', pero no me funciona Sad, busqué también si es algo sobre el utf8 y por eso coloqué la línea "use utf8;" pero tampoco funcionó, solo lo único que quiero es que al leer cada XML verifique si consigue alguno de estos caracteres y los sustituya por los caracteres que sí puede leer, o sea, si consigue una 'ñ' la cambie por '&#241' en el archivo XML.
Mensaje Dom Jul 13, 2008 9:28 am
chechoman
Perlero Nuevo
Perlero Nuevo
Registrado: 02 Jul 2008
Mensajes: 19
Responder citando

Estuve haciendo otras pruebas directamente en el XML, y resulta que si cambio en la primera etiqueta "<?xml ..... " el valor que dice encoding="utf-8" por el de "iso-8859-1" cuando ejecuto el programa en Perl lo hace perfectamente, con eso me doy cuenta que el problema se resuelve al cambiar este valor, el asunto es que no logro hacerlo de forma automática, es decir sin tener que yo abrir el archivo XML y cambiarle este valor, ¿habrá alguna forma de que mi programa abra el XML , le cambie este valor, lo cierre y de ahí siga el proceso de lectura?.
Mensaje Dom Jul 13, 2008 11:18 am
Jenda
Perlero Frecuente
Perlero Frecuente
Registrado: 29 Oct 2007
Mensajes: 106
Ubicación: Praga, Republica Checa
Responder citando

XMLin te devuelve los datos en utf8, espero que los quieres en un código diferente.
http://search.cpan.org/~dankogai/Encode-2.26/Encode.pm
Mensaje Dom Jul 13, 2008 11:34 am
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4143
Ubicación: Valladolid, España
Responder citando

Esa es la peor solución. Se llama 'codificar en entidades' (busca por 'entities' en estos foros).

Primero: aún no nos has dicho en qué están codificados esos caracteres. Hemos supuesto que si es un XML y en la cabecera pone algo como encoding="UTF-8" entonces el contenido debería estar codificado de esa manera. Si está en otra, estás en problemas.

Segundo: Perl, por defecto, piensa que siempre estás trabajando con la codificación iso-8859-1, que es la más normal, con los caracteres anglosajones y centroeuropeos. En Español usamos el iso-8859-15, porque además de los acentos incluye el signo del euro. Cuando necesitamos que Perl gestione ficheros, entradas y/o salidas en que la codificación de unos es distinta de la codificación de salida, tenemos que indicarle a Perl cuáles son esas codificaciones. El uso de 'use utf8;' dentro de un programa solo sirve para decirle a Perl que ese mismo programa contiene algunos caracteres escritos en esa codificación. No sirve para decirle que vamos a leer o escribir en esa codificación. Es solo para los caracteres escritos en el propio programa.

Aquí tienes un ejemplo de trabajo con caracteres escritos en otra codificación.

Tenemos el siguiente fichero xml:
XML:
<?xml version="1.0" encoding="UTF-8"?>
<datos 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>Office</CodOficina>
        <CodEstadoCivil>2</CodEstadoCivil>
        <Naturalizado></Naturalizado>
        <Sexo>M</Sexo>
</datos>

Fíjate que en la entrada '<letra>' he incluido un montón de caracteres 'extraños'. Esto lo he hecho con un editor de textos que escribe en codificación utf8 y, además, mi terminal de trabajo también está en utf8. Para comprobar que está bien escrito en utf8, lo volcamos a nivel de byte:
Código:
explorer@casa:~/Documents/Desarrollo> hexdump -C kk.xml
00000000  3c 3f 78 6d 6c 20 76 65  72 73 69 6f 6e 3d 22 31  |<?xml version="1|
00000010  2e 30 22 20 65 6e 63 6f  64 69 6e 67 3d 22 55 54  |.0" encoding="UT|
00000020  46 2d 38 22 3f 3e 0a 3c  64 61 74 6f 73 20 6f 70  |F-8"?>.<datos op|
00000030  72 3d 22 30 22 3e 0a 20  20 20 20 20 20 20 20 3c  |r="0">.        <|
00000040  6c 65 74 72 61 3e 56 c3  b1 c3 91 c3 a1 c3 a9 c3  |letra>V.........|
00000050  ad c3 b3 c3 ba c3 81 c3  89 c3 8d c3 93 c3 9a 3c  |...............<|
00000060  2f 6c 65 74 72 61 3e 0a  20 20 20 20 20 20 20 20  |/letra>.        |
00000070  3c 63 65 64 75 6c 61 3e  31 32 33 3c 2f 63 65 64  |<cedula>123</ced|
00000080  75 6c 61 3e 0a 20 20 20  20 20 20 20 20 3c 50 4e  |ula>.        <PN|
00000090  6f 6d 62 72 65 3e 6e 6f  6d 62 72 65 3c 2f 50 4e  |ombre>nombre</PN|
000000a0  6f 6d 62 72 65 3e 0a 20  20 20 20 20 20 20 20 3c  |ombre>.        <|
000000b0  53 4e 6f 6d 62 72 65 3e  53 65 67 75 6e 64 6f 20  |SNombre>Segundo |
000000c0  4e 6f 6d 62 72 65 3c 2f  53 4e 6f 6d 62 72 65 3e  |Nombre</SNombre>|
000000d0  0a 20 20 20 20 20 20 20  20 3c 50 41 70 65 6c 6c  |.        <PApell|
000000e0  69 64 6f 3e 61 70 65 6c  6c 69 64 6f 3c 2f 50 41  |ido>apellido</PA|
000000f0  70 65 6c 6c 69 64 6f 3e  0a 20 20 20 20 20 20 20  |pellido>.       |
00000100  20 3c 46 65 63 68 61 4e  61 63 3e 31 39 38 30 2d  | <FechaNac>1980-|
00000110  30 37 2d 32 35 3c 2f 46  65 63 68 61 4e 61 63 3e  |07-25</FechaNac>|
00000120  0a 20 20 20 20 20 20 20  20 3c 46 65 63 68 61 43  |.        <FechaC|
00000130  65 64 4f 72 67 3e 32 30  30 35 2d 30 33 2d 33 31  |edOrg>2005-03-31|
00000140  3c 2f 46 65 63 68 61 43  65 64 4f 72 67 3e 0a 20  |</FechaCedOrg>. |
00000150  20 20 20 20 20 20 20 3c  43 6f 64 4f 62 6a 65 63  |       <CodObjec|
00000160  69 6f 6e 3e 30 30 3c 2f  43 6f 64 4f 62 6a 65 63  |ion>00</CodObjec|
00000170  69 6f 6e 3e 0a 20 20 20  20 20 20 20 20 3c 43 6f  |ion>.        <Co|
00000180  64 4f 66 69 63 69 6e 61  3e 4f 66 66 69 63 65 3c  |dOficina>Office<|
00000190  2f 43 6f 64 4f 66 69 63  69 6e 61 3e 0a 20 20 20  |/CodOficina>.   |
000001a0  20 20 20 20 20 3c 43 6f  64 45 73 74 61 64 6f 43  |     <CodEstadoC|
000001b0  69 76 69 6c 3e 32 3c 2f  43 6f 64 45 73 74 61 64  |ivil>2</CodEstad|
000001c0  6f 43 69 76 69 6c 3e 0a  20 20 20 20 20 20 20 20  |oCivil>.        |
000001d0  3c 4e 61 74 75 72 61 6c  69 7a 61 64 6f 3e 3c 2f  |<Naturalizado></|
000001e0  4e 61 74 75 72 61 6c 69  7a 61 64 6f 3e 0a 20 20  |Naturalizado>.  |
000001f0  20 20 20 20 20 20 3c 53  65 78 6f 3e 4d 3c 2f 53  |      <Sexo>M</S|
00000200  65 78 6f 3e 0a 3c 2f 64  61 74 6f 73 3e 0a        |exo>.</datos>.|
0000020e

Vemos que los caracteres extraños están codificados así:
Código:
c3 b1 c3 91 c3 a1 c3 a9 c3 ad c3 b3 c3 ba c3 81 c3 89 c3 8d c3 93 c3 9a
que, efectivamente, indica que los caracteres están codificados en utf8 (ocupan dos bytes, en lugar de uno solo, si estuvieran codificados en iso-8859-1 o iso-8859-15).

Ahora, tenemos el siguiente programa:
Perl:
#!/usr/bin/perl
use XML::Simple;
use Data::Dumper;

my $datos = XMLin('kk.xml');
print Dumper \$datos;

my $CodOficina = 'NULL';
if ( exists $datos->{CodOficina} ) {
    if ( ref($datos->{CodOficina}) ne 'HASH' ) {
        $CodOficina = $datos->{CodOficina};
    }
}

my $Naturalizado = 'NULL';
if ( exists $datos->{Naturalizado} ) {
    if ( ref($datos->{Naturalizado}) ne 'HASH' ) {
        $Naturalizado = $datos->{Naturalizado};
    }
}

#binmode(STDOUT, ':utf8');

print join q{|},
        $datos->{opr}            ,
        $datos->{letra}          ,
        $datos->{cedula}         ,
        $datos->{PNombre}        ,
        $datos->{SNombre}        ,
        $datos->{PApellido}      ,
        $datos->{FechaNac}       ,
        $datos->{FechaCedOrg}    ,
        $datos->{CodObjecion}    ,
        $CodOficina     ,
        $datos->{CodEstadoCivil} ,
        $Naturalizado   ,
        $datos->{Sexo};
print "\n";
Es el mismo programa tuyo de antes, pero le he añadido una línea, comentada:
Perl:
#binmode(STDOUT, ':utf8');
luego explico porqué.

Si lo ejecutamos, la salida es:
Código:
explorer@casa:~/Documents/Desarrollo> ./kk.pl
$VAR1 = \{
            'opr' => '0',
            'CodEstadoCivil' => '2',
            'CodOficina' => 'Office',
            'letra' => "V\x{f1}\x{d1}\x{e1}\x{e9}\x{ed}\x{f3}\x{fa}\x{c1}\x{c9}\x{cd}\x{d3}\x{da}",
            'FechaCedOrg' => '2005-03-31',
            'SNombre' => 'Segundo Nombre',
            'cedula' => '123',
            'Sexo' => 'M',
            'PNombre' => 'nombre',
            'FechaNac' => '1980-07-25',
            'Naturalizado' => {},
            'CodObjecion' => '00',
            'PApellido' => 'apellido'
          };
0|V������������|123|nombre|Segundo Nombre|apellido|1980-07-25|2005-03-31|00|Office|2|NULL|M
Vemos lo siguiente:
* fijándonos en la línea de la marca '<letra>', vemos que Perl, con el módulo XML::Simple, ha leído correctamente el fichero: estaba en utf8 y ha transformado los caracteres extraños en codificación iso-8859-1:
Código:
\x{f1}\x{d1}\x{e1}\x{e9}\x{ed}\x{f3}\x{fa}\x{c1}\x{c9}\x{cd}\x{d3}\x{da}
    ñ     Ñ     á     é     í     ó     ú     Á     É     Í     Ó     Ú

* pero, a la hora de hacer el print, vemos que salen caracteres mucho más extraños.

Eso es debido a que mi terminal está trabajando en la codificación utf8, y Perl me está mandando caracteres que están en iso-8859-1. Si cambio la codificación de mi terminal a iso-8859-1, la salida es correcta:
Código:
0|VñÑáéíóúÁÉÍÓÚ|123|nombre|Segundo Nombre|apellido|1980-07-25|2005-03-31|00|Office|2|NULL|M

Bien, entonces el problema está en que queremos que los caracteres que saquemos hacia el exterior (sea la salida estándar o un fichero, queremos que lo haga en la misma codificación que la entrada: utf8.

Nos basta indicar a Perl que en las operaciones de ficheros, aplique un cambio de codificación.

Si descomentamos la línea anterior:
Perl:
binmode(STDOUT, ':utf8');
le estamos diciendo que la salida estándar (STDOUT, el que usa por defecto el print) queremos que sea en codificación 'utf8'. Perl hará los cambios de los caracteres y nos sacará el resultado deseado:
Código:
explorer@casa:~/Documents/Desarrollo> ./kk.pl
$VAR1 = \{
            'opr' => '0',
            'CodEstadoCivil' => '2',
            'CodOficina' => 'Office',
            'letra' => "V\x{f1}\x{d1}\x{e1}\x{e9}\x{ed}\x{f3}\x{fa}\x{c1}\x{c9}\x{cd}\x{d3}\x{da}",
            'FechaCedOrg' => '2005-03-31',
            'SNombre' => 'Segundo Nombre',
            'cedula' => '123',
            'Sexo' => 'M',
            'PNombre' => 'nombre',
            'FechaNac' => '1980-07-25',
            'Naturalizado' => {},
            'CodObjecion' => '00',
            'PApellido' => 'apellido'
          };
0|VñÑáéíóúÁÉÍÓÚ|123|nombre|Segundo Nombre|apellido|1980-07-25|2005-03-31|00|Office|2|NULL|M
Para comprobar que, efectivamente, están en utf8, hacemos lo de antes, un volcado a nivel de byte:
explorer@casa:~/Documents/Desarrollo> ./kk.pl|hexdump -C
Código:
00000000  24 56 41 52 31 20 3d 20  5c 7b 0a 20 20 20 20 20  |$VAR1 = \{.     |
00000010  20 20 20 20 20 20 20 27  6f 70 72 27 20 3d 3e 20  |       'opr' => |
00000020  27 30 27 2c 0a 20 20 20  20 20 20 20 20 20 20 20  |'0',.           |
00000030  20 27 43 6f 64 45 73 74  61 64 6f 43 69 76 69 6c  | 'CodEstadoCivil|
00000040  27 20 3d 3e 20 27 32 27  2c 0a 20 20 20 20 20 20  |' => '2',.      |
00000050  20 20 20 20 20 20 27 43  6f 64 4f 66 69 63 69 6e  |      'CodOficin|
00000060  61 27 20 3d 3e 20 27 4f  66 66 69 63 65 27 2c 0a  |a' => 'Office',.|
00000070  20 20 20 20 20 20 20 20  20 20 20 20 27 6c 65 74  |            'let|
00000080  72 61 27 20 3d 3e 20 22  56 5c 78 7b 66 31 7d 5c  |ra' => "V\x{f1}\|
00000090  78 7b 64 31 7d 5c 78 7b  65 31 7d 5c 78 7b 65 39  |x{d1}\x{e1}\x{e9|
000000a0  7d 5c 78 7b 65 64 7d 5c  78 7b 66 33 7d 5c 78 7b  |}\x{ed}\x{f3}\x{|
000000b0  66 61 7d 5c 78 7b 63 31  7d 5c 78 7b 63 39 7d 5c  |fa}\x{c1}\x{c9}\|
000000c0  78 7b 63 64 7d 5c 78 7b  64 33 7d 5c 78 7b 64 61  |x{cd}\x{d3}\x{da|
000000d0  7d 22 2c 0a 20 20 20 20  20 20 20 20 20 20 20 20  |}",.            |
000000e0  27 46 65 63 68 61 43 65  64 4f 72 67 27 20 3d 3e  |'FechaCedOrg' =>|
000000f0  20 27 32 30 30 35 2d 30  33 2d 33 31 27 2c 0a 20  | '2005-03-31',. |
00000100  20 20 20 20 20 20 20 20  20 20 20 27 53 4e 6f 6d  |           'SNom|
00000110  62 72 65 27 20 3d 3e 20  27 53 65 67 75 6e 64 6f  |bre' => 'Segundo|
00000120  20 4e 6f 6d 62 72 65 27  2c 0a 20 20 20 20 20 20  | Nombre',.      |
00000130  20 20 20 20 20 20 27 63  65 64 75 6c 61 27 20 3d  |      'cedula' =|
00000140  3e 20 27 31 32 33 27 2c  0a 20 20 20 20 20 20 20  |> '123',.       |
00000150  20 20 20 20 20 27 53 65  78 6f 27 20 3d 3e 20 27  |     'Sexo' => '|
00000160  4d 27 2c 0a 20 20 20 20  20 20 20 20 20 20 20 20  |M',.            |
00000170  27 50 4e 6f 6d 62 72 65  27 20 3d 3e 20 27 6e 6f  |'PNombre' => 'no|
00000180  6d 62 72 65 27 2c 0a 20  20 20 20 20 20 20 20 20  |mbre',.         |
00000190  20 20 20 27 46 65 63 68  61 4e 61 63 27 20 3d 3e  |   'FechaNac' =>|
000001a0  20 27 31 39 38 30 2d 30  37 2d 32 35 27 2c 0a 20  | '1980-07-25',. |
000001b0  20 20 20 20 20 20 20 20  20 20 20 27 4e 61 74 75  |           'Natu|
000001c0  72 61 6c 69 7a 61 64 6f  27 20 3d 3e 20 7b 7d 2c  |ralizado' => {},|
000001d0  0a 20 20 20 20 20 20 20  20 20 20 20 20 27 43 6f  |.            'Co|
000001e0  64 4f 62 6a 65 63 69 6f  6e 27 20 3d 3e 20 27 30  |dObjecion' => '0|
000001f0  30 27 2c 0a 20 20 20 20  20 20 20 20 20 20 20 20  |0',.            |
00000200  27 50 41 70 65 6c 6c 69  64 6f 27 20 3d 3e 20 27  |'PApellido' => '|
00000210  61 70 65 6c 6c 69 64 6f  27 0a 20 20 20 20 20 20  |apellido'.      |
00000220  20 20 20 20 7d 3b 0a 30  7c 56 c3 b1 c3 91 c3 a1  |    };.0|V......|
00000230  c3 a9 c3 ad c3 b3 c3 ba  c3 81 c3 89 c3 8d c3 93  |................|
00000240  c3 9a 7c 31 32 33 7c 6e  6f 6d 62 72 65 7c 53 65  |..|123|nombre|Se|
00000250  67 75 6e 64 6f 20 4e 6f  6d 62 72 65 7c 61 70 65  |gundo Nombre|ape|
00000260  6c 6c 69 64 6f 7c 31 39  38 30 2d 30 37 2d 32 35  |llido|1980-07-25|
00000270  7c 32 30 30 35 2d 30 33  2d 33 31 7c 30 30 7c 4f  ||2005-03-31|00|O|
00000280  66 66 69 63 65 7c 32 7c  4e 55 4c 4c 7c 4d 0a     |ffice|2|NULL|M.|
0000028f
Lo interesante está al final. Vemos que en el offset 0x22A empieza la secuencia de bytes de los caracteres acentuados, dos bytes cada uno, en codificación 'utf8'.

Pero entonces... ¿por qué hay tanto lío? Es decir, ¿por qué el módulo XML::Simple trabaja de esta manera, leyendo 'utf8' y pasándolo a iso-8859-1? ¿y por qué tenemos que indicar a mano la codificación de salida? En parte, la respuesta es por la forma de trabajo tradicional de Perl: siempre piensa que estamos en iso-8859-1 (algo que ya se ha cambiado desde la versión 5.8 en adelante). Y el por qué tenemos que hacer el cambio de codificación en la salida de datos es porque XML::Simple no contempla ese trabajo con el xml... es decir... si leemos el manual del módulo, habla de leer, modificar y de escribir el xml. Pero no habla nada de pintar los valores, de forma independiente. Hay un problema mayor: XML::Simple no maneja la codificación de los caracteres. Esa labor la hacen los módulos que hacen el 'parseado' del fichero (XML::Parser o SAX) Según sea uno u otro, el comportamiento es distinto. Y también distinto si tu versión de Perl es inferior a la 5.8.8. A la hora de sacar el fichero fuera, saldrá según la codificación indicada para el manipulador del fichero indicado.

Hay varias soluciones.

1.- Hacer que Perl trabaje siempre en 'utf8' en las operaciones de entrada y salida. Una forma de hacerlo es poniendo la opción '-CS' para el intérprete perl. En la primera línea, ponemos
Perl:
#!/usr/bin/perl -CS
y todas las salidas serán con codificación 'utf8'. Más información en perlrun.

2.- Usar binmode() u open() con una codificación para indicar qué codificación usar. Ejemplo de binmode(), la línea comentada de arriba. Ejemplo de open:
Perl:
open my $fh, '>:encoding(utf8)', $fichero or die "$!\n";
XMLout($ref, OutputFile => $fh);


Hay más opciones, como usar el pragma 'open', pero lo más recomendable es usar la segunda propuesta: indicar la codificación en el momento del open().

Hilo del mismo tema en otro foro: http://coding.derkeiler.com/Archive/Perl/comp.lang.perl.misc/2006-03/threads.html#01574

Ultima edición por explorer el Lun Sep 01, 2008 4:06 pm, editado 1 vez
Mensaje Dom Jul 13, 2008 11:42 am
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4143
Ubicación: Valladolid, España
Responder citando

chechoman escribió:
Estuve haciendo otras pruebas directamente en el XML, y resulta que si cambio en la primera etiqueta "<?xml ..... " el valor que dice encoding="utf-8" por el de "iso-8859-1" cuando ejecuto el programa en Perl lo hace perfectamente

Ya tenemos una pista. Es posible que el fichero esté codificado en iso-8859-1.

Si es así, puedes leer el fichero de esta manera:

Perl:
open my $fh, '<:encoding(iso-8859-1)', 'kk.xml' or die "$!\n";
my $datos = XMLin($fh);
Mensaje Lun Jul 14, 2008 1:43 pm
chechoman
Perlero Nuevo
Perlero Nuevo
Registrado: 02 Jul 2008
Mensajes: 19
Responder citando

Bueno, explorer, ante todo muchas gracias por toda tu ayuda, y también por toda la ayuda de las demás personas que han participado en este tema.

Resulta que el problema es que los XML me vienen con una codificación que me causaba problemas (UTF-8) así que lo que tenía que hacer era leer el xml, buscar este texto y colocarle iso-8859-1 la cual es la codificación que me sirve. Al principio lo hice con un comando de Linux: sed, pero el problema era que se tardaba mucho en la ejecución, es decir, por unos 40 mil archivos tardaba alrededor de 20 minutos, así que escribí unas líneas para que hiciera todo dentro del mismo Perl ¡y la ejecución bajo a unos 7 minutos! Aquí agrego entonces el código para permitir leer las 'ñ' y los acentos en un XML:
Perl:
my $filename="/home/principal/lector/xml/$a";
my $oldtext="UTF-8";
my $newtext="iso-8859-1";

open (IN, "$filename") || die $!;
## imprimo el contenido moficado en el archivo .bak
open (OUT, ">$filename.bak") || die $!;
while ($_ = <IN> ) {
    ## Si existe el texto lo reemplazo
    if ($_ =~ /$oldtext/i) {
        $_ =~ s/$oldtext/$newtext/gi;
    }
    print OUT "$_";
}
close (OUT);
close (IN);
#  if ($filename =~ /\.wiki|\.awiki/)
## copio el contenido del archivo moficado .bak al archivo original
rename("$filename.bak","$filename") || die $!;
Mensaje Lun Jul 14, 2008 4:43 pm
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4143
Ubicación: Valladolid, España
Responder citando

Dos puntualizaciones.

La primera, decirte que si los XML están en una codificación distinta de la indicada en la cabecera, entonces la culpa no es tuya, sino del origen. Que lo despidan Smile

La segunda, que no necesitas hacer nada de lo que indicas si abres el xml como te indicaba un poco más arriba, con el open().

De todas formas, enhorabuena por encontrar la solución.
Publicar nuevo tema   Responder al tema    Foros de discusión -> Básico Todas las horas son GMT - 6 Horas
Ir a página Anterior  1, 2
Página 2 de 2



Powered by phpBB © 2001, 2005 phpBB Group