【问题标题】:How should I strip invalid XML characters from a stream in J2ME? org.xml.sax.SAXParseException: Invalid character我应该如何从 J2ME 中的流中去除无效的 XML 字符? org.xml.sax.SAXParseException:无效字符
【发布时间】:2012-04-07 22:57:22
【问题描述】:

此代码在 Blackberry JDE v4.2.1 上运行,它采用一种方法,可以进行返回 XML 的 Web API 调用。有时,返回的 XML 格式不正确,我需要在解析之前去除所有无效字符。

目前,我得到:org.xml.sax.SAXParseException: Invalid character '' encountered

我希望看到一种在输入流上附加无效字符剥离器的快速方法的想法,以便流只流经验证器/剥离器并进入解析调用。即我试图避免保存流的内容。

现有代码:

handlerDefaultHandler 的覆盖
url 是包含 API URL

的字符串
hconn = (HttpConnection) Connector.open(url,Connector.READ_WRITE,true);

...

try{
   XMLParser parser = new XMLParser();
   InputStream input = hconn.openInputStream();
   parser.parse(input, handler);
   input.close();
} catch (SAXException e) {
   Logger.getInstance().error("getViaHTTP() - SAXException - "+e.toString());
}

【问题讨论】:

    标签: xml blackberry java-me sax rim-4.2


    【解决方案1】:

    很难在 InputStream 上附加剥离器,因为流是面向字节的。在Reader 上执行此操作可能更有意义。您可以制作类似于 StripReader 的东西来包装另一个阅读器并处理错误。下面是一个快速的、未经测试的概念证明:

    public class StripReader extends Reader
    {
        private Reader in;
        public StripReader(Reader in)
        {
        this.in = in;
        }
    
        public boolean markSupported()
        {
        return false;
        }
    
        public void mark(int readLimit)
        {
        throw new UnsupportedOperationException("Mark not supported");
        }
    
        public void reset()
        {
        throw new UnsupportedOperationException("Reset not supported");
        }
    
        public int read() throws IOException
        {
        int next;
        do
        {
            next = in.read();
        } while(!(next == -1 || Character.isValidCodePoint(next)));
    
        return next; 
        }
    
        public void close() throws IOException
        {
        in.close();
        }
    
        public int read(char[] cbuf, int off, int len) throws IOException
        {
        int i, next = 0;
        for(i = 0; i < len; i++)
        {
            next = read();
            if(next == -1)
            break;
            cbuf[off + i] = (char)next;
        }
        if(i == 0 && next == -1)
            return -1;
        else
            return i;
        }
    
        public int read(char[] cbuf) throws IOException
        {
        return read(cbuf, 0, cbuf.length);
        }
    }
    

    然后,您将从 Reader 构造一个 InputSource,然后使用 InputSource 进行解析。

    【讨论】:

    • 由于黑莓显然也没有FilterReader,所以我修改了上面的不使用它。
    • RIM 也不包括 Character.isValidCodePoint() 我不得不自己动手。但是,这种方法似乎确实有效 - 至少在模拟器上。希望它也能在真实设备上保持稳定并且不会太慢。谢谢!
    • 不客气。一定要好好测试。由于必须(重新)检查每个字符,因此不可避免地会减慢速度。但是,我不认为我在做任何不必要的复制。附:我很好奇你是如何实现 isValidCodePoint 的。
    • 它不会在这个 cmets 块中很好地显示出来,但这是我用来验证 XML 字符的方法: private boolean isValidXMLChar(int ch) { if ((ch == 0x9) || (ch == 0xA) || (ch == 0xD) || ((ch >= 0x20) && (ch = 0xE000) && (ch = 0x10000) && (ch
    【解决方案2】:

    使用FilterInputStream。覆盖 FilterInputStream#read 以过滤违规字节。

    【讨论】:

    • 问题是需要在流中复制字符解码逻辑。
    • 如果不自定义 XMLParser,可能没有办法避免这种情况?
    • 为什么不只在出现 SAXException 时才使用自定义的 XMLParser?看起来如果你得到一个错误的 xml 文件,那么最好拒绝整个文件,因为损坏的部分可能会导致提取错误的数据。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-29
    • 2011-03-14
    • 2013-09-13
    • 2018-04-29
    • 2011-05-13
    • 1970-01-01
    相关资源
    最近更新 更多