データベースからの出力であるXMLファイルがあります。 Java SAXパーサーを使用してXMLを解析し、別の形式で出力しています。XMLに無効な文字が含まれており、パーサーが「無効なUnicode文字(0x5)」のようなエラーをスローしています
ファイルを行ごとに前処理してそれらを置き換える以外に、これらすべての文字を取り除く良い方法はありますか?これまでのところ、3つの異なる無効な文字(0x5、0x6、0x7)に遭遇しました。これは〜4GBのデータベースダンプであり、大量の処理を行うため、プリプロセッサを実行するために新しいダンプを取得するたびにさらに30分待たなければならないのは面倒です。私がこの問題に遭遇したのはこれが初めてではありません。
私はこれを個人的に使用していませんが、アトラシアンはあなたのニーズに合ったコマンドラインXMLクリーナーを作成しました(主にJIRA用に作成されましたが、XMLはXMLです)。
ダウンロード atlassian-xml-cleaner-0.1.jar
DOSコンソールまたはシェルを開き、コンピューター上でXMLまたはZipバックアップファイルを見つけます。ここではdata.xmlと呼ばれます。
実行:Java -jar atlassian-xml-cleaner-0.1.jar data.xml> data-clean.xml
これにより、無効な文字が削除されたdata.xmlのコピーがdata-clean.xmlに書き込まれます。
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();
}
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
_表記を使用することが可能かもしれません。
オーストラリアの輸出関税の内容をXMLドキュメントに解析するときにも同様の問題があります。次のような解決策は使用できません。-コマンドラインから呼び出される外部ツール(jar)を使用します。 -オーストラリアの税関にソースファイルのクリーンアップを依頼します。
現時点でこの問題を解決する唯一の方法は、ソースファイルのコンテンツ全体を1文字ずつ繰り返し、各文字が0x00〜0x1Fの範囲のASCIIに属していないかどうかをテストすることです。できますが、Java String型のメソッドを使用するより良い方法があるかどうか疑問に思っていました。
編集他の人に役立つ可能性のある解決策を見つけました:Java method String#ReplaceAllを使用して、XMLドキュメント内の不要な文字を置換または削除します。
コード例(混乱を避けるために必要なステートメントをいくつか削除しました):
BufferedReader reader = null;
...
String line = reader.readLine().replaceAll("[\\x00-\\x1F]", "");
この例では、0x00から0x1Fまでの範囲内にある印刷できない文字を削除します(つまり、空の文字列に置き換えます)。 #replaceAll()メソッドの2番目の引数を変更して、アプリケーションで必要な文字列で文字を置き換えることができます。
無効な文字が値自体にのみ存在し、タグ自体には存在しない可能性があります。つまり、XMLは概念的にスキーマを満たしていますが、値は適切にサニタイズされていませんか?もしそうなら、無効な文字を同等のXMLで置き換えるCleansingInputStreamを作成するためにInputStreamをオーバーライドするのはどうですか?
あなたの問題はXMLに関するものではなく、文字エンコーディングに関するものです。つまり、XMLなどのすべての文字列はバイトで構成されており、文字列の文字エンコーディングを教えられない限り、これらのバイトが表す文字を知ることはできません。たとえば、サプライヤからUTF-8であり、それが実際には別のものであると言われた場合、問題が発生する可能性があります。最良のケースでは、すべてが機能しますが、一部のバイトは「間違った」文字に変換されます。最悪の場合、発生したようなエラーが発生します。
実際には、問題はさらに悪化します。文字列には、どの文字エンコーディングの文字も表さないバイトシーケンスが含まれています。ここで役立つXMLパーサーはもちろん、テキスト処理ツールはありません。これにはバイトレベルのクリーンアップが必要です。