2016-06-10 45 views
0

在表中保存編碼到DB2 9.7 LUW的XML數據(UTF-8)時出現問題。將DB2 UTF-8 XML C2 85轉換爲新行轉換

表DDL:發生與稀有Unicode字符一些罕見例子

CREATE TABLE DB2ADMIN.TABLE_FOR_XML 
( 
    ID   INTEGER NOT NULL, 
    XML_FIELD  XML NOT NULL 
) 

問題,我們用java JDBC DB2驅動程序。

例如尋找在正常模式下的編輯器不以十六進制視圖(記事本++)低於該奇怪A(16)之後在黑正方形表示爲NEL

輸入XML是UTF-8編碼看去時在HEX編輯具有此值:

00000010h: 31 36 2E 20 C2 85 42       ; 16. Â…B 

在DB2中插入後,我假定某種轉換的發生是因爲選擇數據時回這個相同的字符現在

00000010h: 31 36 2E 20 0D 0A 42       ; 16. ..B 

C2 85被轉換成新行的0D 0A。

彼此件事我注意到,保存XML到表頭內容時,雖然已開始與 <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內容1,XMLSERIALIZE(XML_FIELD爲CLOB(1M))AS內容2從DB2ADMIN.TABLE_FOR_XML

IN內容2沒有XML頭,但窗框換行符是存在的。

回答

1

此行爲是XML 1.1處理器的標準配置。 XML 1.1 s2.11

XML處理器必須表現得好像它在歸一外部解析實體(包括文件實體)上輸入所有換行符,解析之前,通過平移[單個字符#X85]到單個#xA字符

行終止類型是文檔的許多細節之一,它將在分析和序列化循環中丟失(例如,屬性順序,標記中的空白,數字字符引用...)。

DB2的XML字段使用XML 1.1有點令人驚訝,因爲沒有太多使用該XML修訂版,但對NEL(古老的,無用的大型機行結束字符)的支持並不出乎意料,這只是IBM想要的。

是否有辦法強制db2以UTF-8格式存儲XML而無需轉換?

使用BLOB?

如果您需要原生XML字段功能來保留文檔的原始序列化形式,那麼您需要兩列。

(您肯定需要保留NEL行尾?沒人通常關心的行結束了,這些都是非常假。)

+0

沒有我cloudnt不在乎結束它們在某些輸入XML錯誤的產品,NEL線,我怎麼能幹淨XML在Java中從該C2 85? – Levijatanu

+0

'xmlString = xmlString.replace(「\ u0085」,「\ r \ n」);'會做。換行NEL字符源於EBCDIC編碼,該編碼仍然用於某些IBM大型機(如AS/400)。 '\ u0085'以UTF-8編碼爲這兩個字節。 –

0

正如我通常不需要非可讀字符,保存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(); 
}