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

时间:2015-09-24 12:51:09

标签: sql oracle xml-namespaces

我有下面提到的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 query以从字符串<xsd1:id>201505261213407749</xsd1:id><ser:letterKey>POS_CONTRACT_PRIVATE</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://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;

1 个答案:

答案 0 :(得分:1)

您为命名空间别名提供的URL必须与XML中定义的URL匹配:

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。所以这个woudl也可以工作,例如:

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