从 oracle sql 中的 xml 字符串获取值

get the value from xml string in oracle sql

我有以下 xml 字符串,如下所述:

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" 
xmlns:ser="http://service.soap.CDRator.com" xmlns:xsd="http://data.soap.CDRator.com/xsd" 
xmlns:xsd1="http://core.data.soap.CDRator.com/xsd" xmlns:xsd2="http://core.result.service.soap.CDRator.com/xsd">
   <soap:Body>
      <ser:generateArchiveDocument>
         <!--Optional:-->
         <ser:contextUser>
            <!--Optional:-->
            <xsd:brandKey>QAMSP</xsd:brandKey>
         </ser:contextUser>
         <!--Optional:-->
         <ser:subscription>
            <!--Optional:-->
            <xsd1:id>201505261213407749</xsd1:id>            
         </ser:subscription>
         <!--Optional:-->
         <ser:letterKey>POS_CONTRACT_PRIVATE</ser:letterKey>
      </ser:generateArchiveDocument>
   </soap:Body>
</soap:Envelope>

我在下面写了 select 查询以从字符串 <xsd1:id>201505261213407749</xsd1:id><ser:letterKey>POS_CONTRACT_PRIVATE</ser:letterKey> 中获取值。我想从此字符串中获取值,但查询 return 什么都没有。

这是我的 select 查询:

SELECT ID,xt_req.SUBSCRIPTION_ID,CREATE_DATE,WEB_SERVICE_NAME,WEB_METHOD_NAME
FROM TEMP_SOAP_GENERATE_CONTRACT sm
CROSS JOIN XMLTable(XMLNAMESPACES (
      'http://www.w3.org/2003/05/soap-envelope' AS "xsd1"
    ),
    'for $i in //xsd1:id return $i'
    passing XMLType(sm.REQUEST_XML)
    columns "SUBSCRIPTION_ID" number path '/') xt_req    
CROSS JOIN XMLTable(XMLNAMESPACES (
      'http://www.w3.org/2003/05/soap-envelope' AS "ser"
    ),
    'for $i in ser:letterKey return $i'
    passing XMLType(sm.REQUEST_XML)
    columns "LETTER_KEY" VARCHAR2(1000) path '/') xt_letterkey;

您为命名空间别名提供的 URL 必须与 XML:

中定义的相匹配
CROSS JOIN XMLTable(XMLNAMESPACES (
      'http://core.data.soap.CDRator.com/xsd' AS "xsd1"
    ),

CROSS JOIN XMLTable(XMLNAMESPACES (
      'http://service.soap.CDRator.com' AS "ser"
    ),

命名空间别名不必与原始 XML 中使用的别名相匹配 - 您可以将其命名为其他名称,尽管这可能会造成混淆,因此我不推荐它;但是 URL 必须匹配。它是 URL 命名空间别名代表的,用于匹配节点。所以这也可以工作,例如:

CROSS JOIN XMLTable(XMLNAMESPACES (
      'http://core.data.soap.CDRator.com/xsd' AS "my_alias"
    ),
    'for $i in //my_alias:id return $i'

对于您的 seconf XMLTable,XPath 正在寻找顶级元素;与第一个一样,最简单的做法是使用 //ser:letterKey 而不是 //ser:letterKey.

忽略任何先前的级别

所以放在一起:

SELECT ID,xt_req.SUBSCRIPTION_ID,CREATE_DATE,WEB_SERVICE_NAME,WEB_METHOD_NAME
FROM TEMP_SOAP_GENERATE_CONTRACT sm
CROSS JOIN XMLTable(XMLNAMESPACES (
      'http://core.data.soap.CDRator.com/xsd' AS "xsd1"
    ),
    'for $i in //xsd1:id return $i'
    passing XMLType(sm.REQUEST_XML)
    columns "SUBSCRIPTION_ID" number path '/') xt_req    
CROSS JOIN XMLTable(XMLNAMESPACES (
      'http://service.soap.CDRator.com' AS "ser"
    ),
    'for $i in //ser:letterKey return $i'
    passing XMLType(sm.REQUEST_XML)
    columns "LETTER_KEY" VARCHAR2(1000) path '/') xt_letterkey;

...which gets back one row.