Plsql 如何在PL/SQL中读取多个XML节点值
Soap响应Plsql 如何在PL/SQL中读取多个XML节点值,plsql,Plsql,Soap响应 <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.
<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。
如果服务节点是多个,那么我需要读取所有子节点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中读取结果代码和resultdisc
根据结果代码,我只需要检查服务节点。
请提供您的意见 以下是您如何向前迈进一步的方法:您的问题是您仅限于一项服务。以所有服务为例: x_clob1:=replacesubstrx_clob,instrx_clob,,instrx_clob,-instrx_clob,+length+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;
我建议您使用XMLTABLE将XML映射到关系行和关系列。
您将为每个节点获得一行
第1行的错误可能重复ORA-30625:不允许对NULL自参数进行方法分派ORA-06512:在第145行,我在输出中看到While循环的第一个给定值..但它有8个服务节点,它应该在输出中给出8个值No,=1只是为了检查它是否存在。它确实在每个节点上循环。那么循环所有8个节点的条件是什么,在我的响应中,所有8个节点中的8个服务节点,我需要读取服务ID。请花时间测试它。我在这里做了,得到了预期的两行结果。我在xpath中添加了一个条件,现在我的示例仅当ResultCode='000'时才从服务节点返回信息。
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;
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;