Выбрать главу

 ADD (PRIMARY KEY (ID));

-- Создаем внешний ключ, связывающий таблицы SOURCE и STYLESHEET

ALTER TABLE SOURCE

 ADD (FOREIGN KEY (STYLESHEETID) REFERENCES STYLESHEET);

После того, как схема базы данных была создана, в нее можно добавить записи, содержащие преобразования и обрабатываемые ими документы. Мы ограничимся простым преобразованием и еще более простым документом.

Листинг 9.16. Преобразование

<xsclass="underline" stylesheet

 version="1.0"

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <xsclass="underline" template match="A">

  <B><xsclass="underline" value-of select="."/></B>

 </xsclass="underline" template>

</xsclass="underline" stylesheet>

Листинг 9.17. Обрабатываемый документ

<A>value</A>

Листинг 9.18. SQL-скрипт, загружающий документ и преобразование в БД

-- Сохраняем преобразование

INSERT INTO STYLESHEET VALUES

(1, '<xsclass="underline" stylesheet                                     '||

    ', version="1.0"                                     '||

    '  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> '||

    '  <xsclass="underline" template match="A">                          '||

    '   <B><xsclass="underline" value-of select="."/></B>                '||

    '   </xsclass="underline" template>                                  '||

    '  </xsclass="underline" stylesheet>                                 ');

-- Сохраняем документ

INSERT INTO SOURCE VALUES

(1, '<A>value</A>', 1);

Для того чтобы выполнять преобразования в SELECT-выражении представления таблицы SOURCE, мы напишем функцию PROCESS, которая будет возвращать результат обработки документа с уникальным идентификатором, заданным параметром sourceID.

Листинг 9.19. Функция PROCESS

CREATE OR REPLACE FUNCTION PROCESS (sourceID NUMBER) RETURN VARCHAR2 IS

 -- Инициализация XML-парсера и XSLT-процессора

 parser XMLPARSER.Parser := XMLPARSER.newParser;

 processor XSLPROCESSOR.Processor := XSLPROCESSOR.newProcessor;

 -- Переменные для CLOB-значений входящего документа и преобразования

 sourceCLOB CLOB;

 stylesheetCLOB CLOB;

 -- Переменные для DOM-объектов входящего документа и преобразования

 sourceXML XMLDOM.DOMDocument;

 stylesheetXML XMLDOM.DOMDocument;

 -- Переменная для объекта преобразования

 stylesheet XSLPROCESSOR.Stylesheet;

 -- Переменная результата

 result varchar2(32767);

BEGIN

 -- Получаем CLOB-значение входящего документа в переменную sourceCLOB

 SELECT CONTENT

 INTO sourceCLOB

 FROM SOURCE

 WHERE ID = sourceID;

 -- Получаем CLOB-значение соответствующего преобразования

 SELECT STYLESHEET.CONTENT

 INTO stylesheetCLOB

 FROM STYLESHEET, SOURCE

 WHERE SOURCE.ID = sourceID AND SOURCE.STYLESHEETID = STYLESHEET.ID;

 -- Если хотя бы одно из значений - NULL, прерываем обработку

 -- и возвращаем NULL

 IF sourceCLOB IS NULL OR stylesheetCLOB IS NULL THEN

  RETURN NULL;

 END IF;

 -- Разбираем CLOB-значение входящего документа

 XMLPARSER.parseCLOB(parser, sourceCLOB);

 sourceXML := XMLPARSER.getDocument(parser);

 -- Разбираем CLOB-значение документа преобразования

 XMLPARSER.parseCLOB(parser, stylesheetCLOB);

 stylesheetXML := XMLPARSER.getDocument(parser);

 -- Инициализируем объект преобразования

 stylesheet := XSLPROCESSOR.newStylesheet(stylesheetXML, NULL);

 -- Выполняем преобразование

 XSLPROCESSOR.processXSL(processor, stylesheet, sourceXML, result);

 -- Освобождаем ресурсы

 XSLPROCESSOR.freeProcessor(processor);

 XMLPARSER.freeParser(parser);

 XMLDOM.freeDocument(sourceXML);

 XMLDOM.freeDocument(stylesheetXML);

 RETURN result;

 -- Обработка исключений

 EXCEPTION

  -- Если возникла исключительная ситуация

  WHEN OTHERS THEN

   -- Освобождаем ресурсы

   XSLPROCESSOR.freeProcessor(processor);

   XMLPARSER.freeParser(parser);

   XMLDOM.freeDocument(sourceXML);

   XMLDOM.freeDocument(stylesheetXML);

  -- Передаем исключение дальше

  RAISE;

END;

Представление обработанных документов теперь может быть описано совершенно элементарно.

Листинг 9.20. Представление PROCESSED_SOURCE

CREATE OR REPLACE VIEW PROCESSED_SOURCE AS

SELECT ID, PROCESS(ID) AS CONTENT

FROM SOURCE;

Продемонстрируем работу функции PROCESS и представления PROCESS_SOURCE на примере двух запросов.

Листинг 9.21. Запросы к таблице SOURCE и представлению PROCESSED_SOURCE

SQL> SELECT * FROM SOURCE;

ID  CONTENT       STYLESHEETID

--  ------------  ------------

1   <A>value</A>  1

SQL> SELECT * FROM PROCESSED_SOURCE;

ID CONTENT

-- -------------------------------------------------------

1  <?xml version = '1.0' encoding = 'UTF-8'?> <B>value</B>

Выполнение XSLT-преобразований в Java

Язык Java традиционно широко поддерживает XML-технологии: большинство передовых разработок в этой области реализуется, как правило, сначала на Java и уж затем переносится на другие платформы разработки.

Не стал исключением и XSLT. Можно смело сказать, что количество XSLT-средств, написанных на Java, превосходит половину вообще всех существующих в настоящее время XSLT-пакетов.

Для того чтобы продемонстрировать использование XSLT в Java, мы приведем два варианта одной и той же программы — серверного приложения (сервлета), которое по запросу клиента будет возвращать информацию о текущем HTTP-сеансе в формате HTML.

Первый вариант сервлета можно назвать "традиционным". В нем HTML-документ создается серией инструкций out.println(...), которые выводят в выходящий поток размеченную HTML-тегами информацию о текущем сеансе.