ORA-31011:XML解析失败,预期'<'代替 '?'

时间:2016-01-21 08:56:14

标签: xml oracle plsql xml-parsing

我正在尝试从包含以下内容的文件中获取XML数据

<?xml version="1.0" encoding="UTF-8"?>
<BURS_REPORT>
   <REQUESTID>128546198</REQUESTID>
   <PARENT_REQUESTID>128546195</PARENT_REQUESTID>
   <REPORT_DESC>Description here</REPORT_DESC>
   <OUTPUT_FILE>path_here/o128546198.zip</OUTPUT_FILE>
   <DOCUMENT_STATUS>
      <KEY>1250168</KEY>
      <OUTPUT_TYPE>pdf</OUTPUT_TYPE>
      <DELIVERY>email</DELIVERY>
      <OUTPUT>path_here/1331000-1.pdf</OUTPUT>
      <STATUS>success</STATUS>
      <LOG />
   </DOCUMENT_STATUS>
</BURS_REPORT>

检索内容的代码:

declare
  v_outfile_name varchar2(4500) := '/opt/apps/r12/d1ebs/conc/out/o128553806.out';
  t_temp varchar2(4500) := substr(v_outfile_name, instr(v_outfile_name, '/', -1) + 1);
  v_file bfile := bfilename('CONC_OUT', substr(v_outfile_name, instr(v_outfile_name, '/', -1) + 1));
  v_file_length number;
  v_buffer clob;
  v_xml xmltype;
begin
  dbms_output.put_line('start');
  -- return
  dbms_lob.createtemporary(v_buffer, true);

  dbms_lob.fileopen(v_file, dbms_lob.file_readonly);
  v_file_length := dbms_lob.getlength(v_file);
  if v_file_length > 0 then
    dbms_lob.loadfromfile(v_buffer, v_file, v_file_length);
    v_xml := xmltype(v_buffer); -- error occurs here
  else
    v_xml := null;
  end if;
  dbms_lob.fileclose(v_file);
  dbms_lob.freetemporary(v_buffer);
  -- more code
end;
/

(编辑:摘自this image

运行得到:

Entered Exceptions with Others
ORA-31011: XML parsing failed
ORA-19202: Error occurred in XML processing
LPX-00210: expected '<' instead of '?'
Error at line 1
ORA-06512: at "SYS.XMLTYPE", line 272    
ORA-06512: at "APPS.NI_DOCUMENT_DISTRIBUTION_PUB", line 435

我尝试显示v_temp的值,并显示奇怪的字符:

v_temp: 㰿硭氠癥牳楯渽∱⸰∠敮捯摩湧㴢啔䘭㠢㼾਼䉕剓归䕐佒吾㱒䕑啅協䥄㸱㈸㔵㌷㔶㰯剅兕䕓呉䐾㱐䅒䕎呟剅兕䕓呉䐾ㄲ㠵㔳㜵〼⽐䅒䕎呟剅兕䕓呉䐾㱒䕐佒呟䑅千㹎䥁匠兵潴攠䕭慩氠䑩獴物扵瑩潮⁗潲步爼⽒䕐佒呟䑅千㸼何呐啔彆䥌䔾⽯灴⽡灰猯爱㈯搱敢猯捯湣⽯畴⽯ㄲ㠵㔳㜵㘮穩瀼⽏啔偕呟䙉䱅㸼䑏䍕䵅乔当呁呕匾㱋䕙㸱㈵㌱㜱㰯䭅夾㱏啔偕呟呙偅㹰摦㰯何呐啔彔奐䔾㱄䕌䥖䕒夾敭慩氼⽄䕌䥖䕒夾㱏啔偕吾⽯灴⽡灰猯爱㈯搱敢猯獨慲敳⽷敢影畯瑥猯义兵潴敟ㄳ〴㠶㤭ㄮ灤昼⽏啔偕吾㱓呁呕匾獵捣敳猼⽓呁呕匾㱌佇㸼⽌佇㸼⽄佃啍䕎呟協䅔啓㸼⽂啒卟剅偏剔

为什么会这样?

1 个答案:

答案 0 :(得分:0)

看起来您的源文件编码为UTF-8。 documentation for loadfromfile说:

  

如果字符集的宽度变化,例如UTF-8,则LOB值以固定宽度的UCS2格式存储。因此,如果您使用的是DBMS_LOB.LOADFROMFILE,则BFILE中的数据应该是UCS2字符集而不是UTF-8字符集。

如果你使用loadclobfromfile代替那么它可以处理UTF-8源文件,你只需要传递一些参数:

declare
  v_outfile_name varchar2(4500) := '/opt/apps/r12/d1ebs/conc/out/o128553806.out';
  v_file bfile := bfilename('CONC_OUT', substr(v_outfile_name, instr(v_outfile_name, '/', -1) + 1));
  v_file_length number;
  v_buffer clob;
  v_xml xmltype;
  v_dest_offset integer := 1;
  v_src_offset integer := 1;
  v_bfile_csid number := 0;
  v_lang_context integer := 0;
  v_warning integer;
begin
  dbms_lob.createtemporary(v_buffer, true);
  dbms_lob.fileopen(v_file, dbms_lob.file_readonly);
  v_file_length := dbms_lob.getlength(v_file);
  if v_file_length > 0 then
    dbms_lob.loadclobfromfile(dest_lob => v_buffer,
      src_bfile => v_file,
      amount => v_file_length,
      dest_offset => v_dest_offset,
      src_offset => v_src_offset,
      bfile_csid => v_bfile_csid,
      lang_context => v_lang_context,
      warning => v_warning);
    v_xml := xmltype(v_buffer);
  end if;
  dbms_lob.fileclose(v_file);
  dbms_lob.freetemporary(v_buffer);
end;
/

为了简洁起见,我默认了CSID并忽略了OUT参数中设置的值。