You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在APEX中将CLOB转换为XMLTYPE时遭遇ORA-06512数值/值错误

问题分析与解决思路

问题重现

我有一个名为ws_get_test的PL/SQL函数,返回CLOB格式的SOAP响应。在APEX页面中执行以下代码时,l_xml XMLTYPE := XMLTYPE(l_xml_response);这行会抛出ORA-06512数值或值错误,但相同逻辑在SQL Developer中执行完全正常:

DECLARE
l_xml_response  CLOB;
l_xml XMLTYPE;
BEGIN
select ws_get_test(p_no => '12345' ) into l_xml_response from dual;   
l_xml XMLTYPE := XMLTYPE(l_xml_response);
END;

ws_get_test函数代码如下:

create or replace function ws_get_test(p_no varchar2)
return  clob
as
l_envelope CLOB;
l_xml XMLTYPE;
l_result clob;
begin
l_envelope := '<soapenv:Envelope xmlns:soapenv="http:schemas.xmlsoap.org/soap/envelope/" xmlns:wsei="http://wsei.test.com">

   <soapenv:Header/>

   <soapenv:Body>

      <wsei:CatchData>

         <wsei:lk_no>' || p_no ||  '</wsei:lk_no>

      </wsei:CatchData>

   </soapenv:Body>

</soapenv:Envelope>';

l_xml :=APEX_WEB_SERVICE.make_request(

p_url   => 'http://example.com/services/DS_CatchData',

p_action => 'urn:CatchData',

p_envelope => l_envelope

);
l_result := APEX_WEB_SERVICE.parse_xml_clob(
p_xml =>remove_namespace(l_xml),
p_xpath =>'/Envelope/Body/Data',
p_ns=> ''

);
return l_result;
END;

核心原因排查方向

1. 环境差异导致的响应异常

  • 字符集不匹配:APEX与SQL Developer的数据库/会话字符集不一致,CLOB中的XML包含非法字符,无法被XMLTYPE解析。
  • Web服务访问差异:APEX环境的网络权限、代理设置和SQL Developer不同,调用APEX_WEB_SERVICE.make_request时返回的不是合法XML(比如错误页面、空响应)。

2. 自定义函数remove_namespace的结构破坏

该函数的实现可能在处理XML时破坏了文档结构,比如遗漏标签闭合、引入不可见字符,导致最终返回的CLOB不是合法XML。

3. XMLTYPE构造的格式限制

如果l_xml_response为空、存在未转义的特殊字符(如&未转义为&amp;),或者XML结构不完整,都会触发数值或值错误。

解决步骤

步骤1:捕获详细错误信息

在APEX代码中添加异常处理,打印具体错误和响应片段,定位问题根源:

DECLARE
l_xml_response  CLOB;
l_xml XMLTYPE;
BEGIN
select ws_get_test(p_no => '12345' ) into l_xml_response from dual;   
l_xml := XMLTYPE(l_xml_response);
EXCEPTION
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE('错误信息: ' || SQLERRM);
    -- 打印响应前500字符,确认是否为合法XML
    DBMS_OUTPUT.PUT_LINE('响应内容片段: ' || DBMS_LOB.SUBSTR(l_xml_response, 500));
END;

步骤2:验证remove_namespace函数逻辑

检查该自定义函数的实现,确保它不会破坏XML结构。可以在SQL Developer中执行以下代码对比处理前后的XML:

DECLARE
  l_test_xml XMLTYPE := XMLTYPE('<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><Data>test</Data></soapenv:Body></soapenv:Envelope>');
BEGIN
  DBMS_OUTPUT.PUT_LINE('处理前: ' || l_test_xml.getClobVal());
  DBMS_OUTPUT.PUT_LINE('处理后: ' || remove_namespace(l_test_xml).getClobVal());
END;

步骤3:对比APEX与SQL Developer的Web服务响应

在APEX中直接调用Web服务并输出原始响应,确认和SQL Developer的返回是否一致:

DECLARE
  l_envelope CLOB;
  l_xml XMLTYPE;
BEGIN
l_envelope := '<soapenv:Envelope xmlns:soapenv="http:schemas.xmlsoap.org/soap/envelope/" xmlns:wsei="http://wsei.test.com">
   <soapenv:Header/>
   <soapenv:Body>
      <wsei:CatchData>
         <wsei:lk_no>12345</wsei:lk_no>
      </wsei:CatchData>
   </soapenv:Body>
</soapenv:Envelope>';

l_xml :=APEX_WEB_SERVICE.make_request(
p_url   => 'http://example.com/services/DS_CatchData',
p_action => 'urn:CatchData',
p_envelope => l_envelope
);
DBMS_OUTPUT.PUT_LINE('Web服务原始响应: ' || l_xml.getClobVal());
END;

步骤4:修复字符集或XML格式问题

如果是字符集不匹配,转换CLOB字符集后再构造XMLTYPE(根据实际环境调整字符集参数):

l_xml := XMLTYPE(UTL_I18N.CONVERT(l_xml_response, 'AL32UTF8', 'WE8ISO8859P1'));

如果是XML格式问题,检查APEX_WEB_SERVICE.parse_xml_clob的XPath是否正确,确保返回的l_result是完整合法的XML片段。


内容的提问来源于stack exchange,提问作者hancho

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 10:09:56