DB2 UTF-8 XML C2 85 到换行转换
DB2 UTF-8 XML C2 85 to new line conversion
我们在 table 中保存编码为 DB2 9.7 LUW 的 XML 数据 ( UTF-8) 时遇到问题。
Table DDL:
CREATE TABLE DB2ADMIN.TABLE_FOR_XML
(
ID INTEGER NOT NULL,
XML_FIELD XML NOT NULL
)
问题出现在一些罕见的 Unicode 字符的例子中,我们使用 java jdbc db2 driver。
例如在正常模式下查看编辑器而不是十六进制视图 (Notepad++) 下面这个奇怪的 A(在 16. 之后)在黑色方块中表示为 NEL
输入 XML 采用 UTF-8 编码,在 HEX 编辑器中查看时具有以下值:
00000010h: 31 36 2E 20 C2 85 42 ; 16. Â…B
After inserting in DB2 I presume that some kind of conversion occurs because when selecting data back this same character are now
00000010h: 31 36 2E 20 0D 0A 42 ; 16. ..B
C2 85 转换为 0D 0A 即换行。
另一件事我注意到,虽然将 XML 保存到 table header 内容开始于
<xml version="1.0" encoding="UTF-8">
但是从 db2 中获取 xml 后内容开始于
<xml version="1.0" encoding="UTF-16">
有没有办法强制 db2 在不进行转换的情况下以 UTF-8 格式存储 XML?使用 XMLSERIALIZE 获取没有帮助
SELECT XML_FIELD AS CONTENT1, XMLSERIALIZE(XML_FIELD as cLOB(1M)) AS CONTENT2 from DB2ADMIN.TABLE_FOR_XML
在 content2 中没有 XML header 但有 stile newLine。
此行为是 XML 1.1 处理器的标准行为。 XML 1.1 s2.11:
the XML processor must behave as if it normalized all line breaks in external parsed entities (including the document entity) on input, before parsing, by translating [the single character #x85] to a single #xA character
行尾类型是文档的众多细节之一,这些细节将在解析和序列化循环中丢失(例如属性顺序、标签中的空格、数字字符引用...)。
DB2 的 XML 字段使用 XML 1.1 有点令人惊讶,因为很少有人使用 XML 的修订版,但对 NEL(古老的,无用的大型机行结束字符)是 IBM 唯一想要的东西。
Is there way to force db2 to store XML in UTF-8 without conversions ?
使用 BLOB?
如果您需要原生XML字段功能和来保留文档的原始序列化格式,那么您将需要两列。
(你确定你需要保留 NEL 行尾吗?通常没有人关心行尾,这些都是假的。)
因为我通常不需要不可读字符,所以在将 XML 字符串保存到 Db2 之前,我决定从 x'c285(代码点 133)和 4 字节 UTF-8 字符实现干净的字符串,仅用于案例:
找到类似的例子(How to replace/remove 4(+)-byte characters from a UTF-8 string in Java?)并进行了调整。
public static final String LAST_3_BYTE_UTF_CHAR = "\uFFFF";
public static final String REPLACEMENT_CHAR = "\uFFFD";
public static String toValid3ByteUTF8String(String line) {
final int length = line.length();
StringBuilder b = new StringBuilder(length);
for (int offset = 0; offset < length; ) {
final int codepoint = line.codePointAt(offset);
// do something with the codepoint
if (codepoint > LAST_3_BYTE_UTF_CHAR.codePointAt(0)) { //4-byte UTF replace
b.append(REPLACEMENT_CHAR);
} else if( codepoint == 133){ //NEL or x'c285
b.append(REPLACEMENT_CHAR);
} else {
if (Character.isValidCodePoint(codepoint)) {
b.appendCodePoint(codepoint);
} else {
b.append(REPLACEMENT_CHAR);
}
}
offset += Character.charCount(codepoint);
}
return b.toString();
}
我们在 table 中保存编码为 DB2 9.7 LUW 的 XML 数据 ( UTF-8) 时遇到问题。
Table DDL:
CREATE TABLE DB2ADMIN.TABLE_FOR_XML
(
ID INTEGER NOT NULL,
XML_FIELD XML NOT NULL
)
问题出现在一些罕见的 Unicode 字符的例子中,我们使用 java jdbc db2 driver。
例如在正常模式下查看编辑器而不是十六进制视图 (Notepad++) 下面这个奇怪的 A(在 16. 之后)在黑色方块中表示为 NEL
输入 XML 采用 UTF-8 编码,在 HEX 编辑器中查看时具有以下值:
00000010h: 31 36 2E 20 C2 85 42 ; 16. Â…B
After inserting in DB2 I presume that some kind of conversion occurs because when selecting data back this same character are now
00000010h: 31 36 2E 20 0D 0A 42 ; 16. ..B
C2 85 转换为 0D 0A 即换行。
另一件事我注意到,虽然将 XML 保存到 table header 内容开始于
<xml version="1.0" encoding="UTF-8">
但是从 db2 中获取 xml 后内容开始于
<xml version="1.0" encoding="UTF-16">
有没有办法强制 db2 在不进行转换的情况下以 UTF-8 格式存储 XML?使用 XMLSERIALIZE 获取没有帮助
SELECT XML_FIELD AS CONTENT1, XMLSERIALIZE(XML_FIELD as cLOB(1M)) AS CONTENT2 from DB2ADMIN.TABLE_FOR_XML
在 content2 中没有 XML header 但有 stile newLine。
此行为是 XML 1.1 处理器的标准行为。 XML 1.1 s2.11:
the XML processor must behave as if it normalized all line breaks in external parsed entities (including the document entity) on input, before parsing, by translating [the single character #x85] to a single #xA character
行尾类型是文档的众多细节之一,这些细节将在解析和序列化循环中丢失(例如属性顺序、标签中的空格、数字字符引用...)。
DB2 的 XML 字段使用 XML 1.1 有点令人惊讶,因为很少有人使用 XML 的修订版,但对 NEL(古老的,无用的大型机行结束字符)是 IBM 唯一想要的东西。
Is there way to force db2 to store XML in UTF-8 without conversions ?
使用 BLOB?
如果您需要原生XML字段功能和来保留文档的原始序列化格式,那么您将需要两列。
(你确定你需要保留 NEL 行尾吗?通常没有人关心行尾,这些都是假的。)
因为我通常不需要不可读字符,所以在将 XML 字符串保存到 Db2 之前,我决定从 x'c285(代码点 133)和 4 字节 UTF-8 字符实现干净的字符串,仅用于案例:
找到类似的例子(How to replace/remove 4(+)-byte characters from a UTF-8 string in Java?)并进行了调整。
public static final String LAST_3_BYTE_UTF_CHAR = "\uFFFF";
public static final String REPLACEMENT_CHAR = "\uFFFD";
public static String toValid3ByteUTF8String(String line) {
final int length = line.length();
StringBuilder b = new StringBuilder(length);
for (int offset = 0; offset < length; ) {
final int codepoint = line.codePointAt(offset);
// do something with the codepoint
if (codepoint > LAST_3_BYTE_UTF_CHAR.codePointAt(0)) { //4-byte UTF replace
b.append(REPLACEMENT_CHAR);
} else if( codepoint == 133){ //NEL or x'c285
b.append(REPLACEMENT_CHAR);
} else {
if (Character.isValidCodePoint(codepoint)) {
b.appendCodePoint(codepoint);
} else {
b.append(REPLACEMENT_CHAR);
}
}
offset += Character.charCount(codepoint);
}
return b.toString();
}