まず最初に、xmlの出力を変更することはできません。これはサードパーティによって生成されています。xmlに無効な文字を挿入しています。xmlのバイトストリーム表現のInputStreamが与えられます。ストリームを文字列に消費して処理する以外に、問題のある文字を除外するためのよりクリーンな方法ですか?私はこれを見つけました:FilterReaderを使用していますが、文字ストリームではなくバイトストリームがあるため、これは機能しません。
オプションを提供する場合に備えて、これはすべてjaxbアンマーシャリング手順の一部です。
キャラクターが悪い場合は、ストリーム全体を投げるつもりはありません。それらを削除して続行することにしました。
これが私が作成しようとしたFilterReaderです。
public class InvalidXMLCharacterFilterReader extends FilterReader {
private static final Log LOG = LogFactory
.getLog(InvalidXMLCharacterFilterReader.class);
public InvalidXMLCharacterFilterReader(Reader in) {
super(in);
}
public int read() throws IOException {
char[] buf = new char[1];
int result = read(buf, 0, 1);
if (result == -1)
return -1;
else
return (int) buf[0];
}
public int read(char[] buf, int from, int len) throws IOException {
int count = 0;
while (count == 0) {
count = in.read(buf, from, len);
if (count == -1)
return -1;
int last = from;
for (int i = from; i < from + count; i++) {
LOG.debug("" + (char)buf[i]);
if(!isBadXMLChar(buf[i])) {
buf[last++] = buf[i];
}
}
count = last - from;
}
return count;
}
private boolean isBadXMLChar(char c) {
if ((c == 0x9) ||
(c == 0xA) ||
(c == 0xD) ||
((c >= 0x20) && (c <= 0xD7FF)) ||
((c >= 0xE000) && (c <= 0xFFFD)) ||
((c >= 0x10000) && (c <= 0x10FFFF))) {
return false;
}
return true;
}
}
そして、これが私がそれをアンマーシャリングする方法です:
jaxbContext = JAXBContext.newInstance(MyObj.class);
Unmarshaller unMarshaller = jaxbContext.createUnmarshaller();
Reader r = new InvalidXMLCharacterFilterReader(new BufferedReader(new InputStreamReader(is, "UTF-8")));
MyObj obj = (MyObj) unMarshaller.unmarshal(r);
といくつかの例の悪いxml
<?xml version="1.0" encoding="UTF-8" ?>
<foo>
bar
</foo>