Ejemplo de consulta desde Oracle a un webservice para obtener el cambio de divisas del EURO

El Banco Central Europeo dispone de un webservice en donde publica el cambio diario de divisas del Euro a otras divisas, para acceder a esa información se dispone de esta URL: http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml

En este ejemplo se busca obtener de forma muy simple mediante una SELECT la lista de divisas y su correspondiente cambio.


SELECT EXTRACTVALUE (value (tab), '/Cube/@currency',
                                  'xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref') currency,
       EXTRACTVALUE (value (tab), '/Cube/@rate',
                                  'xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref') rate
  FROM TABLE(XMLSEQUENCE(EXTRACT(
pk_xml.lee_xml_desde_url('http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml',  null, null),
'/gesmes:Envelope/Cube/Cube/Cube',
'xmlns:gesmes=http://www.gesmes.org/xml/2002-08-01  xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref"'
))) tab;

 

Autorizar dirección

Este punto es necesario en caso de tener Oracle 11 o superior.  Hay que autorizar la dirección www.ebc.europa.eu de la siguiente forma:

DECLARE
  acl_path  VARCHAR2 (4000);
  v_numero  NUMBER;
BEGIN
  SELECT acl
    INTO acl_path
    FROM dba_network_acls
   WHERE HOST = 'www.ecb.europa.eu'
     AND lower_port IS NULL
     AND upper_port IS NULL;

  IF dbms_network_acl_admin.check_privilege (acl_path, USER, 'connect') IS NULL THEN
    dbms_network_acl_admin.add_privilege (acl_path, USER, TRUE, 'connect');
  END IF;

  COMMIT;
EXCEPTION
  WHEN NO_DATA_FOUND THEN
    SELECT COUNT(*)
       INTO v_numero
      FROM dba_network_acls
    WHERE acl LIKE '%ACL_LIBRA.xml%';

    IF v_numero = 0 THEN
      dbms_network_acl_admin.create_acl ('ACL_LIBRA.xml', 'Permisos TCP usuario LIBRA', USER, TRUE, 'connect');
    END IF;

    dbms_network_acl_admin.assign_acl ('ACL_LIBRA.xml', 'www.ecb.europa.eu');
    COMMIT;
END;
/

En caso de no hacerlo nos dará el siguiente error:
ORA-29273: fallo de la solicitud HTTP
ORA-06512: en «SYS.UTL_HTTP», línea 1130
ORA-24247: acceso de red denegado por la lista de control de acceso (ACL)
ORA-06512: en «LIBRA.PK_XML», línea 148

 

Función PK_XML.LEE_XML_DESDE_URL

 

El paqute PK_XML forma parte del entorno de Libra, y su código es el siguiente:

FUNCTION lee_xml_desde_url(p_url VARCHAR2, p_usuario VARCHAR2, p_password VARCHAR2) RETURN XMLTYPE AS
 /* Descarga un xml de una dirección web que se pasa por parámetro "p_url".
    Si la dirección web requiere autentificación se debe de pasar el usuario y la constraseña en
    p_usuario y p_password */

  v_req         UTL_HTTP.req;
  resp          UTL_HTTP.resp;
  my_scheme     VARCHAR2(256);
  my_realm      VARCHAR2(256);
  my_proxy      BOOLEAN;
  name          VARCHAR2(4000);
  v_valor       VARCHAR2(32000);
  v_clob        CLOB;
  v_xml         XMLTYPE;
  v_resultado   VARCHAR2(30) := 'OK';
BEGIN
  v_req := UTL_HTTP.begin_request(p_url);
  UTL_HTTP.set_transfer_timeout(180);

  IF p_usuario IS NOT NULL THEN
    UTL_HTTP.set_authentication(v_req, p_usuario, p_password);
  END IF;

  resp := UTL_HTTP.get_response(v_req);

  IF (resp.status_code = UTL_HTTP.http_unauthorized) THEN
    UTL_HTTP.get_authentication(resp, my_scheme, my_realm, my_proxy);

    IF (my_proxy) THEN
      v_resultado := 'PROXY';
      DBMS_OUTPUT.put_line('Web proxy server is protected.');
      DBMS_OUTPUT.put('Please supplied the required ' || my_scheme || ' authentication username/password for realm ' || my_realm || ' for the proxy server.');
    ELSE
      v_resultado := 'VALIDACION';
      DBMS_OUTPUT.put_line('Web page ' || p_url || ' is protected.');
      DBMS_OUTPUT.put('Please supplied the required ' || my_scheme || ' authentication username/password for realm ' || my_realm || ' for the Web page.');
    END IF;

    UTL_HTTP.end_response(resp);
    v_resultado := 'ERROR';
  END IF;

  IF v_resultado = 'OK' THEN
    FOR i IN 1 .. UTL_HTTP.get_header_count(resp) LOOP
      UTL_HTTP.get_header(resp, i, name, v_valor);
      DBMS_OUTPUT.put_line(name || ': ' || v_valor);
    END LOOP;

    LOOP
      BEGIN
        UTL_HTTP.read_text(resp, v_valor, 30000);
        v_clob := v_clob || v_valor;
        DBMS_OUTPUT.put_line(v_valor);
      EXCEPTION
        WHEN OTHERS THEN
          EXIT;
      END;
    END LOOP;

    v_xml := xmltype.createxml(v_clob);
    UTL_HTTP.end_response(resp);
  END IF;

  RETURN (v_xml);
END;

 

Start typing and press Enter to search