如何读取PL / SQL中的多个XML节点值

时间:2016-10-14 07:38:26

标签: plsql

肥皂反应

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
   <s:Body>
      <GetResponse xmlns="http://tempuri.org/">
         <GetResult xmlns:a="http://schemas.datacontract.org/2004/07/CRM" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
            <a:ResultHeader xmlns:b="http://schemas.datacontract.org/2004/07/CRM">
               <b:ResultCode>000</b:ResultCode>
               <b:ResultDescription>Successful</b:ResultDescription>
            </a:ResultHeader>
            <a:ResultMessage>
               <a:AServices>
                  <a:Service>
                     <a:Date>2016-08-18T11:13:19</a:Date>
                     <a:ServiceID>1</a:ServiceID>
                     <a:ServiceName>GG</a:ServiceName>
                     <a:ServiceType>CM</a:ServiceType>
                  </a:Service>
                  <a:Service>
                     <a:Date>2016-08-16T16:02:03</a:Date>
                     <a:ServiceID>3</a:ServiceID>
                     <a:ServiceName>Cricket</a:ServiceName>
                     <a:ServiceType>AS</a:ServiceType>
                  </a:Service>
               </a:AServices>
            </a:ResultMessage>
         </GetResult>
      </GetResponse>
   </s:Body>
</s:Envelope>

我需要读取该节点的ServiceID。 如果Service节点是多个,那么我需要读取所有子节点ServiceId。

现在我只能读取一个节点如下:

IF(http_resp.status_code = 200) THEN
    -- Create XML type from response text
    x_clob1:= replace(substr(x_clob,instr(x_clob,'<a:Service>'),instr(x_clob,'</a:Service>')-instr(x_clob,'<a:Service>')+length('<a:Service>')+1),'a:',null);
    l_resp_xml := XMLType.createXML(x_clob1);          

    l_resp_serviceId   := l_resp_xml.EXTRACT('//Service/'||'ServiceID'||'/text()').getstringval();
    l_resp_ServiceName := l_resp_xml.EXTRACT('//Service/'||'ServiceName'||'/text()').getstringval();  

甚至如何阅读PL / SQL

中的<ResultHeader>,结果代码和结果库

基于结果代码我只需要检查服务节点。 请提供您的意见。

2 个答案:

答案 0 :(得分:1)

我建议您使用XMLTABLE将XML映射到关系行和列。 您将为每个<a:Service>节点获取一行。

DECLARE
    l_xml              XMLTYPE;
    l_resp_serviceId   VARCHAR2(100); 
    l_resp_ServiceName VARCHAR2(100);

    -- cursor for XMLTABLE, where we create a row for each <a:Service>  node, if ResultCode = '000'
    CURSOR my_cursor IS 
        SELECT *
        FROM XMLTABLE (XMLNAMESPACES(
                              DEFAULT  'http://tempuri.org/',
                              'http://schemas.xmlsoap.org/soap/envelope/' AS "s",
                              'http://schemas.datacontract.org/2004/07/CRM' AS "a",
                              'http://schemas.datacontract.org/2004/07/CRM' AS "b",
                              'http://www.w3.org/2001/XMLSchema-instance' AS "i"),
                              '/s:Envelope/s:Body/GetResponse/GetResult[a:ResultHeader/b:ResultCode = 000]/a:ResultMessage/a:AServices/a:Service'
                              PASSING l_xml
                              COLUMNS                 
                                  "Date"           VARCHAR2(100)  PATH 'a:Date',
                                  "ServiceID"      VARCHAR2(100)  PATH 'a:ServiceID',
                                  "ServiceName"    VARCHAR2(100)  PATH 'a:ServiceName',
                                  "ServiceType"    VARCHAR2(100)   PATH 'a:ServiceType');

BEGIN    
    -- just initialize variable 
    l_xml:= XMLTYPE('
        <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
           <s:Body>
              <GetResponse  xmlns="http://tempuri.org/">
                 <GetResult xmlns:a="http://schemas.datacontract.org/2004/07/CRM" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
                    <a:ResultHeader xmlns:b="http://schemas.datacontract.org/2004/07/CRM">
                       <b:ResultCode>000</b:ResultCode>
                       <b:ResultDescription>Successful</b:ResultDescription>
                    </a:ResultHeader>         
                    <a:ResultMessage>
                       <a:AServices>
                          <a:Service>
                             <a:Date>2016-08-18T11:13:19</a:Date>
                             <a:ServiceID>1</a:ServiceID>
                             <a:ServiceName>GG</a:ServiceName>
                             <a:ServiceType>CM</a:ServiceType>
                          </a:Service>
                          <a:Service>
                             <a:Date>2016-08-16T16:02:03</a:Date>
                             <a:ServiceID>3</a:ServiceID>
                             <a:ServiceName>Cricket</a:ServiceName>
                             <a:ServiceType>AS</a:ServiceType>
                          </a:Service>
                       </a:AServices>
                    </a:ResultMessage>
                 </GetResult>
              </GetResponse>
           </s:Body>
        </s:Envelope>');

   -- iterate over all records     
   FOR rec IN my_cursor LOOP
       l_resp_serviceId:= rec."ServiceID";
       l_resp_ServiceName:= rec."ServiceType";
       dbms_output.put_line('ServiceId='||l_resp_serviceId||', ServiceName='||l_resp_ServiceName);    
   END LOOP;
END;    

答案 1 :(得分:0)

以下是您向前迈出一步的方法:您的问题是您只能限制一项服务。采取所有类似的服务:

x_clob1:= replace(substr(x_clob,instr(x_clob,'<a:AServices>'),instr(x_clob,'</a:AServices>')-instr(x_clob,'<a:AServices>')+length('<a:AServices>')+1),'a:',null);

这将允许您处理两种服务:

declare 
  l_resp_xml XMLType;
  x_clob clob:=to_clob('
   <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
   <s:Body>
      <GetResponse xmlns="http://tempuri.org/">
         <GetResult xmlns:a="http://schemas.datacontract.org/2004/07/CRM" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
            <a:ResultHeader xmlns:b="http://schemas.datacontract.org/2004/07/CRM">
               <b:ResultCode>000</b:ResultCode>
               <b:ResultDescription>Successful</b:ResultDescription>
            </a:ResultHeader>
            <a:ResultMessage>
               <a:AServices>
                  <a:Service>
                     <a:Date>2016-08-18T11:13:19</a:Date>
                     <a:ServiceID>1</a:ServiceID>
                     <a:ServiceName>GG</a:ServiceName>
                     <a:ServiceType>CM</a:ServiceType>
                  </a:Service>
                  <a:Service>
                     <a:Date>2016-08-16T16:02:03</a:Date>
                     <a:ServiceID>3</a:ServiceID>
                     <a:ServiceName>Cricket</a:ServiceName>
                     <a:ServiceType>AS</a:ServiceType>
                  </a:Service>
               </a:AServices>
            </a:ResultMessage>
         </GetResult>
      </GetResponse>
   </s:Body>
</s:Envelope>
'); 
  x_clob1 clob;
  l_resp_serviceId varchar2(1000);
  l_resp_ServiceName varchar2(1000);
begin
    x_clob1:= replace(substr(x_clob,instr(x_clob,'<a:AServices>'),instr(x_clob,'</a:AServices>')-instr(x_clob,'<a:AServices>')+length('<a:AServices>')+1),'a:',null);
    l_resp_xml := XMLType.createXML(x_clob1); 

    l_resp_serviceId   := l_resp_xml.EXTRACT('//Service[1]/'||'ServiceID'||'/text()').getstringval();
    l_resp_ServiceName := l_resp_xml.EXTRACT('//Service[1]/'||'ServiceName'||'/text()').getstringval();  
    dbms_output.put_line(l_resp_serviceId||':'||l_resp_ServiceName);
    --    dbms_output.put_line(x_clob1);
    l_resp_serviceId   := l_resp_xml.EXTRACT('//Service[2]/'||'ServiceID'||'/text()').getstringval();
    l_resp_ServiceName := l_resp_xml.EXTRACT('//Service[2]/'||'ServiceName'||'/text()').getstringval();  
    dbms_output.put_line(l_resp_serviceId||':'||l_resp_ServiceName);
end;

现在要在循环中创建它,如果忽略数据中的服务数量,请在XML对象上使用existsNode以确保它在那里,然后迭代:

declare 
  l_resp_xml XMLType;
  x_clob clob:=to_clob('
   .. test value
'); 
  x_clob1 clob;
  l_resp_serviceId varchar2(1000);
  l_resp_ServiceName varchar2(1000);
  i integer := 1;
begin

  x_clob1:= replace(substr(x_clob,instr(x_clob,'<a:AServices>'),instr(x_clob,'</a:AServices>')-instr(x_clob,'<a:AServices>')+length('<a:AServices>')+1),'a:',null);
  l_resp_xml := XMLType.createXML(x_clob1);    

  WHILE l_resp_xml.existsNode('//Service[' || i || ']') = 1 LOOP 
    l_resp_serviceId   := l_resp_xml.EXTRACT('//Service['||i||']/'||'ServiceID'||'/text()').getstringval();
    l_resp_ServiceName := l_resp_xml.EXTRACT('//Service['||i||']/'||'ServiceName'||'/text()').getstringval();  
    dbms_output.put_line(l_resp_serviceId||':'||l_resp_ServiceName);
    i := i + 1;
  END LOOP;
end;