2010-07-09 27 views
2

首先,我无法更改xml的输出,它由第三方生成。他们在XML中插入无效字符。我得到了xml的字节流表示的InputStream。除了将字符串消费到字符串并处理它之外,他们是否更清楚地筛选出违规字符?我发现这个:using a FilterReader但这并不适用于我,因为我有一个字节流,而不是一个字符流。过滤/从流中删除无效的xml字符

为什么它值得这是一个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> 
+2

你确定*他们*插入无效字符吗?是不是你正在使用错误的编码读取二进制流中的字符和/或使用错误的编码显示读取的字符? – BalusC 2010-07-09 18:58:01

+0

你应该检查BalusC的评论。如果您仍然想继续使用FilteredReader实现,那么在将字节流转换为阅读器(使用InputStreamReader)的情况下,只要知道字节流的文本编码就没有问题。 – 2010-07-09 19:23:54

+0

我不知道BalusC在做什么。他们是公然无效的XML 1.0字符。我尝试使用InputStreamReader(以及将其包装在缓冲读取器中),但没有运气。我会用代码更新我的问题。 – DanInDC 2010-07-09 20:43:00

回答

1

为了过滤,以做到这一点,过滤器需要能够识别XML实体,因为坏字符(至少在你的例子中,有时可能在实际使用中) xml作为实体。

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

打破JAXB的转换过程稍后会发生。

+0

没错。所以有关于实体感知过滤器的任何想法?或者,我是唯一的选择,只是将它吸入缓冲区,并使用.replaceAll()这个废话呢? – DanInDC 2010-07-12 13:44:44

+0

我确定我已经看过一个FilterReader代码的例子,可以通过正则表达式进行过滤。目前不能把它放在手上,但谷歌可能会找到一些东西。 它基本上等于“将它吸入缓冲区并将.replaceAll()放在它的外面”,但在过滤器代码中。 – 2010-07-12 14:23:36