I am doing a project to parse some data from the XML.
For example, the XML is
<abc>abcdefghijklmno</abc>
I need to parse "abcdefghijkmnlp".
But while I test my parse, I discover a big problem:
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);
}
}
}
I discover that the parser has parsed the tag two time System print out is,
ABC = abcdefghi
ABC = jklmno <<============ split the message
Why the parser auto call back the characters() two time????
Is the XML haveing some "\n" or "\r" ???
Parser is calling characters
method more than one time, because it can and allowed per spec. This helps fast parser and keep their memory footprint low. If you want a single string create a new StringBuilder
object in the startElement
and process it on endElement
method.
You will be surprised but this is a documented behavior i.e. you can't assume that the parser will read and return all the text-data of an element in a single callback. I had the same experience earlier. You need to code to handle this situation or you can switch to Stax parser. You can use CharArrayWriter to accumulate the data across multiple callbacks.
See below from the JavaDoc of ContentHandler.characters(...)
The Parser will call this method to report each chunk of character data. SAX parsers may return all contiguous character data in a single chunk, or they may split it into several chunks; however, all of the characters in any single event must come from the same external entity so that the Locator provides useful information.
You can change start, end and character method like:
in character method u can make if/else:
if (content == null)
{
content = new String(ch, start, length);
} else {
content += new String(ch, start, length);
}
Brutal way (better to do it with stringbuilder) but works and "string" is not longer splitted.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With