从 Oracle SQL 中的变量访问 XML 中的值

Accessing values in XML from a variable in Oracle SQL

我在变量 p_val 中有如下 XML 数据:

<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:wsa="http://www.w3.org/2005/08/addressing">
    <env:Header>
        <wsa:MessageID>urn:bda29066-5961-11ec-87ec-0242c5d8b376</wsa:MessageID>
        <wsa:ReplyTo>
            <wsa:Address>http://www.w3.org/2005/08/addressing/anonymous</wsa:Address>
            <wsa:ReferenceParameters>
                <instra:tracking.ecid xmlns:instra="http://xmlns.oracle.com/sca/tracking/1.0">9b657011-42e4-4cf4-a78e-537551de4cc0-0057ca4a</instra:tracking.ecid>
                <instra:tracking.FlowEventId xmlns:instra="http://xmlns.oracle.com/sca/tracking/1.0">27818206</instra:tracking.FlowEventId>
                <instra:tracking.FlowId xmlns:instra="http://xmlns.oracle.com/sca/tracking/1.0">169007626</instra:tracking.FlowId>
                <instra:tracking.CorrelationFlowId xmlns:instra="http://xmlns.oracle.com/sca/tracking/1.0">0000NqYCMWFDGfdLxeG7yW1X_Nsm0003Yk</instra:tracking.CorrelationFlowId>
                <instra:tracking.quiescing.SCAEntityId xmlns:instra="http://xmlns.oracle.com/sca/tracking/1.0">1830036</instra:tracking.quiescing.SCAEntityId>
            </wsa:ReferenceParameters>
        </wsa:ReplyTo>
        <wsa:FaultTo>
            <wsa:Address>http://www.w3.org/2005/08/addressing/anonymous</wsa:Address>
        </wsa:FaultTo>
    </env:Header>
    <env:Body>
        <LaunchSpreadSheetWorkFlowResponse xmlns="http://xmlns.oracle.com/bpmn/bpmnCloudProcess/ISV_ROYALTIES/ISVSpreadSheetMainProcess">
            <instanceNumber xmlns:def="http://www.w3.org/2001/XMLSchema" xsi:type="def:long"
                xmlns=""
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">79630772</instanceNumber>
        </LaunchSpreadSheetWorkFlowResponse>
    </env:Body>
</env:Envelope>

我想访问标签的值:instanceNumber,即 79630772。

如果它是直接有效负载而不是变量,我尝试使用以下方法访问它:

select *  
FROM XMLTABLE('/Envelope/Body/LaunchSpreadSheetWorkFlowResponse'  
         PASSING   
            xmltype('
                <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:wsa="http://www.w3.org/2005/08/addressing">
    <env:Header>
        <wsa:MessageID>urn:bda29066-5961-11ec-87ec-0242c5d8b376</wsa:MessageID>
        <wsa:ReplyTo>
            <wsa:Address>http://www.w3.org/2005/08/addressing/anonymous</wsa:Address>
            <wsa:ReferenceParameters>
                <instra:tracking.ecid xmlns:instra="http://xmlns.oracle.com/sca/tracking/1.0">9b657011-42e4-4cf4-a78e-537551de4cc0-0057ca4a</instra:tracking.ecid>
                <instra:tracking.FlowEventId xmlns:instra="http://xmlns.oracle.com/sca/tracking/1.0">27818206</instra:tracking.FlowEventId>
                <instra:tracking.FlowId xmlns:instra="http://xmlns.oracle.com/sca/tracking/1.0">169007626</instra:tracking.FlowId>
                <instra:tracking.CorrelationFlowId xmlns:instra="http://xmlns.oracle.com/sca/tracking/1.0">0000NqYCMWFDGfdLxeG7yW1X_Nsm0003Yk</instra:tracking.CorrelationFlowId>
                <instra:tracking.quiescing.SCAEntityId xmlns:instra="http://xmlns.oracle.com/sca/tracking/1.0">1830036</instra:tracking.quiescing.SCAEntityId>
            </wsa:ReferenceParameters>
        </wsa:ReplyTo>
        <wsa:FaultTo>
            <wsa:Address>http://www.w3.org/2005/08/addressing/anonymous</wsa:Address>
        </wsa:FaultTo>
    </env:Header>
    <env:Body>
        <LaunchSpreadSheetWorkFlowResponse xmlns="http://xmlns.oracle.com/bpmn/bpmnCloudProcess/ISV_ROYALTIES/ISVSpreadSheetMainProcess">
            <instanceNumber xmlns:def="http://www.w3.org/2001/XMLSchema" xsi:type="def:long"
                xmlns=""
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">79630772</instanceNumber>
                <name>XYZ</name>
        </LaunchSpreadSheetWorkFlowResponse>
    </env:Body>
</env:Envelope>
            ')
         COLUMNS  
            temp2 varchar2(20)     PATH './instanceNumber'
     ) xmlt  
;

以上查询返回了一个空值。

我应该如何访问变量的值?

您需要指定并提供命名空间:

select *  
FROM XMLTABLE(
         XMLNAMESPACES(
            default 'http://xmlns.oracle.com/bpmn/bpmnCloudProcess/ISV_ROYALTIES/ISVSpreadSheetMainProcess',
            'http://schemas.xmlsoap.org/soap/envelope/' AS "env"
         ),
         '/env:Envelope/env:Body/LaunchSpreadSheetWorkFlowResponse'  
         PASSING   
         ...
         COLUMNS  
            temp2 varchar2(20)     PATH '*:instanceNumber'
     ) xmlt  
;

EnvelopeBody 属于 SOAP env 命名空间。在 XML 文档中,LaunchSpreadSheetWorkFlowResponse 节点没有命名空间前缀,但定义了默认命名空间,因此也需要提供默认值。然后 instanceNumber 变得有点尴尬,因为该节点重新定义(或清除)默认值,并定义了额外的名称空间,但不使用它们 - 这使该节点有点陷入困境。我采用了简单的方法,并使用 *: 前缀对其进行了通配。

我认为不太懒惰的方法是将 LaunchSpreadSheetWorkFlowResponse 视为一个单独的 XML 片段,并使用 seconf XMLTable 调用:

select xmlt2.instanceNumber
FROM XMLTABLE(
         XMLNAMESPACES(
            default 'http://xmlns.oracle.com/bpmn/bpmnCloudProcess/ISV_ROYALTIES/ISVSpreadSheetMainProcess',
            'http://schemas.xmlsoap.org/soap/envelope/' AS "env"
         ),
         '/env:Envelope/env:Body/LaunchSpreadSheetWorkFlowResponse'  
         PASSING   
         ...
         COLUMNS  
            LaunchSpreadSheetWorkFlowResponse xmlType     PATH '.'
     ) xmlt1
CROSS JOIN XMLTABLE(
         '.'  
         PASSING   
            xmlt1.LaunchSpreadSheetWorkFlowResponse
         COLUMNS  
            instanceNumber varchar2(20)     PATH 'instanceNumber'
     ) xmlt2
;

我不确定这里是否值得,我很想坚持使用通配符版本。

db<>fiddle 显示两者。