## Package net.sf.saxon.tinytree

This package is an implementation of the Saxon internal tree structure, designed to minimize memory usage, and the costs of allocating and garbage-collecting Java objects.

See:
Description

Class Summary
CharSlice: This is an implementation of the JDK 1.4 CharSequence interface: it implements a CharSequence as a view of an array.
TinyBuilder: The TinyBuilder class is responsible for taking a stream of SAX events and constructing a Document tree, using the "TinyTree" implementation.
TinyDocumentImpl: A node in the XML parse tree representing the Document itself (or equivalently, the root node of the Document).

## Package net.sf.saxon.tinytree Description

This package is an implementation of the Saxon internal tree structure, designed to minimize memory usage, and the costs of allocating and garbage-collecting Java objects.

The data structure consists of a set of arrays, held in the TinyDocumentImpl object. These are in three groups.

The principal group of arrays contain one entry for each node other than namespace and attribute nodes. These arrays are in document order. The following information is maintained for each node: the depth in the tree, the name code, the index of the next sibling, an "offset" and a "length". The meaning of "offset" and "length" depends on the node type. For text nodes, comment nodes, and processing instructions these fields index into a StringBuffer holding the text. For element nodes, "offset" is an index into the attributes table, and "length" is an offset into the namespaces table. Either of these may be set to -1 if there are no attributes/namespaces.

A name code is an integer value that indexes into the NamePool object: it can be used to determine the prefix, local name, or namespace URI of an element or attribute name.

The attribute group holds the following information for each attribute node: parent element, prefix, name code, attribute type, and attribute value. Attributes for the same element are adjacent.

The namespace group holds one entry per namespace declaration (not one per namespace node). The following information is held: pointer to the element on which the namespace was declared, and namespace code. A namespace code is an integer, which the NamePool can resolve into a prefix and a namespace URI: the top 16 bits identify the prefix, the bottom 16 bits the URI.

The data structure contains no Java object references: the links between elements and attributes/namespaces are all held as integer offsets. This reduces size, and also makes the whole structure relocatable (though this capability is not currently exploited). All navigation is done by serial traversal of the arrays, using the node depth as a guide. The fact that a next sibling pointer is held, but no previous sibling or parent pointer, is entirely pragmatic: in fact, in most transformations the next sibling pointer makes no difference to performance, but in a few cases it makes a big difference. The absence of the other pointers is a trade-off between tree-building time and transformation time: I found that in most cases, more time was spent creating these pointers than actually using them.

When the tree is navigated, transient ("flyweight") nodes are created as Java objects. These disappear as soon as they are no longer needed. Note that to compare two nodes for identity, you can use either the isSameNode() method, or compare the results of generateId(). Comparing the Java objects using "==" is incorrect.

The tree structure implements the DOM interface as well as the Saxon NodeInfo interface. There are limitations in the DOM support, however: especially (a) the tree is immutable, so all updating methods throw an exception; (b) namespace declarations are not exposed as attributes, and (c) only the core DOM classes are provided.

The primary way of navigating the tree is through the XPath axes, accessible through the getEnumeration() method. The familiar DOM methods such as getNextSibling() and getFirstChild() are implemented as wrapper methods using the XPath axes (in the com.icl.saxon.om.AbstractNode class). This makes them less efficient than using the axis directly.

Michael H. Kay
14 May 2001