Next Previous Up Contents
Next: Streamed access
Up: Reading VOTables
Previous: Read a single VOTable from a file

6.2.2 Read VOTable document structure

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 VOElements 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();
            }
        }
    }


Next Previous Up Contents
Next: Streamed access
Up: Reading VOTables
Previous: Read a single VOTable from a file

STIL - Starlink Tables Infrastructure Library
Starlink User Note 252
STIL web page: http://www.starlink.ac.uk/stil/
Author email: m.b.taylor@bristol.ac.uk
Starlink: http://www.starlink.ac.uk/