Работа с SOAP XML в Oracle Печать E-mail
Рейтинг: / 14
ХудшаяЛучшая 

Работа с внешним приложением по SOAP протоколу в ORACLE .Работа с XML в Oracle.

В создании данного материала неоценимую помощь мне оказал мой коллега
Доброквашин Михаил.

В этом материале будут разобраны следующие моменты:
Работа с XML в Oracle (формирование XML, хранение XML в базе, извлечение и парсинг XML документа)
Придача XML документа по HTTP протоколу, ожидание ответа, авторизация на HTTP сервере, получение ответа.
Работа с данными тип LOB.

Для примеров может быть использован сервер Oracle не ниже 9 ой версии, с поддержкой XML TYPE.

Введение

Многочисленные приложения сейчас используют в качестве обмена информацией формат XML. Протокол SOAP так же используется многими web сервисами и приложениями , такими как ozon , google, yandex. В протоколе soap XML документ передается по http get другому приложению или web службе, которая в свою очередь возвращает ответ так же в XML формате.

Рассмотрим ситуацию, когда нам необходимо с помощью средств oracle разработать приложения для взаимодействия с внешним Веб-сервисом с использованием SOAP протоколу.

 

Общая схема работы приложения

Итак, наша система работает по следующему алгоритму:
o Приложение СУБД Oracle формирует XML документ заданного формата
o Приложение СУБД Oracle внешнему веб-сервису сформированный XML
o Ожидает ответа со стороны веб - сервиса и
o Трансформирует ответ из XML в курсор Oracle и передает его далее во внешнее приложение

Формирование XML

Рассмотрим различные методы для формирования XML в Oracle

Преобразование данных из строки в формат XML
Для создания XML создается соответствующий XML в формате VARCHAR2
Затем переменная VARCHAR2 преобразуется в CLOB , далее происходит непосредственно преобразование в XML.
Подобное преобразование необходимо для того что тип varchar2 ограничивается 32 килобайтами, а предаваемые xml могут большего объема.
Итак, при работе с XML oracle в процессе преобразований целесообразно использовать тип CLOB.

Стандартные методы работы с XML в Oracle


Сохраняем XML в базу данных
Сохранение XML происходит в поле CLOB

Function AddXML(tXML IN sys.xmltype, RETURN NUMBER

is

  tId NUMBER;

  PRAGMA AUTONOMOUS_TRANSACTION;

begin

begin

 

 SELECT LOG.nextval into tID from dual; 

  insert into

   logg

   (

   logid,

   xmldoc_in,

   logdate,

   )

  values

  ( 

   retId

  , tXMLDOC

  , sysdate

  );

 

  commit;

 

  return tId;

exception

  when others then raise_application_error(SQLCODE, 'Ошибка записи в Лог файл' );

end;  

end AddLogInf;

 

Создание XML

Создание XML в ORACLE удобнее всего преобразованием символьной переменной следующим образом:

xxml := '<Header><En xmlns:env="http://schemas.xmlsoap.org/soap/" en="http://orasource.code.ru/">  

</Header>   <Body>  <gets>         <id>'|| IDN  || '</id>'

||'<xml_start>' || T_START ||'</xml_start>'

||'<xml_stop>' || T_STOP || '</xml_stop>'

||' </gets>' ||'</Body> </En>';

 

Формируем XML  из типа varchar32 выполняем преобразование в axml sysxml.type

axml := xmltype.createxml(xXml);

 

итак , мы получаем готовый xml

<Header>

<En xmlns:env="http://schemas.xmlsoap.org/soap/" en="http://orasource.code.ru/">  

<Header/>  

<Body> 

  <gets>  

     <id>1</id>

     <xml_start>start</xml_start>

     <xml_stop>stop</xml_stop>

 </gets>

</Body>

</En>;

 

 

Расшифровка XML ответа

После того как внешнее приложение или веб сервис вернул нам ответ нам необходимо преобразовать его к курсору или единичному значению.

Посмотрим, как это сделать:

Для преобразования XML используется тип XMLSEQUENCE и команда EXTRACT

Единичное значение

<?xml version="1.0" encoding="UTF-8"?>

<Env xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">

<Body><getxml xmlns http://www.orasource.ru/">

   <result>

     1

   </result>

   </getxml >

   </Body>

</Env>

 

 FOR cr_result IN

    (

     select -- Value(p)

     extract(Value(p), '/result/text()').getStringVal()  returnvalue

     from

     Table(XMLSEQUENCE(EXTRACT(xRetXml,'//result '))) p

    )

    LOOP    

      xRet := to_number(cr_result.returnvalue);

    END LOOP;

Курсор

Исходный XML

<?xml version="1.0" encoding="UTF-8"?>

<Env xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">

<Body><getxml xmlns http://www.orasource.ru/">

   <return>

     <id>1</id>

     <id1>1</id1>

     <id2>1</id2>

  </return>

  <return>

     <id>2</id>

     <id1>2</id1>

     <id2>2</id2>

   </return>

   <return>

     <id>3</id>

     <id1>3</id1>

     <id2>3</id2>

   </return>

   </ getxml >

   </Body></Env>

 

open tmp_ref_cursor for

     select

        extract(Value(p), 'return/id /text()').getStringVal()                                id

     ,  cast(extract(Value(p), 'return/id_1 /text()').getStringVal() as NUMBER)           id_1

     ,  cast(extract(Value(p), 'return/id_2/text()').getStringVal() as NUMBER)               id_2      

     ,  cast(REPLACE(extract(Value(p), 'return/id/text()').getStringVal(),'.',',') as NUMBER)  balance

     ,  cast(extract(Value(p), 'return/id_3/text()').getStringVal() as NUMBER)               id_3

       From

Table(XMLSEQUENCE(EXTRACT(xXmlReturn,'//return'))) p;

    --Table(XMLSEQUENCE(EXTRACT(xRetXml,'/S_Envelope/S_Body/ns2_getBalancesListResponse/*'))) p;

    Table(XMLSEQUENCE(EXTRACT(xRetXml,'//return'))) p;

Обработка курсора внешним приложением

 

 

 

Передача данных внешнему приложению

Url - адрес вызова

aXML - сформированный XML документ

Передача данных внешнему приложению осуществляется следующим образом

 

-- создаем временный LOB

  DBMS_LOB.createtemporary(XML, FALSE);

-- устанавливем кодировку http пакета

  utl_http.set_body_charset('UTF-8');

  HTTP_REQ := utl_http.begin_request(aURL, 'POST', 'HTTP/1.1');

  utl_http.set_header(HTTP_REQ, 'Content-Type', 'text/xml');

-- задаем дляну http пакета

-- следует обратить внимание, что длину пакета следует устанавливать с учетом кодировки

-- для utf8 устанавливается одна длина пакета , для другой кодировки будет другая

  utl_http.set_header(HTTP_REQ, 'Content-Length', LENGTHB(UNISTR(aENV))); --длина в ЮНИКОДЕ

-- проходми авторизацию на веб серевере

-- auser apassword пароль и имя пользователя на сервере

  utl_http.set_authentication(HTTP_REQ, v_USER, v_PASSWORD);

    loop

        buf := SUBSTR(aENV,i, 200);

        if buf is not null then

           utl_http.write_text(HTTP_REQ, buf);

           i:=i + 200;

        else

          exit;  

        end if;

    end loop;

-- отравляем пакет на веб сервер по частям, в 2000 байт

 

Итак, мы создаем временную переменную типа LOB в которую в дальнейшем будем принимать данные из внешнего приложения

Задаем кодировку и длину HTTP пакета

Прием данных из внешнего приложения или веб службы.

Прием данных из внешнего приложения или веб службы осуществляется следующим образом: 

HTTP_RESP := utl_http.get_response(HTTP_REQ); 

begin

   loop

     -- последовательно считываем текст XML документа

     -- в переменную env типа clob

     utl_http.read_text(HTTP_RESP, l_text, 32767);

     DBMS_LOB.writeappend (ENV, LENGTH(l_text), l_text); 

   end loop;                                        

  EXCEPTION

      WHEN THEN

-- здесь произвольная обработка исключений

  end;

 

  utl_http.end_response(HTTP_RESP); 

  --dbms_output.put_line(SUBSTR(ENV,1,250));   

  RESP:=ENV;

 

Итак, мы видим, что организуется цикл, который последовательно считывает данные Http ответа в переменную типа CLOB.

 
« Пред.   След. »