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

Posted

技术标签:

【中文标题】从 Oracle SQL 中的变量访问 XML 中的值【英文标题】:Accessing values in XML from a variable in Oracle SQL 【发布时间】:2022-01-14 21:28:44 【问题描述】:

我在变量 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  
;

上述查询返回一个空值。

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

【问题讨论】:

您的实际问题是什么:空值或如何分配变量?后者取决于变量和 SQL 查询是如何相关的:如果它们在同一个 PL/SQL 块中,那么只需传递变量而不是常量 XML 嗨,我想访问作为 XML 一部分的 instanceNumber 的值。并且 XML 将出现在变量 p_xml 中。 【参考方案1】:

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

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 显示两者。

【讨论】:

谢谢你成功了。我们无法弄清楚如何到达 LaunchSpreadSheetWorkFlowResponse。默认的帮助我们。谢谢你:)

以上是关于从 Oracle SQL 中的变量访问 XML 中的值的主要内容,如果未能解决你的问题,请参考以下文章

从XML到Oracle PL / SQL环境中的路径列表

Oracle PL/SQL 使用 XMLTABLE 解析 xml 中的嵌套对象

如何从 Oracle 访问 MS Access 数据库?

列名作为 PL/SQL ORACLE 中的变量

将 XML 文档从 SQL SERVER 插入到 Oracle

sql中的变量定义