• Publicidad

Convertir una respuesta SOAP a XML

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

Convertir una respuesta SOAP a XML

Notapor coltx » 2016-12-08 19:18 @846

Hola estimados, tengo la siguiente duda: estoy capturando desde un web service con el siguiente script una respuesta SOAP:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
$VAR1 = {
        'S:Body' => {
                'ns4:SinteIED' => {
                        'xmlns:ns4' => 'http://ws.iid.sd.eedt.cl/SinteIED',
                        'xmlns:ns3' => 'http://ws.iid.sd.eedt.cl/Consultar',
                        'MovimientosCliente' => {
                                'Movimiento' => [
                                        {
                                                'NOMBRE' => 'ALTIMAS,
                                                'MONTO' => '0.0',
                                                'PAIS_CODIGO' => '522',
                                                'GUIAS' => [
                                                        {
                                                                'LUGRA' => 'CLAVE',
                                                                'FECHA' => '2016-11-23',
                                                                'NRO' => '2885'
                                                        }
                                                ],
                                        }
                                ]
                        },
                        'xmlns:ns2' => 'http://ws.iid.sd.eedt.cl/MovimientosClienteWS'
                }
        },
        'xmlns:S' => 'http://schemas.xmlsoap.org/soap/envelope/'
};
 
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Ahora bien, cuando trato de leer el mensaje a través del siguiente script no puedo leerlo:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2.  
  3. # use module
  4. use XML::Simple;
  5. use Data::Dumper;
  6.  
  7. # create object
  8. my $xml = new XML::Simple;
  9.  
  10. # read XML file
  11. my $data = $xml->XMLin("TOTAL.xml", ForceArray => ["BULTOS","ITEMS","GUIAS"], SuppressEmpty => '');
  12.  
  13. for my $MOV ( @{$data->{Movimiento}} ) {
  14.  
  15.          print "NOMBRE => $MOV->{NOMBRE} \n";
  16.  
  17. }
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

por lo cual tengo que transformar el mensaje de esta forma para que el script lo pueda tomar:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
$VAR1 = {
        'Movimiento' => [
                {
                        'NOMBRE' => 'ALTIMAS,
                        'MONTO' => '0.0',
                        'PAIS_CODIGO' => '522',
                        'GUIAS' => [
                                {
                                        'LUGRA' => 'CLAVE',
                                        'FECHA' => '2016-11-23',
                                        'NRO' => '2885'
                                }
                        ],
                }
        ]
}
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

¿Es posible transformar la primera respuesta SOAP a XML? ¿O bien qué me recomiendan o bien cómo mejorar el script para leer el mensaje original sin tener que cambiar el mensaje?

Gracias.
coltx
Perlero nuevo
Perlero nuevo
 
Mensajes: 79
Registrado: 2011-09-16 08:01 @376

Publicidad

Re: Convertir una respuesta SOAP a XML

Notapor explorer » 2016-12-09 18:42 @821

Lo que muestras en la primera caja de código, ¿qué es? ¿Por qué lo llamas la respuesta? Se supone que la respuesta SOAP debe estar en formato XML, y eso más bien parece el volcado de una estructura de datos Perl.

Sin ver el XML original, poco se puede decir a XML::Simple.

De todas maneras, hay formas mejores de tratar con este tema. Por ejemplo con SOAP::Lite, que se encargaría de hacer la interpretación de la respuesta y convertirla en una estructura Perl 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

Re: Convertir una respuesta SOAP a XML

Notapor coltx » 2016-12-10 12:26 @560

Hola, explorer. Efectivamente, la respuesta XML del SOAP es la siguiente:

<?xml version="1.0" ?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns4:SinteIED xmlns:ns2="http://ws.iid.sd.eedt.cl/SinteIED/MovimientosCliente" xmlns:ns3="http://ws.iid.sd.eedt.cl/SinteIED/Consultar" xmlns:ns4="http://ws.iid.sd.eedt.cl/SinteIED"><MovimientosCliente><Movimiento>
<NOMBRE>ALTIMAS</NOMBRE>
<MONTO>150</MONTO>
<PAIS_CODIGO>522</PAIS_CODIGO>
<GUIAS>
<LUGAR>CLAVE</LUGAR>
<FECHA>2016-12-02</FECHA>
<NRO>3344</NRO>
</GUIAS>
<DETALLE>
<LINEA>1</LINEA>
<PROD>SHAMPOO</PROD>
</DETALLE>
</Movimiento>
</MovimientosCliente>
</ns4:SinteIED >
</S:Body>
</S:Envelope>

Y tengo el siguiente script para leer el mensaje, pero no sé cómo tomar en este caso el nodo GUIAS o el nodo DETALLE. Ese es mi problema en realidad... por eso lo estaba intentando con el XML::Simple, por favor, tu ayuda.


#!/usr/bin/perl

use LWP::UserAgent;
use HTTP::Request::Common;
use Data::Dumper;


my $userAgent = LWP::UserAgent->new();

my $message = '<?xml version="1.0" encoding="iso-8859-1"?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:con="http://ws.iid.sd.eedt.cl/Consultar">
<soapenv:Header/>
<soapenv:Body>
<con:Consultar>
<Desde>2016-10-01</Desde>
<Hasta>2016-11-10</Hasta>
</con:Consultar>
</soapenv:Body>
</soapenv:Envelope>';


my $request = HTTP::Request->new(POST => 'http://ws.iid.sd.eedt.cl/MovimientosCliente?wsdl');
$request->header(SOAPAction => '"http://ws.iid.sd.eedt.cl/"');
$request->content($message);
$request->content_type("text/xml; charset=iso-8859-1");
$response = $userAgent->request($request);
$response->as_string;
my $respuesta_decodificada = $response->decoded_content;



my @NOMBRE = $respuesta_decodificada =~ m{<NOMBRE>(.*?)</NOMBRE>}gsm;
my @MONTO = $respuesta_decodificada =~ m{<MONTO>(.*?)</MONTO>}gsm;
my @PAIS = $respuesta_decodificada =~ m{<PAIS >(.*?)</PAIS>}gsm;

$NReg=$#DESPACHO;

for($i=0 ; $i<=$NReg ; $i++)
{

my $NOMBRE = @NOMBRE[$i];
my $MONTO = @MONTO[$i];
my $PAIS = @PAIS[$i];
}


Desde ya, muchas gracias.
coltx
Perlero nuevo
Perlero nuevo
 
Mensajes: 79
Registrado: 2011-09-16 08:01 @376

Re: Convertir una respuesta SOAP a XML

Notapor explorer » 2016-12-11 08:29 @395

Antes de nada, te pido por favor que edites tus mensajes para poner marcas al código Perl, al XML y a las salidas. Es muy difícil leer tus mensajes si todo va en texto plano.

Si usamos XML::Simple con el XML que nos indicas, sale una estructura muy sencilla:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use v5.14;
  3. use XML::Simple;
  4.  
  5. my $xml_ref = XMLin('kk.xml', KeepRoot => 1);
  6.  
  7. use Data::Dumper;
  8. say Dumper $xml_ref;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
La salida es:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
$VAR1 = {
          'S:Envelope' => {
                          'xmlns:S' => 'http://schemas.xmlsoap.org/soap/envelope/',
                          'S:Body' => {
                                      'ns4:SinteIED' => {
                                                        'xmlns:ns3' => 'http://ws.iid.sd.eedt.cl/SinteIED/Consultar',
                                                        'xmlns:ns2' => 'http://ws.iid.sd.eedt.cl/SinteIED/MovimientosCliente',
                                                        'MovimientosCliente' => {
                                                                                'Movimiento' => {
                                                                                                'DETALLE' => {
                                                                                                             'LINEA' => '1',
                                                                                                             'PROD' => 'SHAMPOO'
                                                                                                           },
                                                                                                'PAIS_CODIGO' => '522',
                                                                                                'MONTO' => '150',
                                                                                                'GUIAS' => {
                                                                                                           'LUGAR' => 'CLAVE',
                                                                                                           'FECHA' => '2016-12-02',
                                                                                                           'NRO' => '3344'
                                                                                                         },
                                                                                                'NOMBRE' => 'ALTIMAS'
                                                                                              }
                                                                              },
                                                        'xmlns:ns4' => 'http://ws.iid.sd.eedt.cl/SinteIED'
                                                      }
                                    }
                        }
        };
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

así que es muy fácil acceder a lo que quieres. Solo hay que hacer el camino de desreferencia de la estructura que estamos recorriendo:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. say $xml_ref->{'S:Envelope'}->{'S:Body'}->{'ns4:SinteIED'}->{'MovimientosCliente'}->{'Movimiento'}->{'GUIAS'}->{'FECHA'};       # 2016-12-02
  2. say $xml_ref->{'S:Envelope'}->{'S:Body'}->{'ns4:SinteIED'}->{'MovimientosCliente'}->{'Movimiento'}->{'DETALLE'}->{'PROD'};      # SHAMPOO
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

Naturalmente, es un fastidio tener que escribir todo eso. Incluso haciéndolo con la forma abreviada:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. say $xml_ref->{'S:Envelope'}{'S:Body'}{'ns4:SinteIED'}{'MovimientosCliente'}{'Movimiento'}{'GUIAS'}{'FECHA'};   # 2016-12-02
  2. say $xml_ref->{'S:Envelope'}{'S:Body'}{'ns4:SinteIED'}{'MovimientosCliente'}{'Movimiento'}{'DETALLE'}{'PROD'};  # SHAMPOO
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Una forma de abreviarlo es teniendo una referencia a la estructura de datos que realmente nos interesa:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my $movimiento_ref = $xml_ref->{'S:Envelope'}->{'S:Body'}->{'ns4:SinteIED'}->{'MovimientosCliente'}->{'Movimiento'};
  2.  
  3. say $movimiento_ref->{'GUIAS'}->{'NRO'};        # 3344
  4. say $movimiento_ref->{'NOMBRE'};                # ALTIMAS
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Pero todo esto funciona solamente si la estructura del XML es exactamente como lo has indicado. Si, por ejemplo, hubiera más registros de Movimientos, vendría en forma de array:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
'MovimientosCliente' => {
                        'Movimiento' => [
                                        {
                                          'GUIAS' => {
                                                     'FECHA' => '2016-1
                                                     'LUGAR' => 'CLAVE'
                                                     'NRO' => '3344'
                                                   },
                                          'MONTO' => '150',
                                          'PAIS_CODIGO' => '522',
                                          'DETALLE' => {
                                                       'PROD' => 'SHAMP
                                                       'LINEA' => '1'
                                                     },
                                          'NOMBRE' => 'ALTIMAS1'
                                        },
                                        {
                                          'GUIAS' => {
                                                     'FECHA' => '2016-1
                                                     'NRO' => '3344',
                                                     'LUGAR' => 'CLAVE'
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Así que no nos vale el programa tal y como lo tenemos porque no contemplamos la posibilidad de que hubiera un array.

Tenemos, entonces, que decirle a XML::Simple qué estructuras queremos que se presenten siempre en forma de array:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my $xml_ref = XMLin('kk.xml', KeepRoot => 1, ForceArray => ['Movimiento']);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Y ahora ya sí podemos acceder a ese array, sin importar que el XML original tuviese uno o más elementos:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my $movimientos_ref = $xml_ref->{'S:Envelope'}{'S:Body'}{'ns4:SinteIED'}{'MovimientosCliente'}{'Movimiento'};
  2.  
  3. for my $mov_ref (@$movimientos_ref) {
  4.     say $mov_ref->{'DETALLE'}{'PROD'};  # SHAMPOO,...
  5.     say $mov_ref->{'GUIAS'}->{'NRO'};   # 3344,...
  6.     say $mov_ref->{'NOMBRE'};           # ALTIMAS1, ALTIMA2...
  7. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
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: Convertir una respuesta SOAP a XML

Notapor coltx » 2016-12-11 12:01 @542

Gracias, explorer, pero cuando ejecuto lo que me indicas para llegar al nodo DETALLE,

say $mov_ref->{'DETALLE'}{'PROD'};

Recibo como respuesta: "Not a HASH reference at CAPTURA.pl line 45".
coltx
Perlero nuevo
Perlero nuevo
 
Mensajes: 79
Registrado: 2011-09-16 08:01 @376

Re: Convertir una respuesta SOAP a XML

Notapor coltx » 2016-12-11 12:27 @560

explorer: olvída mi pregunta anterior. He podido acceder realizando lo siguiente:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. for my $mov_ref (@$movimientos_ref) {
  2.         for my $DET ( @{$mov_ref->{DETALLE}} ) {
  3.                 print "$DET->{'PROD'}\n";
  4.         }
  5. }
  6.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Muchas gracias por tu ayuda.
coltx
Perlero nuevo
Perlero nuevo
 
Mensajes: 79
Registrado: 2011-09-16 08:01 @376

Re: Convertir una respuesta SOAP a XML

Notapor explorer » 2016-12-11 12:36 @566

Eso indica que la entrada DETALLE también es un array, en algunos casos. Mejor si lo añades a XMLin() para que lo sea siempre.
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


Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: Bing [Bot] y 7 invitados