我正在做一个解析XML中的一些数据的项目。
例如,XML是
<abc>abcdefghijklmno</abc>
我需要解析“abcdefghijkmnlp”。
但是当我测试我的解析时,我发现了一个大问题:
public class parser{
private boolean hasABC = false;
//Constructor HERE
......................
......................
@Override
public void startDocument () throws SAXException{
}
@Override
public void endDocument () throws SAXException{
}
@Override
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException{
if ("abc".equalsIgnoreCase(localName)) {
this.hasABC = true;
}
}
@Override
public void endElement(String namespaceURI, String localName, String qName) throws SAXException{
if ("abc".equalsIgnoreCase(localName)) {
this.hasABC = false;
}
}
@Override
public void characters(char ch[], int start, int length){
String content = new String(ch, start, length).trim();
if(this.hasABC){
System.out.println("ABC = " + content);
}
}
}
我发现解析器已经解析了两次标记 系统打印输出是,
ABC = abcdefghi
ABC = jklmno&lt;&lt; ============拆分邮件
为什么解析器会自动回调两次字符()????
XML是否有一些“\ n”或“\ r”???
答案 0 :(得分:35)
Parser多次调用characters
方法,因为它可以并且允许每个规范。这有助于快速解析并保持较低的内存占用。如果您想要一个字符串,请在StringBuilder
中创建一个新的startElement
对象,并在endElement
方法上对其进行处理。
答案 1 :(得分:8)
您会感到惊讶,但这是一个记录在案的行为,即您不能假设解析器将读取并返回单个回调中元素的所有文本数据。我之前有过相同的经历。您需要编码来处理这种情况,或者您可以切换到Stax parser。您可以使用CharArrayWriter在多个回调中累积数据。
请参阅下面的JavaDoc of ContentHandler.characters(...)
Parser会调用此方法 报告每个字符数据块。 SAX解析器可能会返回所有连续的 单个块中的字符数据,或 他们可能将它分成几个块; 但是,任何人物中的所有人物 单一事件必须来自同一事件 外部实体使定位器 提供有用的信息。
答案 2 :(得分:5)
您可以更改开始,结束和字符方法,如:
在字符方法中你可以制作if / else:
if (content == null)
{
content = new String(ch, start, length);
} else {
content += new String(ch, start, length);
}
野蛮的方式(最好用stringbuilder完成)但是工作和“字符串”不再分裂。
答案 3 :(得分:3)
这是SAX的一项功能。解析器可以拆分文本段并根据需要多次调用characters
方法。
其原因在于性能,SAX优先于易用性。 SAX可能已经用完了它的内部缓冲区,所以为了避免复制它,它会将它到目前为止的数据传递给你的代码。