从流中过滤/删除无效的xml字符

时间:2010-07-09 18:30:39

标签: java xml filter jaxb invalid-characters

首先,我无法改变xml的输出,它是由第三方生成的。他们在xml中插入无效字符。我得到了一个xml字节流表示的InputStream。除了将流消费到字符串并处理它之外,它们是否更清晰地过滤掉有问题的字符?我发现了这个:using a 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 个答案:

答案 0 :(得分:1)

为了使用过滤器执行此操作,过滤器需要支持XML实体,因为(至少在您的示例中,有时可能在实际使用中),错误的字符在xml中作为实体。

过滤器将您的实体视为6个完全可接受的字符的序列,因此不会剥离它们。

在此过程的后期发生了破坏JAXB的转换。