File: conHandlingAny.html

package info (click to toggle)
xmlbeans 3.0.2-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster
  • size: 19,260 kB
  • sloc: java: 147,742; xml: 41,691; sh: 688; sql: 48; makefile: 17
file content (285 lines) | stat: -rw-r--r-- 15,199 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
<!doctype HTML public "-//W3C//DTD HTML 4.0 Frameset//EN">

<!-- Copyright 2004 The Apache Software Foundation

     Licensed 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. -->
<html>
<head>
<!-- InstanceBeginEditable name="doctitle" -->
<title>Handling xs:any with the XMLBeans API </title>
<!-- InstanceEndEditable -->
<!--(Meta)==========================================================-->

<meta http-equiv=Content-Type content="text/html; charset=$CHARSET;">


<!-- InstanceBeginEditable name="metatags" -->

<meta content="your name" name="author">
<meta content="A description of the topic contents." name="description">
<meta content="keywords to help in searches" name="keywords">
<meta content="10/25/02" name="date last modified">
<!-- InstanceEndEditable -->

<!--(Links)=========================================================-->
<!-- InstanceBeginEditable name="head" -->
<link href="../xmlbeans.css" rel="stylesheet" type="text/css">
<!-- InstanceEndEditable -->
<link href="../xmlbeans.css" rel="stylesheet" type="text/css">
<a href="../../../core/index.html" id="index"></a>
<script language="JavaScript" src="../../../core/topicInfo.js"></script>
<script language="JavaScript" src="../../../core/CookieClass.js"></script>
<script language="JavaScript" src="../../../core/displayContent.js"></script>
</head>

<!--(Body)==========================================================-->
<body>
<script language="JavaScript">

</script>
<!-- InstanceBeginEditable name="body" -->
<h1> Handling xs:any  with the XMLBeans API </h1>
<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>
<div id="topictext"><pre>&lt;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">
    &lt;xs:element name="root">
        &lt;xs:complexType>
            &lt;xs:sequence>
                &lt;xs:element ref="stringelement"/>
                &lt;xs:any processContents="lax"/>
                &lt;xs:element name="arrayofany">
                    &lt;xs:complexType>
                        &lt;xs:sequence>
                            &lt;xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
                        &lt;/xs:sequence>
                    &lt;/xs:complexType>
                &lt;/xs:element>
            &lt;/xs:sequence>
        &lt;/xs:complexType>
    &lt;/xs:element>
    &lt;xs:element name="stringelement" type="xs:string"/>    
    &lt;xs:complexType name="ListOfStrings">
        &lt;xs:sequence>
            &lt;xs:element ref="stringelement" minOccurs="0" maxOccurs="unbounded"/>
        &lt;/xs:sequence>
        &lt;xs:attribute name="id" type="xs:string"/>
    &lt;/xs:complexType>
&lt;/xs:schema></pre>
    <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>
    <h2><a name="using_cursors"></a>Using Cursors to Add XML </h2>
    <p>As described in <a href="conNavigatingXMLwithCursors.html">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>
    <pre>// Start by creating a &lt;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, &lt;stringelement>.
root.setStringelement("some text");

// Create an XmlObject in which to build the second
// element in the sequence, &lt;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 &lt;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);</pre>
    <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>
    <pre>// Create a simple &lt;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 &lt;stringelement> into place.
stringElementCursor.moveXml(arrayCursor);
stringElementCursor.dispose();</pre>
    <h2><a name="using_xpath"></a>Using XPath and the selectPath Method to Find XML </h2>
    <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>
    <pre>&lt;root xmlns="http://xmlbeans.apache.org/samples/any">
    &lt;stringelement>some text&lt;/stringelement>
    &lt;anyfoo>some text&lt;/anyfoo>
    &lt;arrayofany>
        &lt;stringelement>some text&lt;/stringelement>
        &lt;someelement>
            &lt;stringlist id="001">
                &lt;stringelement>string1&lt;/stringelement>
                &lt;stringelement>string2&lt;/stringelement>
            &lt;/stringlist>
        &lt;/someelement>
    &lt;/arrayofany>
&lt;/root></pre>
    <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>
    <pre>public boolean editExistingDocWithSelectPath(RootDocument rootDoc)
{
    String namespaceUri = "http://xmlbeans.apache.org/samples/any";

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

    // Use XPath and cursor movement to position the cursor at
    // the &lt;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 
    // &lt;stringelement&gt;'s &lt;someelement> parent.
    XmlCursor editCursor = selectionCursor.newCursor();
    editCursor.toParent();

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

    return rootDoc.validate();
}</pre>
    <h2><a name="using_selectchildren"></a>Using the selectChildren Method to Find XML </h2>
    <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>
    <pre>public boolean editExistingDocWithSelectChildren(RootDocument rootDoc)
{
    String namespaceUri = "http://xmlbeans.apache.org/samples/any";
    RootDocument.Root root = rootDoc.getRoot();
        
    // Select the &lt;anyfoo> children of &lt;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();
}</pre>
    <h2><a name="using_dom"></a>Using the DOM API to Find XML </h2>
    <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>
    <pre>public boolean editExistingDocWithDOM(RootDocument rootDoc)
{
    RootDocument.Root root = rootDoc.getRoot();
        
    // Get the DOM nodes for the &lt;arrayofany> element's children.
    Node arrayOfAnyNode = root.getArrayofany().getDomNode();

    // You don't have get* accessors for any of the &lt;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
    // &lt;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
    // &lt;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 &lt;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();
}</pre>
</div>
<div>
<h2>Related Topics</h2>
</div>
<p><a href="conGettingStartedwithXMLBeans.html">Getting Started with XMLBeans</a></p>
<!-- InstanceEndEditable -->
<script language="JavaScript">

</script>
</body>
</html>