<?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V2.0//EN" "http://forrest.apache.org/dtd/document-v20.dtd">
<document>
    <header>
        <title>Navigating XML with Cursors</title>
    </header>
    <body>
        <section>
            <title>Navigating XML with Cursors</title>
            <p>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.
            </p>
            <p>With an XML cursor, you can:</p>
            <ul>
                <li>
                    <a href="site:xmltokens">Use the token model</a>
                    to move
                    through XML in small increments, or in a manner similar to using a DOM-based
                    model.
                </li>
                <li>Get and set values within the XML.</li>
                <li>
                    <a href="#adding_elements_attributes">Change the structure</a>
                    of an
                    XML document by inserting, removing, and moving elements and attributes.
                </li>
                <li>
                    <a href="site:xpathxquery">Execute XQuery expressions</a>
                    against the XML represented by the cursor.
                </li>
                <li>
                    <a href="site:bookmarks">Insert bookmarks</a>
                    to
                    mark locations in XML.
                </li>
            </ul>
            <p>When you're finished using a cursor, your code should call its
                <strong>dispose</strong>
                method.
            </p>
        </section>

        <section>
            <title>Creating and Moving a Cursor</title>

            <p>With an XML instance document bound to
                <strong>
                    <a href="ext:api/stable/XmlObject">XmlObject</a>
                </strong>
                (or a type inheriting from it), you create a new cursor by calling the
                <strong>newCursor</strong>
                method. The
                <strong>
                    <a href="ext:api/stable/XmlCursor">XmlCursor</a>
                </strong>
                interface represents a cursor. From a cursor standpoint, an XML document is
                a collection of <strong>tokens</strong> 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 <em>token type</em>.
            </p>
            <note>
                <strong>Note:</strong>
                For a more complete description of
                XML tokens, see <a href="site:xmltokens">Understanding XML Tokens</a>.
            </note>
            <p>For example, the following code loads the XML instance described above
                from a <strong>File</strong> object, then creates a new cursor.
                The <strong>toFirstChild</strong> takes the cursor to the start
                tag of the <strong>batchWidgetOrder</strong> 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, <strong class="filepath">Token
                    type: START /
                </strong> and the
                <strong class="filepath">batchWidgetOrderElement</strong>
                and its contents.
            </p>
            <source><![CDATA[
                public static void insertCursor(File orderFile) throws Exception {
                    BatchWidgetOrderDocument xmlDoc = BatchWidgetOrderDocument.Factory.parse(orderFile);
                    XmlCursor orderCursor = xmlDoc.newCursor();
                    orderCursor.toFirstChild();
                    System.out.println("Token type: " + orderCursor.currentTokenType() +
                    " / " + orderCursor.xmlText());
                }
            ]]></source>
            <note><strong>Note</strong>: The
                <strong>XmlCursor</strong>
                interface provides many methods you can use to put a cursor where you want it.
                For a list of those methods, see <a href="ext:api/stable/XmlCursor">XmlCursor
                    Interface</a>.
            </note>
        </section>

        <section id="adding_elements_attributes">
            <title>Adding Elements and Attributes</title>
            <p>The <strong>XmlCursor</strong> interface provides several methods
                you can use to add elements and attributes to XML.
            </p>
            <p>One way to add new XML is with the
                <strong>beginElement</strong>
                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:
            </p>
            <source><![CDATA[
                // Create a new chunk of XML.
                XmlObject newXml = XmlObject.Factory.newInstance();
                /*
                 * Insert a new cursor and move it to the first START token (where the
                 * XML actually begins.
                 */
                XmlCursor cursor = newXml.newCursor();
                cursor.toNextToken();
                // Begin a new item element whose namespace URI is "http://openuri.org".
                cursor.beginElement("item", "http://openuri.org/");
                // Insert an ID attribute on the item element, along with an attribute value.
                cursor.insertAttributeWithValue("id", "4056404");
                // Insert "bicycle" as an element value.
                cursor.insertChars("bicycle");
                cursor.dispose();
            ]]></source>
            <p>This example results in something like the following:</p>
            <source><![CDATA[
                <ns1:item id="4056404" xmlns:ns1="http://openuri.org/">bicycle</ns1:item>
            ]]></source>
        </section>

        <section>
            <title>Using Stored Cursor Locations with push() and pop()</title>
            <p>When you want to move a cursor around, but want to keep track of a former
                location, you can use the <strong>XmlCursor</strong> interface's
                <strong>push</strong>
                and
                <strong>pop</strong>
                methods. The <strong>push</strong> method pushes the cursor's
                current location onto a stack of locations maintained for that particular
                cursor; the <strong>pop</strong> method removes the location
                from the top of the stack and moves the cursor to that location.
            </p>
            <p>For example, consider the following &lt;employee&gt; element, used in the
                example below.
            </p>
            <source><![CDATA[
                <employee>
                    <name>Gladys Kravitz</name>
                    <address location="home">
                        <street>1313 Mockingbird Lane</street>
                        <city>Seattle</city>
                        <state>WA</state>
                        <zip>98115</zip>
                    </address>
                    <address location="work">
                        <street>2011 152nd Avenue NE</street>
                        <city>Redmond</city>
                        <state>WA</state>
                        <zip>98052</zip>
                    </address>
                    <phone location="work">(425) 555-6897</phone>
                    <phone location="home">(206) 555-6594</phone>
                    <phone location="mobile">(206) 555-7894</phone>
                </employee>
            ]]></source>
            <p>The following Java code illustrates how you can use
                <strong>push</strong>
                and <strong>pop</strong> to put the cursor back to a saved
                location after a bit of traveling.
            </p>
            <source><![CDATA[
                /**
                 * 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();
                }
            ]]></source>
            <p>Of course, you can call <strong>push</strong> and
                <strong>pop</strong>
                multiple times. Each new call to the
                <strong>push</strong>
                method pushes the current location onto the stack. As you call the
                <strong>pop</strong>
                method, you're always getting what's on top of the stack. So if you called
                <strong>push</strong>
                three times before calling
                <strong>pop</strong>
                &#8212; 1, 2, 3 &#8212; calling <strong>pop</strong> three
                times would get those locations in reverse order &#8212; 3, 2, 1.
            </p>
            <p>The <strong>push</strong> and
                <strong>pop</strong>
                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
                <strong>push</strong>
                and <strong>pop</strong> are far less than those needed by
                cursors.
            </p>
        </section>

        <section>
            <title>Disposing of a Cursor</title>
            <p>When you're through with a cursor, your code should call its
                <strong>dispose</strong>
                method to indicate that it's no longer needed.
            </p>
        </section>

        <section id="relatedtopics">
            <title>Related Topics</title>
            <p>
                <a href="site:xmltokens">Understanding XML Tokens</a>
            </p>
            <p>
                <a href="site:gettingstarted">Getting Started with XMLBeans</a>
            </p>
        </section>
    </body>
</document>