NioSax (pronounced ‘Neo-Sax’) provides a Java NIO friendly XML push parser similar in operation to SAX. Unlike SAX, with NioSax it is possible for the xml source to contain partial content (i.e. only part of the XML stream has been received over the network). When this occurs, instead of failing with an error, NioSax simply stops. As soon as your application receives more data you simply call the same instance of the parser again and it will resume parsing where it left off.
The public API consists of the classes within this package, although the bare minimum required for use are the NioSaxParser, NioSaxParserHandler and NioSaxSource classes.
To use NioSax you simply use NioSaxParserFactory to create a NioSaxParser, implement a SAX ContentHandler and finally create a NioSaxSource which references the content.
Then you can parse one or more ByteBuffer’s by updating the NioSaxSource with each buffer and pass it to the NioSaxParser.parse(NioSaxSource) method.
The only other two things you must to do with the parser is to ensure that you call NioSaxParser.startDocument() prior to any parsing, and call NioSaxParser.endDocument() once you are done with the parser so any resources used can be cleaned up.
Example
First in maven we need to add a dependency to NioSax. For details of the repository click on the ‘reteptools’ menu above. However you’ll need to add the following to your pom:
<dependency> <groupId>uk.org.retep</groupId> <artifactId>niosax</artifactId> <version>10.6</version> </dependency>
Now we’ll create a parser:
import java.nio.ByteBuffer; import uk.org.retep.niosax.NioSaxParser; import uk.org.retep.niosax.NioSaxParserFactory; import uk.org.retep.niosax.NioSaxParserHandler; import uk.org.retep.niosax.NioSaxSource; public class MyParser { private NioSaxParser parser; private NioSaxParserHandler handler; private NioSaxSource source; public void start() { NioSaxParserFactory factory = NioSaxParserFactory.getInstance(); parser = factory.newInstance(); parser.setHandler( handler ); source = new NioSaxSource(); parser.startDocument(); } }
Next, when you receive data from some nio source and have the data in a ByteBuffer you need to pass it to the parser:
public void parse( ByteBuffer buffer ) { // flip the buffer so the parser starts at the beginning buffer.flip(); // update the source (presuming the buffer has changed) source.setByteBuffer( buffer ); // Parse the available content then compact parser.parse( source ); source.compact(); }
Finally we must call endDocument() to release any resources:
public void close() { // releases any resources and notifies the handler the docment has completed parser.endDocument(); }
Now all we need to is when we receive some data from an external source like a Socket, we pass the ByteBuffer to the parse method. This then passes it to the NioSax parser which in turn calls the ContentHandler as the parse progresses.
When it gets to the end of the available content, it compacts the buffer so that it can be reused.
Usually the buffer will now be empty, however if there was partial content (like only part of a Unicode character was present) then the parser would stop prior to that character and that character would remain in the buffer. The next packet received via nio would have the rest of that character and the parser would then continue where it left off.
This was originally posted early in 2009 but the post seemed to have vanished so this article is loosely based on the documentation for NioSax.