星期五, 3月 29, 2013

XMLBeans 使用經驗紀錄

最近因為客戶要求 OXM (Object/XML Mapping) 必需使用 XMLBeans 2.5。

在此紀錄其與 JAXB 之差異點:
1. JAXB 在輸出 Big5 XML 時,若遇到非 Big5 編碼,會轉為 Unicode 編碼,如菓 --> 菓 而 XMLBeans 碰到這情況會直接輸出 ?

2. 雖然 XSD 定義中指出要使用 default namespace 的方式,但輸出時卻輸出有 prefix 之 Tag 模式。
   解決方式為輸出前需設定 XmlOptions 之 setUseDefaultNamespace();

3. 字串會自動判斷是否轉 CDATA,這是什麼意思呢?
我們知道 XML 內的 Tag 內容若有特殊符號,例如 Tag 內容為 <b>ABC</b>,需以CDATA包起來。
  <Root>
    <Body><![CDATA[<b>ABC</b>]]></Body>
  </Root>

或是將特殊符號進行 escape,如下:
  <Root>
    <Body>&lt;b&gt;ABC&lt;/b&gt;</Body>
  </Root>

也就是說,上面兩份 XML 基本上是相等的,只差在可讀性。

而我們透過 XMLBeans 的 Java 物件轉換為 XML 時。
發現,當這類需要 escape 的字元超過 5 個。則輸出會變成 CDATA 模式。若沒超過 5 個,則為 escape 模式。

由於使用不同模式會造成後續程式處理有誤。因此得查出此問題的發生原因。
最後追到 XMLBeans 之 API 說明。

原來 XmlOptions 有兩組參數:CDataLengthThreshold 與 CDataEntityCountThreshold 預設值分別為 32 與 5。
其轉換邏輯為當資料長度大於 CDataLengthThreshold 且 跳脫字元數量超過 CDataEntityCountThreshold 時會轉換為 CDATA 模式。

而我們希望的是,一律使用 escape 模式,在追了 XmlBeans source code 之後,很可惜的是,除了可以使用 XmlOptions.useCDataBookmarks() 來強迫使用 CDATA 模式外,並無設定一律使用 escape 的方法,且這兩個參數也不得設為 -1, 0 來表示無限制。所以只能將這兩個參數設大一點以避免問題。