我正在使用SaxParser解析我的android应用程序中有近90000个字符的xml响应。 xml如下所示:
<Registration>
<Client>
<Name>John</Name>
<ID>1</ID>
<Date>2013:08:22T03:43:44</Date>
</Client>
<Client>
<Name>James</Name>
<ID>2</ID>
<Date>2013:08:23T16:28:00</Date>
</Client>
<Client>
<Name>Eric</Name>
<ID>3</ID>
<Date>2013:08:23T19:04:15</Date>
</Client>
.....
</Registration>
有时解析器会错过Date标记中的某些字符。而不是给予2013:08:23T19:04:15,而不是2013:08:23T。我尝试使用以下代码行跳过响应xml字符串中的所有空格:
responseStr = responseStr.replaceAll("\\s","");
然后我得到以下例外:
Parsing exception: org.apache.harmony.xml.ExpatParser$ParseException: At line 1, column 16: not well-formed (invalid token)
以下是我用于解析的代码:
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
DefaultHandler handler = new DefaultHandler() {
public void startElement(String uri, String localName,String qName, Attributes attributes) throws SAXException {
tagName = qName;
}
public void endElement(String uri, String localName, String qName) throws SAXException {
}
public void characters(char ch[], int start, int length) throws SAXException {
if(tagName.equals("Name")){
obj = new RegisteredUser();
String str = new String(ch, start, length);
obj.setName(str);
}else if(tagName.equals("ID")){
String str = new String(ch, start, length);
obj.setId(str);
}else if(tagName.equals("Date")){
String str = new String(ch, start, length);
obj.setDate(str);
users.add(obj);
}
}
public void startDocument() throws SAXException {
System.out.println("document started");
}
public void endDocument() throws SAXException {
System.out.println("document ended");
}
};
saxParser.parse(new InputSource(new StringReader(resp)), handler);
}catch(Exception e){
System.out.println("Parsing exception: "+e);
System.out.println("exception");
}
任何想法为什么解析器会从标记中跳过字符,我该如何解决这个问题。提前谢谢。
答案 0 :(得分:9)
对于任何给定的文本节点,characters
可能会被多次调用。
在这种情况下,你必须自己连接结果!
这样做的原因是当解析器的某个内部缓冲区结束时,仍然存在文本节点的内容。它不是放大缓冲区(当文本节点很大时可能需要很多内存),而是由客户端代码处理。
你想要这样的东西:
StringBuilder textContent = new StringBuilder();
public void startElement(String uri, String localName,String qName, Attributes attributes) throws SAXException {
tagName = qName;
textContent.setLength(0);
}
public void characters(char ch[], int start, int length) throws SAXException {
textContent.append(ch, start, length);
}
public void endElement(String uri, String localName, String qName) throws SAXException {
String text = textContent.toString();
// handle text here
}
当然,可以改进此代码,仅跟踪您真正关心的节点的文本内容。
答案 1 :(得分:2)
由于其他提到的characters
方法可能被多次调用,因此它可以在SAX解析器实现中返回所有contiguous character data in a single chunk, or they may split it into several chunks
。
请参阅文档SAX Parser characters
答案 2 :(得分:1)
您错误地认为文本节点中的所有字符都会立即被读取并发送到characters()
方法。事实并非如此。对于单个文本节点,可以多次调用characters()
方法。
您应该将所有字符附加到StringBuilder,然后仅在调用endElement()
时转换为字符串或日期。