<?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>Handling xs:any with the XMLBeans API</title>
    </header>
    <body>
        <section>
            <title>Compiling the schema</title>
            <p>Compiling schema for use with XMLBeans generates a kind of custom API specific to your schema. This API
                includes types with accessors designed to get and set parts of the XML defined by the schema. But if
                you've compiled schema that includes <code>xs:any</code> particles, you may have noticed that XMLBeans
                doesn't generate accessors for these these particles.
            </p>
            <p>For example, imagine the accessors generated by compiling the following schema snippet:</p>

            <source><![CDATA[
                <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
                    xmlns="http://xmlbeans.apache.org/samples/any"
                    targetNamespace="http://xmlbeans.apache.org/samples/any" elementFormDefault="qualified">
                    <xs:element name="root">
                        <xs:complexType>
                            <xs:sequence>
                                <xs:element ref="stringelement"/>
                                <xs:any processContents="lax"/>
                                <xs:element name="arrayofany">
                                    <xs:complexType>
                                        <xs:sequence>
                                            <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
                                        </xs:sequence>
                                    </xs:complexType>
                                </xs:element>
                            </xs:sequence>
                        </xs:complexType>
                    </xs:element>
                    <xs:element name="stringelement" type="xs:string"/>
                    <xs:complexType name="ListOfStrings">
                        <xs:sequence>
                            <xs:element ref="stringelement" minOccurs="0" maxOccurs="unbounded"/>
                        </xs:sequence>
                        <xs:attribute name="id" type="xs:string"/>
                    </xs:complexType>
                </xs:schema>
            ]]></source>

            <p>After compilation, you'd have the follow methods for <code>Root</code>, the type that gives you access to
                the <code>&lt;root&gt;</code> element:
            </p>
            <p>
                <code>addNewArrayofany()</code>
            </p>
            <p>
                <code>getArrayofany()</code>
            </p>
            <p>
                <code>getStringelement()</code>
            </p>
            <p>
                <code>setArrayofany(Arrayofany)</code>
            </p>
            <p>
                <code>setStringelement(String)</code>
            </p>
            <p>
                <code>xgetStringelement()</code>
            </p>
            <p>
                <code>xsetStringelement(XmlString)</code>
            </p>
            <p>What's missing? There's no <code>getAny</code> or <code>setAny</code>. How do you get or set the <code>
                &lt;root&gt;
            </code> element's second child? As it turns out, you do this by leaving behind (at least for a moment)
                JavaBeans-style accessors, and picking up any of a number of tools the API provides. These tools
                include:
            </p>
            <ul>
                <li>
                    <a href="#using_cursors">Using <code>XmlCursor</code> instances
                    </a>
                    to &quot;walk&quot; the XML, handling elements cursor-style.
                </li>
                <li>
                    <a href="#using_xpath">Using the <code>selectPath</code> method
                    </a>
                    to retrieve the XML you want via XPath.
                </li>
                <li>
                    <a href="#using_selectchildren">Using the <code>selectChildren</code> method
                    </a>
                    to retrieve child elements by name.
                </li>
                <li>
                    <a href="#using_dom">Using the DOM API</a>
                    to &quot;walk&quot; the node tree, handling elements by
                    name.
                </li>
            </ul>

        </section>
        <section id="using_cursors">
            <title>Using Cursors to Add XML</title>
            <p>As described in <a href="site:cursornav">Navigating XML with Cursors</a>, with an <code>
                XmlCursor
            </code> instance you can traverse your XML instance's full infoset. A cursor views XML as tokens, and you
                move a cursor from one token to another as if they were cars in a train.
            </p>
            <p>The following example illustrates how you might, in the course of building out the <code>&lt;root&gt;
            </code> document, create a second child element <code>&lt;anyfoo&gt;</code> where schema specifies <code>
                xs:any</code>. You add the element by creating it with a cursor, then (in lieu of a setter) using the <code>
                XmlCursor.copyXml
            </code> or <code>XmlCursor.moveXml</code> method to put the element where it needs to go.
            </p>

            <source><![CDATA[
                // Start by creating a <root> element that will contain
                // the children built by this code.
                RootDocument rootDoc = RootDocument.Factory.newInstance();
                RootDocument.Root root = rootDoc.addNewRoot();

                // Add the first element, <stringelement>.
                root.setStringelement("some text");

                // Create an XmlObject in which to build the second
                // element in the sequence, <anyfoo>. Here, the
                // XmlObject instance is simply a kind of incubator
                // for the XML. Later the XML will be moved into the
                // document this code is building.
                XmlObject anyFoo = XmlObject.Factory.newInstance();

                // Add a cursor to do the work of building the XML.
                XmlCursor anyFooCursor = anyFoo.newCursor();
                anyFooCursor.toNextToken();

                // Add the element in the schema's namespace, then add
                // element content.
                anyFooCursor.beginElement(new QName(m_namespaceUri, "anyfoo"));
                anyFooCursor.insertChars("some text");

                // Move the cursor back to the new element's top, where
                // it can grab all of the element's XML.
                anyFooCursor.toStartDoc();
                anyFooCursor.toNextToken();

                // Finally, move the XML into the <root> document by moving it
                // from a position at one cursor to a position at
                // another.
                XmlCursor rootCursor = root.newCursor();
                rootCursor.toEndToken();
                anyFooCursor.moveXml(rootCursor);
            ]]></source>

            <p>You might find that this build-and-move-cursor-to-cursor pattern is common when you're creating or moving
                XML when accessors aren't available. For example, you could do the same sort of thing when your schema
                defines a type that you want to place into an <code>xs:any</code> space in an instance. The following
                code adds a <code>&lt;stringelement&gt;</code>element as a child of the <code>&lt;arrayofany&gt;</code> element,
                which schema defines as containing a sequence of <code>xs:any</code> particles. The <code>&lt;stringlement&gt;</code> element
                is simple, but it could just as easily be a complex schema type.
            </p>

            <source><![CDATA[
                // Create a simple <stringelement>.
                StringelementDocument stringElementDoc = StringelementDocument.Factory.newInstance();
                stringElementDoc.setStringelement("some text");
                XmlCursor stringElementCursor = stringElementDoc.newCursor();
                stringElementCursor.toFirstContentToken();

                // Add a cursor to mark the position to which the new child
                // XML will be moved.
                XmlCursor arrayCursor = arrayOfAny.newCursor();
                arrayCursor.toNextToken();

                // Move the new <stringelement> into place.
                stringElementCursor.moveXml(arrayCursor);
                stringElementCursor.dispose();
            ]]></source>
        </section>
        <section id="using_xpath">
            <title>Using XPath and the selectPath Method to Find XML</title>
            <p>XPath is a convenient, direct way to get at specific chunks of XML. In the XMLBeans API, you execute
                XPath expressions with the <code>XmlObject.selectPath</code> or <code>XmlCursor.selectPath</code> methods.
                The example in Java below assumes the following instance conforming to the schema introduced at the
                beginning of this topic:
            </p>
            <source><![CDATA[
                <root xmlns="http://xmlbeans.apache.org/samples/any">
                    <stringelement>some text</stringelement>
                    <anyfoo>some text</anyfoo>
                    <arrayofany>
                        <stringelement>some text</stringelement>
                        <someelement>
                            <stringlist id="001">
                                <stringelement>string1</stringelement>
                                <stringelement>string2</stringelement>
                            </stringlist>
                        </someelement>
                    </arrayofany>
                </root>
            ]]></source>
            <p>The following code uses XPath to reach the <code>&lt;stringelement&gt;</code> element because there is no
                accessor available. It then shifts the XML around a little, moving <code>&lt;stringelement&gt;</code> up
                in the hierarchy to replace its parent, <code>&lt;someelement&gt;</code>.
            </p>
            <source><![CDATA[
                public boolean editExistingDocWithSelectPath(RootDocument rootDoc) {
                    String namespaceUri = "http://xmlbeans.apache.org/samples/any";

                    // Put a cursor at the top of the <arrayofany> element.
                    XmlCursor selectionCursor = rootDoc.getRoot().getArrayofany().newCursor();

                    // Use XPath and cursor movement to position the cursor at
                    // the <stringlist> element.
                    String namespaceDecl = "declare namespace any='" + namespaceUri + "'; ";
                    selectionCursor.selectPath(namespaceDecl + "$this//any:someelement/any:stringlist");
                    selectionCursor.toNextSelection();

                    // Create a new cursor at the same location and move it to
                    // <stringelement&gt;'s <someelement> parent.
                    XmlCursor editCursor = selectionCursor.newCursor();
                    editCursor.toParent();

                    // Move the <stringelement> element to this position, displacing
                    // the <someelement> downward. Remove the <someelement> XML,
                    // effectively replacing <someelement> with <stringlist>.
                    selectionCursor.moveXml(editCursor);
                    editCursor.removeXml();
                    editCursor.dispose();

                    return rootDoc.validate();
                }
            ]]></source>
        </section>
        <section id="using_selectchildren">
            <title>Using the selectChildren Method to Find XML</title>
            <p>The <code>XmlObject.selectChildren</code> method you can retrieve an array of the child elements of a
                specified name. The method is overloaded to take <code>java.xml.namespace.QName</code> instances or
                strings as parameters. The following code (based on the instance used in the preceding example) simply
                finds the <code>&lt;anyfoo&gt;</code> element, an <code>xs:any</code>, and replaces it with an <code>
                    &lt;anybar&gt;
                </code> element.
            </p>
            <source><![CDATA[
                public boolean editExistingDocWithSelectChildren(RootDocument rootDoc) {
                    String namespaceUri = "http://xmlbeans.apache.org/samples/any";
                    RootDocument.Root root = rootDoc.getRoot();

                    // Select the <anyfoo> children of <root>.
                    XmlObject[] stringElements = root.selectChildren(new QName(m_namespaceUri, "anyfoo"));

                    // If the element is there, replace it with another element.
                    if (stringElements.length > 0) {
                        XmlCursor editCursor = stringElements[0].newCursor();
                        editCursor.removeXml();
                        editCursor.beginElement(new QName(namespaceUri, "anybar"));
                        editCursor.insertChars("some other text");
                        editCursor.dispose();
                    }
                    return rootDoc.validate();
                }
            ]]></source>
        </section>
        <section id="using_dom">
            <title>Using the DOM API to Find XML</title>
            <p>Through the <code>getDomNode</code> method (exposed by <code>XmlObject</code> and types generated from
                schema), you can get a live DOM node representing your XML. For example, calling <code>
                    myElement.getDomNode()
                </code> will return a <code>org.w3c.dom.Node</code> instance representing the XML bound to <code>
                    myElement</code>. If you're already familiar with DOM-style access to XML, this can be a familiar
                alternative for handling <code>xs:any</code> instances.
            </p>
            <p>Using the instance introduced earlier in this topic, the following example adds a new <code>&lt;bar&gt;
            </code> element between the first and second children of the <code>&lt;arrayofany&gt;</code> element. The
                code also ensures that the first and second children are <code>&lt;stringelement&gt;</code> and <code>
                    &lt;someelement&gt;</code>, respectively.
            </p>
            <source><![CDATA[
                public boolean editExistingDocWithDOM(RootDocument rootDoc) {
                    RootDocument.Root root = rootDoc.getRoot();

                    // Get the DOM nodes for the <arrayofany> element's children.
                    Node arrayOfAnyNode = root.getArrayofany().getDomNode();

                    // You don't have get* accessors for any of the <arrayofany>
                    // element's children, so use DOM to identify the first
                    // and second elements while looping through the child list.
                    NodeList childList = arrayOfAnyNode.getChildNodes();
                    Element firstElementChild = null;
                    Element secondElementChild = null;

                    // Find the first child element and make sure it's
                    // <stringelement>.
                    for (int i = 0; i < childList.getLength(); i++) {
                        Node node = childList.item(i);
                        if (node.getNodeType() == Node.ELEMENT_NODE) {
                            if (node.getLocalName().equals("stringelement")) {
                                firstElementChild = (Element)node;
                                break;
                            }
                        }
                    }
                    if (firstElementChild == null) {
                        return false;
                    }

                    // Find the second child element and make sure it's
                    // <someelement>.
                    Node node = firstElementChild.getNextSibling();
                    do {
                        if (node.getNodeType() == Node.ELEMENT_NODE) {
                            if (node.getLocalName().equals("someelement")) {
                                secondElementChild = (Element)node;
                                break;
                            }
                        }
                        node = node.getNextSibling();
                    } while (node != null);
                    if (secondElementChild == null) {return false;}

                    // Create and insert a new <bar> element.
                    Element fooElement =
                        secondElementChild.getOwnerDocument().createElementNS("http://openuri.org","bar");
                    Node valueNode =
                        fooElement.getOwnerDocument().createTextNode("some text");
                    fooElement.appendChild(valueNode);
                    arrayOfAnyNode.insertBefore(fooElement, secondElementChild);

                    return rootDoc.validate();
                }
            ]]></source>
        </section>
        <section>
            <title>Related Topics</title>
            <p>
                <a href="site:gettingstarted">Getting Started with XMLBeans</a>
            </p>
        </section>
    </body>
</document>