Sax解析和编码

6
我有一个联系人在解析RSS和Atom文件时遇到了SAX的问题。据他说,似乎来自Item元素的文本在撇号或者有重音符号的字符处被截断了。这似乎也与编码有关。
我尝试使用SAX,也发现了一些截断的情况,但是没有深入研究。如果有人曾经解决过这个问题,我会非常感激一些建议。
以下是ContentHandler中使用的代码:
public void characters( char[], int start, int end ) throws SAXException {
//
    link = new String(ch, start, end);

编辑:编码问题可能是由于将信息存储在字节数组中,因为我知道Java使用Unicode。

3个回答

13

characters()方法不能保证一次性给出文本元素的完整字符内容 - 完整的文本可能跨越缓冲区界限。在开始和结束元素事件之间,您需要自己缓冲字符。

例如:

StringBuilder builder;

public void startElement(String uri, String localName, String qName, Attributes atts) {
   builder = new StringBuilder();
}

public void characters(char[] ch, int start, int length) {
   builder.append(ch,start,length);
}

public void endElement(String uri, String localName, String qName) {
  String theFullText = builder.toString();
}

StringBuilder的追加操作不应该同步吗?或者使用StringBuffer? - ruchirhhi
不需要同步 - SAX解析是单线程的,通常每个被解析的文档都会使用一个单独的ContentHandler。如果您想要重用ContentHandlers,最好使用ThreadLocal或其他池机制 - 编写一个能够同时处理多个解析流的ContentHandler非常困难,因为它如何跟踪哪个事件来自哪个文档? - Alex Vigdor
我使用了它,但它没有工作。SAX解析器在此符号后未读取文本。 - Ashish Mishra

5

XML实体会在SAX中产生特殊事件。您可以使用LexicalHandler捕获它们,尽管通常不是必需的。但这解释了为什么不能假设您将仅收到每个标记一个字符事件。请像其他答案中所述使用缓冲区。

例如,hello&world将生成以下序列

  • startElement
  • characters hello
  • startEntity
  • characters &
  • endEntity
  • characters world

如果您需要更多示例,请查看辅助SAX接口。其他特殊事件包括外部实体、注释、CDATA等。


1
你是如何将输入传递给SAX的?使用InputStream(推荐)还是Reader?因此,从你的byte[]开始,尝试使用ByteArrayInputStream

Egon,我已经查看了Channel类,并使用XMLReader。设置ContentHandler,然后调用parse()方法。大概就是这样。 - James P.
你可以看一下我的代码:http://cdk.git.sourceforge.net/git/gitweb.cgi?p=cdk/cdk;a=blob;f=src/main/org/openscience/cdk/io/CMLReader.java;h=490743955939b8a003c95769c3261b06eb341842;hb=HEAD - Egon Willighagen
顺便问一下,你在用哪个XML解析器?我刚刚链接的代码允许使用三种不同的XML解析器,默认使用随Java版本更新的那个,然后是Aelfred,最后是Xerces。 - Egon Willighagen
抱歉回复有些晚了。我看了一下你的代码,似乎正在使用默认解析器。 - James P.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接