ADD (PRIMARY KEY (ID));
-- Создаем внешний ключ, связывающий таблицы SOURCE и STYLESHEET
ALTER TABLE SOURCE
ADD (FOREIGN KEY (STYLESHEETID) REFERENCES STYLESHEET);
После того, как схема базы данных была создана, в нее можно добавить записи, содержащие преобразования и обрабатываемые ими документы. Мы ограничимся простым преобразованием и еще более простым документом.
<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>
<A>value</A>
-- Сохраняем преобразование
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.
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;
Представление обработанных документов теперь может быть описано совершенно элементарно.
CREATE OR REPLACE VIEW PROCESSED_SOURCE AS
SELECT ID, PROCESS(ID) AS CONTENT
FROM SOURCE;
Продемонстрируем работу функции PROCESS и представления PROCESS_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-тегами информацию о текущем сеансе.