Работа с XML в Oracle PL/SQL (Часть 1)
В этой публикации я приведу основные способы работы с XML в Oracle, которые сам использую.
Здесь будут рассмотрены на примерах такие операторы и функции как: XMLType, XMLElement, xmlattributes, XMLAGG, XMLSequence, insertchildxml, xmlconcat.
Итак начнем с объявления переменной в которой будем хранить текст XML.
Делается это так:
declare
--Задаем переменную
my_var XMLType;
begin
--Присваиваем значение нашей переменной
my_var:= XMLType('<root><item>Просто пробуем XML в Oracle</item></root>');
--Выводим в вывод
dbms_output.put_line(my_var.GetClobVal());
end;
Для начала рассмотрим некоторые приёмы работы с XML, чуть позже перейдем к генерации XML из данных при выборке.
1. Функция INSERTCHILDXML — Добавляет дочерний элемент в XML.
Пример:
declare
--Задаем переменную
my_var XMLType;
my_var_child XMLType;
begin
--Присваиваем значение нашей переменной
my_var:= XMLType('<root><item></item></root>');
--Добавим в элемент "item" содержимое
select insertchildxml(my_var, '/root/item', 'id', XMLType('<id>1</id>')) into my_var from dual;
select insertchildxml(my_var, '/root/item', 'name', XMLType('<name>Роман</name>')) into my_var from dual;
--А тепреь добавим ещё один элемент "item"
my_var_child:= XMLType('<item/>');
select insertchildxml(my_var_child, '/item', 'id', XMLType('<id>2</id>')) into my_var_child from dual;
select insertchildxml(my_var_child, '/item', 'name', XMLType('<name>Пётр</name>')) into my_var_child from dual;
select insertchildxml(my_var, '/root', 'item', my_var_child) into my_var from dual;
--Выводим в вывод
dbms_output.put_line(my_var.GetClobVal());
end;
В результате выполнения кода, мы получим XML Вида:
<root>
<item><id>1</id><name>Роман</name></item>
<item><id>2</id><name>Пётр</name></item>
</root>
2. Функция XMLCONCAT — Объединят две части XML в одну.
Пример:
declare
--Задаем переменную
my_var XMLType;
my_var_child XMLType;
begin
--Присваиваем значение нашей переменной
my_var:= XMLType('<root><item></item></root>');
--Добавим в элемент "item" содержимое
select insertchildxml(my_var, '/root/item', 'id', XMLType('<id>1</id>')) into my_var from dual;
select insertchildxml(my_var, '/root/item', 'name', XMLType('<name>Роман</name>')) into my_var from dual;
--А тепреь добавим ещё один элемент "item"
my_var_child:= XMLType('<item/>');
select insertchildxml(my_var_child, '/item', 'id', XMLType('<id>2</id>')) into my_var_child from dual;
select insertchildxml(my_var_child, '/item', 'name', XMLType('<name>Пётр</name>')) into my_var_child from dual;
--Объединим элемент my_var_child с самим собой
select xmlconcat( my_var_child, my_var_child) into my_var_child from dual;
select insertchildxml(my_var, '/root', 'item', my_var_child) into my_var from dual;
--Выводим в вывод
dbms_output.put_line(my_var.GetClobVal());
end;
Выполнив код мы увидим такой результат:
<root><item><id>1</id><name>Роман</name></item><item><id>2</id><name>Пётр</name></item><item><id>2</id><name>Пётр</name></item></root>
Как видим, объединив последний элемент с самим собой мы получили в исходной XML два одинаковых элемента.
!!! Наблюдение из правктики.
!!! Элементы INSERTCHILDXML и XMLCONCAT — очень медленные, поэтому работать с ними надо крайне осторожно и по возможности избегать.
Теперь посмотрим методы для извлечения информации из XML.
Для получения данных из XML нам понадобится оператор XMLSequence
3. Выбор множества XML элементов
(select extract(value(t),'root') result
from table(XMLSequence(my_xml_var.extract('root/item'))) t)
Пример:
declare
--Задаем переменную
my_var XMLType;
my_var_child XMLType;
begin
--Присваиваем значение нашей переменной
my_var:= XMLType('<root><item></item></root>');
--Добавим в элемент "item" содержимое
select insertchildxml(my_var, '/root/item', 'id', XMLType('<id>1</id>')) into my_var from dual;
select insertchildxml(my_var, '/root/item', 'name', XMLType('<name>Роман</name>')) into my_var from dual;
--А тепреь добавим ещё один элемент "item"
my_var_child:= XMLType('<item/>');
select insertchildxml(my_var_child, '/item', 'id', XMLType('<id>2</id>')) into my_var_child from dual;
select insertchildxml(my_var_child, '/item', 'name', XMLType('<name>Пётр</name>')) into my_var_child from dual;
--Объединим элемент my_var_child с самим собой
select xmlconcat( my_var_child, my_var_child) into my_var_child from dual;
select insertchildxml(my_var, '/root', 'item', my_var_child) into my_var from dual;
for rec in
(select extract(value(t),'item') as res
from table(XMLSequence(my_var.extract('root/item'))) t)
loop
--Выводим в вывод построчно элементы
dbms_output.put_line(rec.res.GetClobVal());
end loop;
end;
Результат:
<item><id>1</id><name>Роман</name></item>
<item><id>2</id><name>Пётр</name></item>
<item><id>2</id><name>Пётр</name></item>
4. Выбираем значение атрибута
select extractValue(value(t1),'item/@type') into v_res
from table(XMLSequence(my_xml_var.extract('item'))) t1;
Пример (добавим атрибут в элементы item):
declare
--Задаем переменную
my_var XMLType;
my_var_child XMLType;
begin
--Присваиваем значение нашей переменной
my_var:= XMLType('<root><item type="1"></item></root>');
--Добавим в элемент "item" содержимое
select insertchildxml(my_var, '/root/item', 'id', XMLType('<id>1</id>')) into my_var from dual;
select insertchildxml(my_var, '/root/item', 'name', XMLType('<name>Роман</name>')) into my_var from dual;
--А тепреь добавим ещё один элемент "item"
my_var_child:= XMLType('<item type="2"/>');
select insertchildxml(my_var_child, '/item', 'id', XMLType('<id>2</id>')) into my_var_child from dual;
select insertchildxml(my_var_child, '/item', 'name', XMLType('<name>Пётр</name>')) into my_var_child from dual;
--Объединим элемент my_var_child с самим собой
select xmlconcat( my_var_child, my_var_child) into my_var_child from dual;
select insertchildxml(my_var, '/root', 'item', my_var_child) into my_var from dual;
for rec in
(select extract(value(t),'item/@type') as res
from table(XMLSequence(my_var.extract('root/item'))) t)
loop
--Выводим в вывод построчно элементы
dbms_output.put_line(rec.res.GetClobVal());
end loop;
end;
Результат:
1
2
2
5. Выбираем содержимое элемента
select extractValue(value(t),'root/item') into v_res
from table(XMLSequence(my_xml_var.extract('item'))) t;
Пример:
declare
--Задаем переменную
my_var XMLType;
my_var_child XMLType;
v_res varchar2(100);
begin
--Присваиваем значение нашей переменной
my_var:= XMLType('<root><item type="1"></item></root>');
--Добавим в элемент "item" содержимое
select insertchildxml(my_var, '/root/item', 'id', XMLType('<id>1</id>')) into my_var from dual;
select insertchildxml(my_var, '/root/item', 'name', XMLType('<name>Роман</name>')) into my_var from dual;
--А тепреь добавим ещё один элемент "item"
my_var_child:= XMLType('<item type="2"/>');
select insertchildxml(my_var_child, '/item', 'id', XMLType('<id>2</id>')) into my_var_child from dual;
select insertchildxml(my_var_child, '/item', 'name', XMLType('<name>Пётр</name>')) into my_var_child from dual;
--Объединим элемент my_var_child с самим собой
select xmlconcat( my_var_child, my_var_child) into my_var_child from dual;
select insertchildxml(my_var, '/root', 'item', my_var_child) into my_var from dual;
for rec in
(select extract(value(t),'item/name') as res
from table(XMLSequence(my_var.extract('root/item'))) t)
loop
--Получаем содержимое элемента name
select extractValue(value(t1),'name') into v_res
from table(XMLSequence(rec.res.extract('name'))) t1;
--Выводим в вывод построчно содержимое элемента
dbms_output.put_line(v_res);
end loop;
end;
Результат:
Роман
Пётр
Пётр
Продолжение: Oracle и выборки в виде XML (XMLELEMENT, XMLATTRIBUTE, XMLAGG)
Комментарии и вопросы приветствуются.