If you are interested in the structure of the VOTable document
as opposed to just the tabular data,
you can obtain a tree of VOElement
objects representing all or part of the document (very much like a DOM),
which can be navigated using the getChildren
method and so on.
Some of the nodes in this tree are of specialised subclasses of
VOElement
;
these nodes provide extra functionality relevant to their
rôle in a VOTable document.
For instance a ParamElement
object (which represents a PARAM element in the XML document)
has a getObject
method, which returns the parameter's
value as a Java object - this may be an Integer
,
or a float[]
array, or some other type of item,
depending on not only the value
attribute of the element,
but on what its datatype
and arraysize
attributes are too (its class follows the same rules as for table columns).
The various VOElement
subclasses and their
methods are not documented exhaustively here - see the javadocs.
The most important of the VOElement
subclassses is TableElement
,
which represents a TABLE element.
The best way to obtain the actual table data (values of the cells)
from a TableElement
is to make a StarTable
from it using the
VOStarTable
adapter class;
this can be interrogated for its data and metadata as described
in section 2.
The resulting StarTable
may or may not provide random
access (isRandom
may or not return true).
This reflects how the data has been obtained - if it's a binary
stream from a remote URL it may only be possible to read the rows from
start to finish a row at a time, but if it's a set of DOM nodes
it may be possible to read cells in any order.
If you need random access for a table and you don't have it
(or don't know if you do), then use
Tables.randomTable
as usual (see section 2.3.3).
It is also possible to access the table data directly (without
making it into a StarTable
) by using the
getData
method of the TableElement
, but in this case you need
to work a bit harder to extract some of the data and metadata in
useful forms. See the TabularData
documentation for details.
Where possible, STIL uses a hybrid SAX/DOM approach to
constructing the tree of VOElement
s
which represents the VOTable document.
In general it builds a DOM of the whole document with the exception
of the children of STREAM or TABLEDATA elements,
since these are the ones which contain the actual table data cells, and
would thus be likely to have large memory requirements.
When it gets to one of these, it works out how to turn the contents
into a tabular data object, and interprets the corresponding SAX
events directly to do this. The effect of this is that (for all but
the weirdest VOTable documents) the memory requirements of the DOM tree
are very modest, but all the information about the hierarchical
structure of the document is available. What's lost from the DOM
is the representation of the cell values themselves, and you almost certainly
don't want to go poking around in that, since you can obtain it
in ready-to-use form from the TableElement
.
Having said that, if for some reason you do want the DOM to represent
the whole of a VOTable document, bulk data and all, you can do that
too - just parse the document to construct a DOM yourself, and
submit that full DOM to VOElementFactory
.
Although the DOM tree will be small, in some cases the memory requirements
for a table may be large, since the data has to be stored somewhere.
Currently,
for table data which is supplied inline (in any of the three formats)
STIL will store it internally in some kind of memory structure
(hence random access is available).
There are plans for a configurable flag to cause this data to be stored
in a scratch file instead, so that there is no large memory requirement.
For href-referenced streamed data, it just streams the data every time
the corresponding TabularData
's
getRowStepper
method is called, so in this case only
sequential access is available, and there is no large memory requirement.
To read a VOTable document as described in this section, use one of
VOElementFactory
's
several makeVOElement
methods to obtain a top-level
VOElement
object. You can then interrogate the resulting
tree using methods like getChildren
, getParent
,
getAttribute
etc.
When you get to a TABLE element
(TableElement
object),
you can turn it into a StarTable
using the
VOStarTable
adapter class.
The top-level element you get from the VOElementFactory
will typically be a
VOTABLE element, since that is normally the top element of a VOTable
document, but STIL does not require this - for instance the XML document
could start with a RESOURCE element, or you could use it to
investigate only a subtree of a DOM representing a document you
parsed earlier.
Here is an example of using this approach to read the structure of a, possibly complex, VOTable document. This program locates each TABLE element which is the immediate child of the first RESOURCE element in the document, and prints out its column titles and table data.
void printFirstTable( File votFile ) throws IOException, SAXException { // Create a tree of VOElements from the given XML file. VOElement top = VOElementFactory.makeVOElement( votFile ); // Find the first RESOURCE element. VOElement[] resources = top.getDescendantsByName( "RESOURCE" ); VOElement res1 = resources[ 0 ]; // Iterate over all its direct children which are TABLE elements. VOElement[] tables = res1.getChildrenByName( "TABLE" ); for ( int iTab = 0; iTab < tables.length; iTab++ ) { System.out.println( "Table #" + iTab + "\n\n" ); TableElement tableEl = (TableElement) tables[ iTab ]; StarTable starTable = new VOStarTable( tableEl ); // Write out the column name for each of its columns. int nCol = starTable.getColumnCount(); for ( int iCol = 0; iCol < nCol; iCol++ ) { String colName = starTable.getColumnInfo( iCol ).getName(); System.out.print( colName + "\t" ); } System.out.println(); // Iterate through its data rows, printing out each element. for ( RowSequence rSeq = starTable.getRowSequence(); rSeq.hasNext(); ) { rSeq.next(); Object[] row = rSeq.getRow(); for ( int iCol = 0; iCol < nCol; iCol++ ) { System.out.print( row[ iCol ] + "\t" ); } System.out.println(); } } }