Página 1 de 1

Convertir una respuesta SOAP a XML

NotaPublicado: 2016-12-08 19:18 @846
por coltx
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.004 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.

Re: Convertir una respuesta SOAP a XML

NotaPublicado: 2016-12-09 18:42 @821
por explorer
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.

Re: Convertir una respuesta SOAP a XML

NotaPublicado: 2016-12-10 12:26 @560
por coltx
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.

Re: Convertir una respuesta SOAP a XML

NotaPublicado: 2016-12-11 08:29 @395
por explorer
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.002 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

Re: Convertir una respuesta SOAP a XML

NotaPublicado: 2016-12-11 12:01 @542
por coltx
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".

Re: Convertir una respuesta SOAP a XML

NotaPublicado: 2016-12-11 12:27 @560
por coltx
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.

Re: Convertir una respuesta SOAP a XML

NotaPublicado: 2016-12-11 12:36 @566
por explorer
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.