Navigating XML with Cursors

XML cursors are a way to navigate through an XML instance document. Once
you load an XML document, you can create a cursor to represent a specific
place in the XML. Because you can use a cursor with or without a schema corresponding
to the XML, cursors are an ideal way to handle XML without a schema.

With an XML cursor, you can:

Use the token model to move
through XML in small increments, or in a manner similar to using a DOM-based
model.

When you're finished using a cursor, your code should call its dispose
method.

Creating and Moving a Cursor

With an XML instance document bound to XmlObject
(or a type inheriting from it), you create a new cursor by calling the newCursor
method. The XmlCursor
interface represents a cursor. From a cursor standpoint, an XML document is
a collection of tokens that represent the kinds of things that can
appear in XML. These include attributes, the start and end of elements,
comments, and so on. Each piece of information in XML is represented by
a token type.

For example, the following code loads the XML instance described above
from a File object, then creates a new cursor.
The toFirstChild takes the cursor to the start
tag of the batchWidgetOrder document element.
The code then prints the type for the token at the cursor's location, along
with the XML the cursor represents—in other words, Token
type: START / and the batchWidgetOrderElement
and its contents.

Note: The XmlCursor
interface provides many methods you can use to put a cursor where you want it.
For a list of those methods, see XmlCursor
Interface.

Adding
Elements and Attributes

The XmlCursor interface provides several methods
you can use to add elements and attributes to XML.

One way to add new XML is with the beginElement
method. This method is designed to insert a new element at the cursor's location,
and do it so the cursor ends up between the new element's START and END tokens.
From this position, you can insert attributes (they're automatically placed
in the start tag, where they belong) and insert a value. Here's an example:

Using Stored Cursor Locations with push() and pop()

When you want to move a cursor around, but want to keep track of a former
location, you can use the XmlCursor interface's
push and pop
methods. The push method pushes the cursor's
current location onto a stack of locations maintained for that particular
cursor; the pop method removes the location
from the top of the stack and moves the cursor to that location.

For example, consider the following <employee> element, used in the
example below.

The following Java code illustrates how you can use push
and pop to put the cursor back to a saved
location after a bit of traveling.

/**
* Pass to the trySelectPath method an XmlObject instance that contains
* the XML above.
*/
public void trySelectPath(XmlObject xml)
{
/*
* Inserts the cursor at the STARTDOC token (the very beginning,
* before any elements).
*/
XmlCursor cursor = xml.newCursor();
// Moves the cursor to just before <employee>
cursor.toFirstChild();
// Pushes the cursor's current location onto the stack.
cursor.push();
// Moves the cursor to just before the "work" <phone> element.
cursor.toChild(2);
// Moves the cursor to just before the "home" <phone> element.
cursor.toNextSibling();
// Moves the cursor back to just before <employee>
cursor.pop();
}

Of course, you can call push and pop
multiple times. Each new call to the push
method pushes the current location onto the stack. As you call the pop
method, you're always getting what's on top of the stack. So if you called
push three times before calling pop
— 1, 2, 3 — calling pop three
times would get those locations in reverse order — 3, 2, 1.

The push and pop
methods can be handy as an alternative to creating new cursors that are designed
simply to mark a particular location while you move another cursor around.
The resources required to maintain a location stack through push
and pop are far less than those needed by
cursors.

Disposing of a Cursor

When you're through with a cursor, your code should call its dispose
method to indicate that it's no longer needed.