Работа с 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)

Комментарии и вопросы приветствуются.

0 комментариев

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.