Как импортировать XML-файл, содержащий китайские иероглифы и кодировку UTF-8, в базу данных Oracle с использованием US7ASCII - PullRequest
0 голосов
/ 29 июня 2018

Я изо всех сил пытался импортировать XML-файл, содержащий китайские символы и закодированный в UTF-8, из внешних источников в нашу базу данных Oracle, которая использует кодирование US7ASCII. Тем не менее, ошибка ниже продолжает вызывать:

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 голосов
/ 29 июня 2018

Вам следует подумать о переносе вашей базы данных в UTF-8, см. Миграция набора символов . Перенос БД с US7ASCII на AL32UTF8 не должен создавать никаких проблем.

Oracle DB DB Ограничения говорит:

NCHAR, NVARCHAR2 и NCLOB не поддерживаются - Oracle XML DB не поддерживает поддерживать использование типов данных SQL NCHAR, NVARCHAR2 и NCLOB для любых из следующего:

  • Отображение элементов или атрибутов XML в эти типы данных с использованием аннотации SQLType в схеме XML

  • Генерация данных XML из этих типов данных с использованием функций SQL / XML XMLElement, XMLAttributes и XMLForest

  • Внутри функций 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 .

0 голосов
/ 29 июня 2018

Я нашел решение, чтобы прочитать файл 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;
0 голосов
/ 29 июня 2018

У вас нет базы данных US7ASCII для тестирования, но вы можете конвертировать наборы символов для xmltypes с помощью метода getblobval

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>
...