SAX (Simple API for XML) is an event-based model for processing XML streams,
defined in the org.xml.sax
package.
While generally a bit more effort to use than DOM, it provides
more flexibility and possibilities for efficiency,
since you can decide what to do with each element rather than
always store it in memory. Although a DOM built using the
mechanism described in the previous section
will usually itself be pretty small, it will normally have to store
table data somewhere in memory or on disk, so if you don't need,
and wish to avoid, this overhead, you'd better use event-based processing
directly. This section describes how to do that.
The basic tool to use for VOTable-aware SAX-based processing is a
TableContentHandler
,
which is a SAX ContentHandler
implementation
that monitors all the SAX events and when it comes across a
TABLE element containing DATA
it passes SAX-like messages to a user-supplied
TableHandler
which can do
what it likes with them.
TableHandler
is a callback interface for dealing with
table metadata and data events defined by STIL in the spirit of the
existing SAX callback interfaces such as ContentHandler
,
LexicalHandler
etc. You define a TableHandler
by implementing the methods
startTable
,
rowData
and
endTable
.
For full details of how to use this, see the appropriate javadocs, but here is a simple example which counts the rows in each TABLE in a VOTable stream.
import javax.xml.parsers.SAXParserFactory; import org.xml.sax.ContentHandler; import org.xml.sax.InputSource; import org.xml.sax.XMLReader; import uk.ac.starlink.table.StarTable; import uk.ac.starlink.votable.TableContentHandler; import uk.ac.starlink.votable.TableHandler;
void summariseVotableDocument( InputStream in ) throws Exception { // Set up a handler which responds to TABLE-triggered events in // a suitable way. TableHandler tableHandler = new TableHandler() { long rowCount; // Number of rows seen in this table. // Start of table: print out the table name. public void startTable( StarTable meta ) { rowCount = 0; System.out.println( "Table: " + meta.getName() ); } // New row: increment the running total of rows in this table. public void rowData( Object[] row ) { rowCount++; } // End of table: print out the summary. public void endTable() { System.out.println( rowCount + " rows" ); } }; // Install it into a TableContentHandler ready for use. TableContentHandler votContentHandler = new TableContentHandler( true ); votContentHandler.setTableHandler( tableHandler ); // Get a SAX parser in the usual way. XMLReader parser = SAXParserFactory.newInstance().newSAXParser() .getXMLReader(); // Install our table-aware content handler in it. parser.setContentHandler( votContentHandler ); // Perform the parse; this will go through the XML stream sending // SAX events to votContentHandler, which in turn will forward // table events to tableHandler, which responds by printing the summary. parser.parse( new InputSource( in ) ); }