根据属性值从 XML 中提取不同的值

Extract distinct values from XML based on attribute value

我需要从 XML 中提取到 doc_numx for kod = 'N',像这样:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<main doc_num=99>
<item name="A">
    <Dok Kod="N" X="1" Id="5"/>
    <Dok Kod="N" X="4" Id="5"/>
</item>
<item name="B">
    <Dok Kod="N" X="1" Id="2"/>
    <Dok Kod="N" X="4" Id="6"/>
    <Dok Kod="N" X="5" Id="8"/>
    <Dok Kod="Z" X="4553" Id="8"/>
</item>
</main>

输出应该是这样的,我只需要不同的:

doc_num     X
99          1
99          4
99          5 

您可以将 XMLTable 与以 Kod=N 节点为目标的 Xpath 一起使用,然后沿着树返回以获取 doc_num;此版本假定您的原始值为字符串:

select distinct xml.doc_num, xml.x
from your_table t
cross apply xmltable (
  '/main/item/Dok[@Kod="N"]'
  passing xmltype(t.your_xml)
  columns doc_num number path './../../@doc_num',
    x number path '@X'
) xml
DOC_NUM X
------- -
     99 1
     99 4
     99 5

db<>fiddle

如果您的原始值已经是 XMLType,那么返回树上将不会按预期工作 - 不确定这是否是错误,但至少在 11gR2 和 18c 中似乎会发生。您可以通过转换为字符串并返回来解决此问题:

select distinct xml.doc_num, xml.x
from your_table t
cross apply xmltable (
  '/main/item/Dok[@Kod="N"]'
  passing xmltype(t.your_xml.getclobval())
  columns doc_num number path './../../@doc_num',
    x number path '@X'
) xml
DOC_NUM X
------- -
     99 1
     99 4
     99 5

db<>fiddle


我刚刚注意到您为 Oracle 11g 标记了这个...因此交叉应用不可用,并且返回树上也不起作用;也不过滤子属性名称。因此,您可以使用两级 XMLTable 来执行此操作:

select distinct xml1.doc_num, xml2.x
from your_table t
cross join xmltable (
  '/main'
  passing xmltype(t.your_xml)
  columns doc_num number path '@doc_num',
    doks xmltype path 'item/Dok'
) xml1
cross join xmltable (
  '/Dok'
  passing xml1.doks
  columns kod varchar2(1) path '@Kod',
    x number path '@X'
) xml2
where xml2.kod = 'N'
DOC_NUM X
------- -
     99 1
     99 4
     99 5

适用于 11g with a string or with an XMLType 来源。