Основная особенность: высокоуровневые конструкции, которые возвращали бы последовательность элементов по XPath или XQuery можно использовать только SQL-запросе. Они не работають в "чистом" PL/SQL. Если стоит задача парсить XML, не используя select'ы вообще, то для извлечения скалярных значений можно пользоваться extract(xmltype('xml text'), 'some XPath'). Но чтобы получить однородный массив, придется использовать XMLDOM API, как во 2-м примере.
Следует учитывать, что xmlsequence объявлена как deprecated. Наиболее гибкий и мощный способ преборазования XML в массивы и таблицы - это XQuery через XmlTable.
1. Через преобразование результата XPath к xmlsequence в SQL-запросе:
select value(t).getClobVal(), (select extract(value(t),to_char('/*/@'||'connects')).getClobVal() from dual), (select extract(value(t),to_char('/*/text()')).getClobVal() from dual) from table(xmlsequence(extract(xmltype('<packet id="3073653"> <contract value="669752/NIC-D"/> <subd name="oracle" connects="100"/> <subd name="oracle" connects="100"/> <subd name="mysql" connects="10"/> <email value="box@nicmail.ru"/> <hcp-access value="on"/> <hdns> <on value="vasia.ru"/> <on value="masha.ru"/> <off value="gazdarmaku.net"/> <not-hosting-dns value="hdns.net"/> </hdns> </packet> '),'/packet/subd[attribute::name="oracle" and attribute::connects>1 and attribute::connects<101]')))
2. С помощью XMLDOM API:
declare xml XMLType := XMLType('<packet id="3073653"> <contract value="669752/NIC-D"/> <subd name="oracle" connects="100"/> <subd name="oracle" connects="100"/> <subd name="mysql" connects="10"/> <email value="box@nicmail.ru"/> <hcp-access value="on"/> <hdns> <on value="vasia.ru"/> <on value="masha.ru"/> <off value="gazdarmaku.net"/> <not-hosting-dns value="hdns.net"/> </hdns> </packet>'); x dbms_xmldom.DOMNodeList; node dbms_xmldom.DOMNode; value varchar2(32000); i pls_integer; begin x := dbms_xmldom.getChildNodes(dbms_xmldom.getNodeFromFragment(xml.extract('//*[@connects]'))); dbms_output.put_line(dbms_xmldom.getLength(x) ); for i in 0..dbms_xmldom.getLength(x)-1 loop node := dbms_xmldom.item(x, i); dbms_output.put_line( dbms_xmldom.getNodeValue( dbms_xmldom.getNamedItem( dbms_xmldom.getAttributes(node) , 'connects' ) ) ); end loop; end;
3. С помощью XQuery в конструкции XmlTable:
declare l_t xmltype := xmltype('<packet id="3073653"> <contract value="669752/NIC-D"/> <subd name="oracle" connects="100"/> <subd name="oracle" connects="100"/> <subd name="mysql" connects="10"/> <email value="box@nicmail.ru"/> <hcp-access value="on"/> <hdns> <on value="vasia.ru"/> <on value="masha.ru"/> <off value="gazdarmaku.net"/> <not-hosting-dns value="hdns.net"/> </hdns> </packet>'); l_p xmltype; begin
for p in (SELECT cc v from XMLTable( 'for $i in /packet/subd[attribute::name="oracle" and attribute::connects>1 and attribute::connects<101] return $i' PASSING l_t COLUMNS cc number path '@connects') xtab) loop dbms_output.put_line(p.v * 2); end loop;
end;
|