在 PLSQL 中使用命名空间解析嵌套 XML

Parsing Nested XML with Namespaces in PLSQL

我有一个 xml 如下所示

<ibm:dept bldg="123" xmlns:ibm="http://www.ibm.com/xmltable">
  <ibm:employee id="144">
    <ibm:name>
      <ibm:first>James</ibm:first>
      <ibm:last>Bond</ibm:last>
    </ibm:name>
    <ibm:office>007</ibm:office>
    <ibm:phone>905-007-1007</ibm:phone>
    <ibm:salary currency="USD">77007</ibm:salary>
  </ibm:employee>
</ibm:dept>'

我正在尝试使用 XMLTable 函数对其进行解析。这是我试过的-

select x.*,
       y.*
 from xml_tab t,
 XMLTable(XMLnamespaces('http://www.ibm.com/xmltable' as "ibm"),
 'ibm:dept/ibm:employee' 
 passing t.xml_data
 columns 
        empid NUMBER path '@id',
        office VARCHAR2(5) path 'ibm:office',
        name XMLTYPE path 'ibm:name' 
 ) x,
 XMLTable(
 'ibm:name'
 passing x.name 
     columns 
            firstname VARCHAR2(10) path 'ibm:first',
            lastname VARCHAR2(10) path 'ibm:last') y
 where t.id =3;

但是出现以下错误

ORA-19228: XPST0008 - undeclared identifier: prefix 'ibm' local-name 'ibm:name'

希望有人能解释错误。干杯!

数据设置

create table xml_tab
(
 id NUMBER,
 xml_data XMLType
 );



insert into xml_tab
values(3, XMLType.createXML('<ibm:dept bldg="123" xmlns:ibm="http://www.ibm.com/xmltable">
  <ibm:employee id="144">
    <ibm:name>
      <ibm:first>James</ibm:first>
      <ibm:last>Bond</ibm:last>
    </ibm:name>
    <ibm:office>007</ibm:office>
    <ibm:phone>905-007-1007</ibm:phone>
    <ibm:salary currency="USD">77007</ibm:salary>
  </ibm:employee>
</ibm:dept>'));

如果要在 COLUMNS 子句的 PATH 表达式中使用限定名称,则需要指定 XMLNAMESPACES 子句 ( Doc. )。

所以你需要单独定义 XMLnamespaces 即使是第二个 XMLTable

(别名可能会更改,例如第二个 table 的 ibm2 通过将所有 ibm: 替换为 ibm2:

select x.*, y.*
  from xml_tab t,
       XMLTable(XMLnamespaces('http://www.ibm.com/xmltable' as "ibm"),
                'ibm:dept/ibm:employee' passing t.xml_data columns empid
                NUMBER path '@id',
                office VARCHAR2(5) path 'ibm:office',
                name XMLTYPE path 'ibm:name') x,
       XMLTable(XMLnamespaces('http://www.ibm.com/xmltable' as "ibm"),
                'ibm:name' passing x.name columns firstname VARCHAR2(10) path
                'ibm:first',
                lastname VARCHAR2(10) path 'ibm:last') y                
 where t.id = 3;

Demo