• Publicidad

Generar XML

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

Re: Generar XML

Notapor explorer » 2012-02-27 17:06 @754

Ya te dije que manejar XML::Simple, puede ser muy complicado.

Una forma de atacar el problema es:

  1. Poner en un archivo XML el código que queremos manejar
  2. Leerlo con XMLin, y volcar la estructura que ha generado con Data::Dumper
  3. Volver a generar el xml con XMLout, buscando las opciones correctas

Así, creamos el xml así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using xml Syntax Highlighting
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <root>
  3.     <AddInfo>
  4.         <Line id="1">Otra Información opcional</Line>
  5.         <Line id="2"></Line>
  6.         <Line id="3"></Line>
  7.         <Line id="4"></Line>
  8.         <Line id="5"></Line>
  9.         <Line id="6"></Line>
  10.         <Line id="7"></Line>
  11.         <Line id="8"></Line>
  12.     </AddInfo>
  13.     <Items>
  14.         <Item Id="1" Price="10.00" Qty="1" Desc="Producto generico" Tax="1" Code="01234567" Comments="xxxxxx" />
  15.         <Item Id="2" Price="10.00" Qty="1" Desc="Producto generico 2" Tax="0" Code="01234577" Comments="xxxxxx" />
  16.     </Items>
  17. </root>
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
y ahora creamos un programa mínimo:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use 5.010;
  3. use utf8::all;                  # Turn on UTF-8. All of it.
  4.  
  5. use XML::Simple;
  6. use Data::Dumper::Simple;
  7.  
  8. my $xml = XMLin('kk.xml', KeyAttr => []);
  9.  
  10. say Dumper $xml;
  11.  
  12. say XMLout($xml);
  13. __END__
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
La salida es:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
$xml = {
         'Items' => {
                    'Item' => [
                              {
                                'Comments' => 'xxxxxx',
                                'Code' => '01234567',
                                'Qty' => '1',
                                'Id' => '1',
                                'Tax' => '1',
                                'Price' => '10.00',
                                'Desc' => 'Producto generico'
                              },
                              {
                                'Comments' => 'xxxxxx',
                                'Code' => '01234577',
                                'Qty' => '1',
                                'Id' => '2',
                                'Tax' => '0',
                                'Price' => '10.00',
                                'Desc' => 'Producto generico 2'
                              }
                            ]
                  },
         'AddInfo' => {
                      'Line' => [
                                {
                                  'content' => "Otra Informaci\x{f3}n opcional",
                                  'id' => '1'
                                },
                                {
                                  'id' => '2'
                                },
                                {
                                  'id' => '3'
                                },
                                {
                                  'id' => '4'
                                },
                                {
                                  'id' => '5'
                                },
                                {
                                  'id' => '6'
                                },
                                {
                                  'id' => '7'
                                },
                                {
                                  'id' => '8'
                                }
                              ]
                    }
       };

<opt>
  <AddInfo>
    <Line id="1">Otra Información opcional</Line>
    <Line id="2" />
    <Line id="3" />
    <Line id="4" />
    <Line id="5" />
    <Line id="6" />
    <Line id="7" />
    <Line id="8" />
  </AddInfo>
  <Items>
    <Item Code="01234567" Comments="xxxxxx" Desc="Producto generico" Id="1" Price="10.00" Qty="1" Tax="1" />
    <Item Code="01234577" Comments="xxxxxx" Desc="Producto generico 2" Id="2" Price="10.00" Qty="1" Tax="0" />
  </Items>
</opt>
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Tuve que poner KeyAttr => [], porque uno de los atributos es 'Id', que para XML::Simple es importante.

Con la salida de Data::Dumper vemos la estructura que tienes que crear, para que XMLout() genere la salida correcta.
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: Generar XML

Notapor calcifer1990 » 2012-02-28 07:40 @361

Gracias, explorer, lo probaré y comentaré los resultados.
calcifer1990
Perlero nuevo
Perlero nuevo
 
Mensajes: 26
Registrado: 2011-10-03 10:15 @468

Re: Generar XML

Notapor calcifer1990 » 2012-03-01 11:03 @502

Muchas gracias, funciona a la perfección, perdón por la demora.
calcifer1990
Perlero nuevo
Perlero nuevo
 
Mensajes: 26
Registrado: 2011-10-03 10:15 @468

Re: Generar XML

Notapor calcifer1990 » 2012-03-05 09:15 @427

¿Me podrían ayudar con estos errores, por favor?

Corregir caracteres especiales:
Ejemplo:
Sintáxis: [ Descargar ] [ Ocultar ]
Using xml Syntax Highlighting
<CustomerName>DISEÑOS</CustomerName>
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Y validar comillas para que no afecten las etiquetas del xml:
Sintáxis: [ Descargar ] [ Ocultar ]
Using xml Syntax Highlighting
<Item Code=" 10SCXA000901554 " dperc="0%" Qty="1" Tax="1" Id="130" Price="0.88" Desc="TEMFLEX ROJO (3/4" X 66') "/>
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


De antemano, muchas gracias.
calcifer1990
Perlero nuevo
Perlero nuevo
 
Mensajes: 26
Registrado: 2011-10-03 10:15 @468

Re: Generar XML

Notapor explorer » 2012-03-05 10:05 @462

Los caracteres especiales, en realidad, quiere decir que están codificados en utf-8, lo cual es acorde a lo que dice la norma.

Si necesitas hacer cambios en la codificación del archivo, debes usar alguna capa de E/S, con binmode(), por ejemplo. O usar las funciones de cambio de codificación que te da el módulo Encode.

Para el segundo caso, el único problema que veo es en el último atributo, que sí tiene unas dobles comillas como valor de ese atributo.

Una forma de solucionarlo sería "escapando" las comillas dobles convirtiéndolas a una entidad XML. En el caso de las comillas dobles, sería &quot; .

XML::Simple hace esto de forma automática, y activado por defecto (ver opción NoEscape).
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: Generar XML

Notapor calcifer1990 » 2012-03-05 14:28 @644

Gracias, explorer, pero tengo el siguiente error al utilizar encode():
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. encode("utf8",$variable)
  2.  
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


Sintáxis: [ Descargar ] [ Ocultar ]
Using xml Syntax Highlighting
  1. <CustomerName>DISEÑOS</CustomerName>
  2.  
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


o con decode():

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. decode("utf8",$variable)
  2.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Sintáxis: [ Descargar ] [ Ocultar ]
Using xml Syntax Highlighting
  1. <CustomerName>DISE�OS</CustomerName>
  2.  
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


¿Qué puede ser?

Gracias
calcifer1990
Perlero nuevo
Perlero nuevo
 
Mensajes: 26
Registrado: 2011-10-03 10:15 @468

Re: Generar XML

Notapor explorer » 2012-03-05 18:22 @806

A ver... no es tan simple...

¿Cuál es el proceso que realizas? ¿Lees de un fichero y escribes a otro? Entonces... ¿en qué está codificado el archivo de entrada? ¿en qué codificación debe estar la salida?

Si usas XML, ya sabes que la codificación por defecto de este tipo de archivos es UTF-8, así que hay que suponer que esa es la codificación de entrada, y suponemos también que esa es la codificación de salida.

En el caso que comentas, parece que el carácter que no se ve es una 'Ñ', codificada en UTF-8. ¿Qué es lo que quieres hacer con ese texto? Guardarlo en otro sitio, pero, ¿en qué codificación?

Lo que tienes es esto:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use 5.010;
  3. use Encode;
  4.  
  5. my $string = "<Tag>DISE\xC3\x91OS</Tag>";  # Una ristra de *bytes*
  6.  
  7. my $octets = decode_utf8($string);         # De esa ristra, la decodificamos como si estuviera en UTF-8, y
  8.                                            # la almacenamos como una ristra de *caracteres*,
  9.                                            # en el _formato interno de Perl_
  10.  
  11. binmode STDOUT, ':encoding(utf-8)';        # solicitamos que la salida por STDOUT debe ir codificado en UTF-8
  12.  
  13. say $octets;                               # Perl toma la ristra de *caracteres* (en formato Perl),
  14.                                            # y lo saca en codificación UTF-8
  15.  
  16. __END__
  17. <Tag>DISEÑOS</Tag>
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

Observa: no es lo mismo hablar de una ristra de bytes, que una ristra de caracteres. Con Encode podemos pasar de una codificación a otra o, como en este caso, pasamos de un formato conocido por nosotros (y no por Perl), al formato interno que usa Perl para almacenar caracteres. Una vez que lo tenemos, podemos hacer las cosas normales que hacemos con las operaciones de caracteres. Finalmente, en el momento de la salida de datos, tenemos que indicar en qué codificación debe ser la salida, ya que por defecto, Perl lo hace en codificación ISO-8859-1. Si la salida debe ser en UTF-8 (bien sea porque nuestra terminal de línea de comandos o el archivo donde estamos escribiendo están en esa codificación), entonces lo cambiamos con un binmode(), indicando la capa de E/S que Perl debe usar para hacer la conversión entre el formato interno.

Ahora bien... supongamos que tanto la entrada y la salida están en formato UTF-8, y que esa entrada y salida son (por simplificar también), las correspondientes a las estándares. Entonces, el programa queda muy simple:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use 5.010;
  3. use open qw(:utf8 :std);                               # Entradas y salidas estándar, en modo utf8
  4. use File::Slurp;                                       # Leer y escribir archivos
  5.  
  6. my $cadena = read_file('kk.txt', binmode => ':utf8');  # Leemos el archivo, codificado en utf8
  7.  
  8. # ...  aquí jugamos con la $cadena
  9.  
  10. say $cadena;                                           # La salida ya sabemos que va en UTF-8
  11.  
  12. __END__
  13. <Tag>DISEÑOS</Tag>
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Así que primero tenemos que saber en qué codificaciones tienes que trabajar... :)

A partir de Perl v5.12, y sobretodo a partir de Perl v5.14, todas las operaciones de cadenas usan semántica de caracteres (dentro del ámbito de la feature 'unicode_strings', que facilita mucho el trabajo con varias codificaciones, pero centrándose siempre en UTF-8).
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: Generar XML

Notapor calcifer1990 » 2012-03-06 07:56 @372

Hola, explorer. De nuevo muchas gracias por tu pronta respuesta.

Te explico: en el script no leo ningún archivo; utilicé XMLin() únicamente para mirar cómo crear el hash, ya que este se carga de una consulta a una base de datos, de la siguiente manera:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.     while ( $sth->fetchrow_arrayref() ) {
  2.  
  3.         $hashXml->{'CustomerName'} = [$variable];
  4.         $hashXml->{'CustomerRuc'}  = [
  5.             $variable;
  6.                 $hashXml->{'CustomerAddress'} = [$variable];
  7.  
  8.                 $hashXml->{'AddInfo'}->{Line}->[0] = {
  9.                 'content' => $variable,
  10.                 'id'      => '1',
  11.                 },
  12.             {   'content' => $variable,
  13.                 'id'      => '2'
  14.             },
  15.             $hashXml->{'AddInfo'}->{Line}->[1] = {
  16.                 'content' => $variable,
  17.                 'id'      => '2'
  18.             },
  19.  
  20.             $hashXml->{'Items'}->{Item}->[$cont] = {
  21.                 'Id'    => $variabl,
  22.                 'Price' => $variable,
  23.                 'Qty'   => $variable,
  24.                 'Desc'  => $variable,
  25.                 'dperc' => $variable . '%',
  26.                 'Tax'   => variable,
  27.                 'Code'  => $variable,
  28.             },
  29.             ;
  30.         }
  31.  
  32.  
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4


La codificación del archivo de salida debe ser ISO-8859-1, esto lo hago utilizando XMLDecl:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. $xs = XML::Simple->new(
  2.     ForceArray => 1,
  3.     KeepRoot   => 1,
  4.     RootName   => 'FiscalDoc',
  5.     XMLDecl    => '<?xml version="1.0" encoding="ISO-8859-1" ?>',
  6.     OutputFile => 'xxx.xml'
  7. );
  8.  
  9. $xml = $xs->XMLout($hashXml);
  10.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


El dato que contiene los caracteres UTF-8 lo trae la consulta a la base de datos. Si cambio el XMLDecl de la siguiente forma, funciona sin problemas:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.  XMLDecl => '<?xml version="1.0" encoding="UTF-8" ?>'
  2.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Pero por requerimiento del usuario, debe ser ISO-8859-1.

De nuevo muchas gracias.
calcifer1990
Perlero nuevo
Perlero nuevo
 
Mensajes: 26
Registrado: 2011-10-03 10:15 @468

Re: Generar XML

Notapor explorer » 2012-03-06 12:49 @575

Te faltan algunas llaves y corchetes, pero la idea se ve.

El caso es que esas asignaciones a $hashXml se pueden reducir bastante, si las agruparas.

Sobre el tema de la codificación, esto es lo que tienes que hacer: los datos que llegan de la base de datos, si están en UTF-8, les debes decodificar, con decode_utf8(). Así, las cadenas de texto se transforman de ristras de bytes a caracteres lógicos en formato Perl.

Luego, a la hora de guardar en disco, ejecutas un binmode() sobre el gestor de archivo abierto, y con el ':encoding("UTF-8")', y así se guardarán en esa codificació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: Generar XML

Notapor calcifer1990 » 2012-03-15 09:11 @424

Gracias explorer, perdón por la demora.

Entiendo tu idea pero no estoy seguro de la sintaxis.
Sería algo así pero no obtengo ningún resultado.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. decode_utf8($hashXml);
  2. binmode STDOUT, ':encoding(UTF-8)';
  3.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
calcifer1990
Perlero nuevo
Perlero nuevo
 
Mensajes: 26
Registrado: 2011-10-03 10:15 @468

AnteriorSiguiente

Volver a Básico

¿Quién está conectado?

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