фильтровать / удалять недопустимые символы XML из потока - PullRequest
2 голосов
/ 09 июля 2010

Перво-наперво, я не могу изменить вывод xml, он производится третьей стороной. Они вставляют недопустимые символы в XML. Мне дают InputStream представления потока байтов xml. Являются ли они более чистым способом отфильтровывать оскорбительные символы, кроме потребления потока в строку и его обработки? Я нашел это: с использованием 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&#x01;
</foo>

1 Ответ

1 голос
/ 10 июля 2010

Чтобы сделать это с фильтром, фильтр должен учитывать сущность XML, потому что (по крайней мере в вашем примере и, вероятно, иногда при фактическом использовании) недопустимые символы присутствуют в XML как сущности.

Фильтр видит вашу сущность как последовательность из 6 совершенно приемлемых символов и, следовательно, не удаляет их.

Преобразование, которое нарушает JAXB, происходит позже в процессе.

...