Oracle 11g xml - 返回子节点不存在的行

时间:2017-03-24 12:50:15

标签: xml xpath oracle11g

我有一张包含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

我希望只返回没有子节点<tmp2>的节点(即第1行)。这可以通过查询实现吗?也许通过使用成员函数existnode?

谢谢!

2 个答案:

答案 0 :(得分:1)

您可以通过XMLTable调用同时获取您感兴趣的节点值和子节点(如果存在),然后过滤那些没有孩子的行:

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

我已将filter列的数据类型保留为XMLType,但如果您知道该类型,则可以从节点获取实际值。这也会捕获空的子节点。

或者您可以直接在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

答案 1 :(得分:0)

如果我理解你的问题。您只想返回叶节点。

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()' ,
 )
;