2008-09-18 327 views
27

我有一個XML文件,它是數據庫的輸出。我正在使用Java SAX解析器來解析XML並以不同的格式輸出它。 XML包含一些無效字符,並且解析器拋出錯誤,如'Unicode字符無效(0x5)'剝離Java中的無效XML字符

除了預先處理文件並將其替換之外,是否有一種很好的方法可以去除所有這些字符?到目前爲止,我已經遇到了3個不同的無效字符(0x5,0x6和0x7)。這是一個大約4GB的數據庫轉儲,我們將要處理它很多次,所以每次我們得到一個新的轉儲以運行預處理器時,必須等待額外的30分鐘,這將是一個痛苦,這不是我第一次遇到這個問題。

+2

執行角色有什麼意義呢?想必他們不是隨機的腐敗,所以不剝奪他們消除信息? – 2008-09-18 17:32:15

+0

如果文件包含無效字符,則不是XML文件。請求它的創建者將來只創建格式良好的XML。過去我遇到過這個問題。人們似乎並不瞭解XML需要格式良好並且不包含垃圾。 – MarkR 2008-09-18 15:39:19

+0

我同意100%不幸的是,這並不總是可能的(無能的技術人員,合同措詞等) – Mason 2008-09-18 15:41:21

回答

9

我沒有使用過這種私人所有,而是由Atlassian的可能滿足您的需求(這是由主要的JIRA但XML是XML)命令行XML清潔:

下載atlassian-xml-cleaner-0.1.jar

開放一個DOS控制檯或shell,並找到您的計算機上的XML或ZIP備份文件,這裏假定被稱爲data.xml

運行: java -jar atlassian-xml-cleaner-0.1.jar data.xml> data -clean.xml

這會將data.xml的副本寫入data-clean.xml,並刪除無效字符。

0

是否有可能您的無效字符僅存在於值中,而不是標籤本身,即XML在概念上符合模式,但值未被正確消毒?如果是這樣,那麼重寫InputStream來創建一個CleansingInputStream來替換無效字符和它們的XML等價物呢?

0

您的問題不涉及XML:它涉及字符編碼。最重要的是每個字符串,不論是XML還是其他字符串,都由字節組成,並且不知道這些字節代表什麼字符,除非告訴您字符串具有什麼字符編碼。例如,如果供應商告訴你它是UTF-8,而且它實際上是其他的東西,你肯定會遇到問題。在最好的情況下,一切正常,但有些字節被轉換成'錯誤'的字符。在最糟糕的情況下,你會遇到類似你遇到的錯誤。

實際上,你的問題更糟糕:你的字符串包含的字節序列不能代表任何字符編碼中的字符。沒有文本處理工具,更不用說XML解析器,它可以幫助你。這需要字節級清理。

6

我用下面的正則表達式,這似乎是預期的JDK6工作:

Pattern INVALID_XML_CHARS = Pattern.compile("[^\\u0009\\u000A\\u000D\\u0020-\\uD7FF\\uE000-\\uFFFD\uD800\uDC00-\uDBFF\uDFFF]"); 
... 
INVALID_XML_CHARS.matcher(stringToCleanup).replaceAll(""); 

在JDK7有可能使用的符號\x{10000}-\x{10FFFF}爲位於BMP之外,而不是最後的範圍\uD800\uDC00-\uDBFF\uDFFF表示法不容易理解。

3

將澳大利亞出口關稅的內容解析爲XML文檔時,我有類似的問題。我不能使用此處建議的解決方案,例如: - 使用從命令行調用的外部工具(jar)。 - 要求澳大利亞海關清理源文件。

目前解決此問題的唯一方法是逐個字符遍歷源文件的整個內容,並測試每個字符是否不屬於ascii範圍0x00至0x1F(包含性)。它可以完成,但我想知道是否有更好的方法使用類型爲String的Java方法。

編輯 我找到了一個對其他人有用的解決方案:使用Java方法String#ReplaceAll替換或刪除XML文檔中的任何不需要的字符。

實施例的代碼(I去掉了一些必要的語句以避免混亂):

BufferedReader reader = null; 
... 
String line = reader.readLine().replaceAll("[\\x00-\\x1F]", ""); 

在這個例子中我刪除(即,具有一個空字符串替換),內範圍爲0x00不可打印的字符爲0x1F包含性。您可以更改方法#replaceAll()中的第二個參數,以將字符替換爲您的應用程序所需的字符串。

20

我用的Xalan org.apache.xml.utils.XMLChar類:

public static String stripInvalidXmlCharacters(String input) { 
    StringBuilder sb = new StringBuilder(); 
    for (int i = 0; i < input.length(); i++) { 
     char c = input.charAt(i); 
     if (XMLChar.isValid(c)) { 
      sb.append(c); 
     } 
    } 

    return sb.toString(); 
}