如何使用US7ASCII将包含汉字和UTF-8编码的XML文件导入Oracle数据库

时间:2018-06-29 03:12:29

标签: xml oracle plsql utf-8 ascii

我一直在努力将包含汉字并以UTF-8编码的XML文件从外部各方导入到我们的使用US7ASCII编码的Oracle数据库中。但是,下面的错误一直提示:

pkg_dxe.get_xmldata: ORA-31011: XML parsing failed
ORA-19202: Error occurred in XML processing
LPX-00200: could not convert from encoding UTF-8 to US-ASCII
Error at line 1

处理导入过程的PL \ SQL代码:

v_xml := XMLType(bfilename('XMLDIR_IBISAPP', 'xmldata.xml'), nls_charset_id('UTF8'));
Select count(*) into v_cnt from XML_TAB_A;
If v_cnt > 0 then    
    update XML_TAB_A set 
        xml_data = v_xml, 
        timestamp = sysdate;
else
    Insert into XML_TAB_A(xml_data, timestamp) values (v_xml, sysdate);
end if;

XML示例:

<?xml version="1.0" standalone="yes" ?> 
<APPLICATION>
  <DXE_APPLICATION>
    <APP_TRAN_NO>20180621031622817</APP_TRAN_NO> 
  </DXE_APPLICATION>
  <DXE_CUSTOMER>
    <APP_TRAN_NO>20180621031622817</APP_TRAN_NO> 
    <SEQ>0</SEQ>  
    <CUST_TITLE>Mr.</CUST_TITLE> 
    <CUST_NAME>HELLO</CUST_NAME> 
    <CUST_GNAME>HELLO</CUST_GNAME> 
    <CUST_ONAME>hello</CUST_ONAME> 
    <CUST_NAME_CHN>陳大文</CUST_NAME_CHN>
  </DXE_CUSTOMER>
</APPLICATION>

导致该错误的字段是Cust_Name_Chn,但是我们不能排除在其他字段中还会提供汉字的情况。

有什么方法可以正确地将XML导入我们的Oracle数据库,而不会在包含中文字符时提示错误?如果在此阶段导入后无法读取汉字,则可以接受。

我尝试使用CONVERT()函数,但错误LPX-00200仍然存在。

3 个答案:

答案 0 :(得分:0)

没有US7ASCII数据库可供测试,但是您可以通过getblobval方法将xmltypes字符集转换为

with x as
    (select xmltype('<?xml version="1.0" standalone="yes" ?> 
<APPLICATION>
  <DXE_APPLICATION>
    <APP_TRAN_NO>20180621031622817</APP_TRAN_NO> 
  </DXE_APPLICATION>
  <DXE_CUSTOMER>
    <APP_TRAN_NO>20180621031622817</APP_TRAN_NO> 
    <SEQ>0</SEQ>  
    <CUST_TITLE>Mr.</CUST_TITLE> 
    <CUST_NAME>HELLO</CUST_NAME> 
    <CUST_GNAME>HELLO</CUST_GNAME> 
    <CUST_ONAME>hello</CUST_ONAME> 
    <CUST_NAME_CHN>陳大文</CUST_NAME_CHN>
  </DXE_CUSTOMER>
</APPLICATION>') a from dual)
select xmltype(x.a.getblobval(NLS_CHARSET_ID('US7ASCII')),NLS_CHARSET_ID('US7ASCII')) y
from x x;

将名称行转到:

<CUST_NAME_CHN>&#x9673;&#x5927;&#x6587;</CUST_NAME_CHN>

答案 1 :(得分:0)

您应该考虑将数据库迁移到UTF-8,请参见Character Set Migration。将数据库从US7ASCII迁移到AL32UTF8不会造成任何麻烦。

Oracle XML DB Restrictions说:

  

不支持NCHAR,NVARCHAR2和NCLOB –不支持Oracle XML DB   支持将SQL数据类型NCHAR,NVARCHAR2和NCLOB用于任何   以下:

     
      
  • 在XML模式中使用SQLType注释将XML元素或属性映射到这些数据类型

  •   
  • 使用SQL / XML函数XMLElement,XMLAttributes和XMLForest从这些数据类型生成XML数据

  •   
  • 在SQL / XML函数XMLQuery和XMLTable中,在表上使用XQuery函数ora:view(不建议使用),fn:doc和fn:collection   包含具有这些数据类型的列

  •   
     

处理,存储或生成包含多字节的XML数据   字符,Oracle强烈建议您使用AL32UTF8作为   数据库字符集。

您可以将纯数据存储为NCLOB

CREATE TABLE XML_TAB_A (xml_data NCLOB, ts TIMESTAMP);

DECLARE

    v_nclob NCLOB;
    v_cnt NUMBER;

    xbfile   BFILE; 
    destOffset INTEGER := 1; 
    srcOffset INTEGER := 1; 
    langContext INTEGER := DBMS_LOB.DEFAULT_LANG_CTX; 
    warning INTEGER; 

BEGIN

    xbfile := BFILENAME ('XMLDIR_IBISAPP', 'xmldata.xml'); 
    DBMS_LOB.OPEN (xbfile); 
    DBMS_LOB.CREATETEMPORARY (v_nclob, TRUE, DBMS_LOB.SESSION); 
    DBMS_LOB.LOADCLOBFROMFILE (
        dest_lob => v_nclob, 
        src_bfile => xbfile, 
        amount => DBMS_LOB.GETLENGTH(xbfile), 
        dest_offset => destOffset, 
        src_offset => srcOffset, 
        bfile_csid => NLS_CHARSET_ID('AL32UTF8'), 
        lang_context => langContext, 
        warning => warning);    
    DBMS_LOB.CLOSE (xbfile); 

    SELECT COUNT(*) INTO v_cnt FROM XML_TAB_A;
    IF v_cnt > 0 THEN    
         UPDATE XML_TAB_A SET 
              xml_data = v_nclob, 
              ts = SYSDATE;
    ELSE
         INSERT INTO XML_TAB_A(xml_data, ts) VALUES (v_nclob, SYSDATE);
    END IF;

END;

但是,您将无法使用任何XMLTYPE函数。

答案 2 :(得分:0)

我找到了一种将XML文件读入Clob,然后将其转换回XMLType以避免提示编码错误的解决方案

file := bfilename('XMLDIR_IBISAPP', 'xmldata.xml');
dbms_lob.createTemporary(contents, true, dbms_lob.session);
dbms_lob.fileopen(file, dbms_lob.file_readonly);
dbms_lob.loadClobfromFile(contents, file, dbms_lob.getLength(file), dest_offset, src_offset, nls_charset_id('AL32UTF8'), lang_context, conv_warning);
dbms_lob.fileclose(file);

v_xml := XMLTYPE.createXML(contents);

Update xml_tab_a set 
        xml_data = v_xml, 
        timestamp = sysdate;