Oracle DB 中 XMLTYPE 列中的 XML 编码



我创建了一个这样的表:

create table b (data timestamp, value XMLTYPE);

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

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;

当我尝试查看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>

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

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

数据库的NLS_CHARACTERSET参数为 WE8MSWIN1252。 为什么要追加?我可以随时将谁存储为 UTF-8?

Oracle 将使用客户端字符集从 CLOB 或 String 创建XMLTYPE,并完全忽略 XML prolog 中的编码(请参阅文档(。您可以设置encoding="blabla",它将起作用。Oracle 仅在从 BLOB 创建 XMLTYPE 时遵循 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;

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

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

select asciistr('Çõ'), unistr('0C70F5') from dual;

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

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

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

最新更新