Reputation: 399
I have a table holding an xmlstructure
create table xml_stg_test (rawdata xmltype);
insert into xml_stg_test (rawdata) values (xmltype.createxml('<root>
<tmp1>
<val1>123</val1>
</tmp1>
<tmp1>
<val1>234</val1>
<tmp2>
<val2>567</val2>
</tmp2>
</tmp1>
</root>'));
Select extractvalue(value(rec), '*/val1') test
from xml_stg_test sg, table(xmlsequence(extract(rawdata,'*/tmp1'))) rec;
**TEST**
1 123
2 234
I wish to only return the node which does not have child node <tmp2>
(i.e row 1). Is this possible to achieve via query? Perhaps by use of member function existnode?
Thanks!
Upvotes: 0
Views: 943
Reputation: 6366
If i understand your question correctly. You want to return only leaf node.
select * from xmltable('//*[not(*)]' passing xmltype('<root>
<tmp1>
<val1>123</val1>
</tmp1>
<tmp1>
<val1>234</val1>
<tmp2>
<val2>567</val2>
</tmp2>
</tmp1>
</root>' )
columns
leaf_name varchar2(100) path 'name()',
leaf_value varchar2(100) path 'text()' ,
)
;
Upvotes: 0
Reputation: 191560
You could get both the node value you're interested in, and the child node (if it exists) via an XMLTable call instead, and then filter those rows which don't have the child:
select xt.test
from xml_stg_test xsg
cross join xmltable (
'/root/tmp1'
passing xsg.rawdata
columns test number path 'val1',
filter xmltype path 'tmp2'
) xt
where xt.filter is null;
TEST
----------
123
I've left the data type of the filter
column as XMLType but you could get the actual value form the node if you know the type. This would catch empty child nodes too though.
Or you can filter directly in the XPath:
select xt.test
from xml_stg_test xsg
cross join xmltable (
'for $n in /root/tmp1 where not(exists($n/tmp2)) return $n'
passing xsg.rawdata
columns test number path 'val1',
filter xmltype path 'tmp2'
) xt;
TEST
----------
123
Upvotes: 1