想要从 Oracle table 获取一个 XML 节点

Want fetch a XML node from Oracle table

在 oracle table 中有一列存储 XML 下面是值:

    <Header xmlns="http://load.xyx.gen/gen1"/>
    <Body xmlns="http://load.xyx.gen/" xmlns:soapenv="http://load.xyx.gen/" xmlns:xsi="http://load.xyx.gen/instance" xmlns:SOAP-ENV="http://load.xyx.gen/" xmlns:SOAP-ENC="http://load.xyx.gen/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <ns2:handleEmploye xmlns:ns2="http://load.xyx.gen/emp1">
            <ns2:reisterEmp>
                <ns4:empName xmlns:ns4="http://load.xyx.gen/empName1">Mirac</ns4:empName>
                <ns4:empId xmlns:ns4="http://load.xyx.gen/empId1">12</ns4:empId>
                <ns4:empDep xmlns:ns4="http://load.xyx.gen/empDep1">Finance</ns4:empDep>
            </ns2:reisterEmp>
        </ns2:handleEmploye>
    </Body>
</soapenv:Envelope>

现在我正在尝试获取 empId 但出现以下错误:

ORA-31011: XML parsing failed ORA-19202: Error occurred in XML processing

我用了参考。来自这个 但它对我不起作用。

SELECT XMLTYPE('<soapenv:Envelope xmlns:soapenv="http://load.xyx.gen/">
    <Header xmlns="http://load.xyx.gen/gen1"/>
    <Body xmlns="http://load.xyx.gen/" xmlns:soapenv="http://load.xyx.gen/" xmlns:xsi="http://load.xyx.gen/instance" xmlns:SOAP-ENV="http://load.xyx.gen/" xmlns:SOAP-ENC="http://load.xyx.gen/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <ns2:handleEmploye xmlns:ns2="http://load.xyx.gen/emp1">
            <ns2:reisterEmp>
                <ns4:empName xmlns:ns4="http://load.xyx.gen/empName1">Mirac</ns4:empName>
                <ns4:empId xmlns:ns4="http://load.xyx.gen/empId1">12</ns4:empId>
                <ns4:empDep xmlns:ns4="http://load.xyx.gen/empDep1">Finance</ns4:empDep>
            </ns2:reisterEmp>
        </ns2:handleEmploye>
    </Body>
</soapenv:Envelope>
').EXTRACT('//Body/ns2:handleEmploye/ns2:reisterEmp/ns4:empId/text()').getStringVal() result
FROM dual;

谁能推荐一下?

您提到了 ORA-31011 和 ORA-19202,但根据您所展示的内容,它们将由 LPX-00601 引起:

ORA-31011: XML parsing failed
ORA-19202: Error occurred in XML processing
LPX-00601: Invalid token in: '//Body/ns2:handleEmploye/ns2:reisterEmp/ns4:empId/text()'

这是因为您的 XML 和 XPath 具有命名空间引用(在您修改后的 XML 中看起来有点混乱),但您没有在 [=14= 中包含命名空间映射] 通话:

SELECT XMLTYPE('...
').EXTRACT('//Body/ns2:handleEmploye/ns2:reisterEmp/ns4:empId/text()',
  'xmlns="http://load.xyx.gen/" xmlns:ns2="http://load.xyx.gen/emp1" xmlns:ns4="http://load.xyx.gen/empId1"'
  ).getStringVal() result
FROM dual;
RESULT
12

您可以改用 XMLQuery,并在 XPath 中提供命名空间:

SELECT XMLQuery(
 'declare namespace ns2="http://load.xyx.gen/emp1";
  declare namespace ns4="http://load.xyx.gen/empId1";
  declare default element namespace "http://load.xyx.gen/";
  //Body/ns2:handleEmploye/ns2:reisterEmp/ns4:empId/text()'
  PASSING XMLTYPE('...')
  RETURNING CONTENT) AS result
FROM dual;
RESULT
12

然后根据需要将结果转换为数字。

或者,如果您确实打算获取所有值,您可以使用 XMLTable,并使用 XMLNamespaces 提供名称空间;但是因为你为每个节点定义了不同的 'ns4' (无论如何在这个例子中)你需要为它们提供唯一的查询名称:

SELECT empId, empName, empDep
FROM XMLTable(
  XMLNamespaces(default 'http://load.xyx.gen/',
    'http://load.xyx.gen/emp1' as "ns2",
    'http://load.xyx.gen/empName1' as "ns4name",
    'http://load.xyx.gen/empId1' as "ns4id",
    'http://load.xyx.gen/empDep1' as "ns4dep"),
  '//Body/ns2:handleEmploye/ns2:reisterEmp'
  PASSING XMLTYPE('...')
  COLUMNS
    empId number PATH '//ns4id:empId',
    empName varchar2(30) PATH '//ns4name:empName',
    empDep varchar2(30) PATH '//ns4dep:empDep'
);
EMPID EMPNAME EMPDEP
12 Mirac Finance

或者您可以将它们全部通配:

SELECT empId, empName, empDep
FROM XMLTable(
  XMLNamespaces(default 'http://load.xyx.gen/',
    'http://load.xyx.gen/emp1' as "ns2",
    'http://load.xyx.gen/empId1' as "ns4"),
  '//Body/ns2:handleEmploye/ns2:reisterEmp'
  PASSING XMLTYPE('...')
  COLUMNS
    empId number PATH '//*:empId',
    empName varchar2(30) PATH '//*:empName',
    empDep varchar2(30) PATH '//*:empDep'
);
EMPID EMPNAME EMPDEP
12 Mirac Finance

db<>fiddle