Oracle DB中的XMLTYPE列中的XML编码

时间:2018-05-24 17:11:23

标签: xml oracle character-encoding oracle12c toad

我有一个像这样创建的表:

DECLARE
    lc_Soap         CLOB;
    lc_Request      CLOB;
    px_RequestXML   XMLTYPE
        := XMLTYPE ('<test><test1>ABDDÇJJSõ</test1></test>');
BEGIN
    DELETE b;

    lc_Soap :=
        '<?xml version="1.0" encoding="ISO-8859-1"?>
               <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
                  <s:Header>
                      <h:AxisValues xmlns="urn:/microsoft/multichannelframework/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:h="urn:/microsoft/multichannelframework/">
                          <User xmlns="">TEST</User>
                      </h:AxisValues>
                  </s:Header>
                  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
                      <substr/>
                  </s:Body>
              </s:Envelope>';

    lc_Request :=
        pkg_utils.replace_clob (lc_Soap,
                                '<substr/>',
                                xml_utils.XMLTypeToClob (px_RequestXML));

    px_RequestXML := XMLTYPE.createXML (lc_Request);

    INSERT INTO b
         VALUES (SYSTIMESTAMP, px_RequestXML);

    COMMIT;
END;

我在TOAD 12.6中运行此脚本以在表中存储XML。

VALUE

当我尝试查看UTF-8列中的内容时,我得到了这种编码<?xml version="1.0" encoding="UTF-8"?> <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> <s:Header> <h:AxisValues xmlns="urn:/microsoft/multichannelframework/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:h="urn:/microsoft/multichannelframework/"> <User xmlns="">TEST</User> </h:AxisValues> </s:Header> <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <test> <test1>ABDDÇJJSõ</test1> </test> </s:Body> </s:Envelope>

<?xml version="1.0" encoding="WINDOWS-1252"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <h:AxisValues xmlns="urn:/microsoft/multichannelframework/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:h="urn:/microsoft/multichannelframework/">
      <User xmlns="">TEST</User>
    </h:AxisValues>
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <test>
      <test1>ABDDÇJJSõ</test1>
    </test>
  </s:Body>
</s:Envelope>

但是这个脚本是为了在不同的DB用户或Oracle JOB中运行而构建的。在这种情况下,编码是不同的:

NLS_CHARACTERSET

DB的{{1}}参数是WE8MSWIN1252。 为什么要追加?谁能直接存储为UTF-8?

2 个答案:

答案 0 :(得分:3)

Oracle将使用客户端字符集从CLOB或String创建XMLTYPE,并完全忽略XML prolog中的编码(请参阅docs)。您可以设置encoding="blabla",它会起作用。只有在从BLOB创建XMLTYPE时,Oracle才会尊重XML prolog中的编码。

客户端环境在读取XMLTYPE时也会驱动编码。如果您希望XML文档以UTF-8编码而不管客户端编码如何,则必须将其检索为BLOB。

通过getBlobVal()

SELECT (c2).getBlobVal(nls_charset_id('UTF8')) FROM b;

或通过xmlserialize()

SELECT xmlserialize(DOCUMENT c2 AS BLOB ENCODING 'UTF-8') FROM b;

答案 1 :(得分:1)

如果在从客户端发送到数据库的内容中包含非ASCII字符(例如ABDDJJJSõ),则可能需要从客户端字符集到DB字符集进行转换。如果客户端对正在使用的字符集不正确,或者数据库无法处理字符,则可能会变得复杂。如果内容来自文件,那么在处理文件时,还有其他应用程序错误理解字符集的风险(例如版本控制)

使用任何潜在问题字符的编码版本通常更安全。您可以使用ASCIISTR获取字符串的明确转换版本,并使用UNISTR将其转换回来。

select asciistr('Çõ'), unistr('\00C7\00F5') from dual;

您甚至可以检查字符是否按预期转换。

http://www.fileformat.info/info/unicode/char/00c7/index.htm http://www.fileformat.info/info/unicode/char/00f5/index.htm

如果脚本中没有非ascii字符,则可以消除许多潜在问题。可能仍有问题,但它们更易于诊断。