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;