001: /* Copyright 2004 The Apache Software Foundation
002: *
003: * Licensed under the Apache License, Version 2.0 (the "License");
004: * you may not use this file except in compliance with the License.
005: * You may obtain a copy of the License at
006: *
007: * http://www.apache.org/licenses/LICENSE-2.0
008: *
009: * Unless required by applicable law or agreed to in writing, software
010: * distributed under the License is distributed on an "AS IS" BASIS,
011: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: * See the License for the specific language governing permissions and
013: * limitations under the License.
014: */
015:
016: package org.apache.xmlbeans.samples.xquery;
017:
018: import org.apache.xmlbeans.XmlCursor;
019: import org.apache.xmlbeans.XmlObject;
020: import org.apache.xmlbeans.XmlException;
021: import org.apache.xmlbeans.samples.xquery.employees.PhoneType;
022:
023: /**
024: * This class demonstrates how to use the selectPath method to execute XPath
025: * expressions. Compare the code here with the code in the ExecQuery class.
026: * That class uses the execQuery method to execute XQuery expressions.
027: * <p/>
028: * You can call the selectPath method from either an XmlObject or XmlCursor
029: * instance. Calling from XmlObject returns an XmlObject array. Calling
030: * from XmlCursor returns void, and you use methods of the cursor to
031: * navigate among returned "selections".
032: */
033: public class SelectPath {
034: // Declare a namespace corresponding to the namespace declared in the XML
035: // instance. The string here will be used as part of the XPath expression to
036: // ensure that the query finds namespace-qualified elements in the XML.
037: final static String m_namespaceDeclaration = "declare namespace xq='http://xmlbeans.apache.org/samples/xquery/employees';";
038:
039: /**
040: * Prints the XML bound to <em>empDoc</em>, uses XPath to
041: * retrieve elements containing work phone numbers, changes the numbers
042: * to another number, then prints the XML again to display the changes.
043: *
044: * This method demonstrates the following characteristics of the selectPath method:
045: *
046: * - it supports expressions that include predicates
047: * - the XML it returns is the XML queried against -- not a copy, as with results
048: * returned via execQuery methods and XQuery. Changes to this XML update
049: * the XML queried against.
050: * - selectPath called from an XMLBean type (instead of a cursor) returns an
051: * array of results (if any). These results can be cast to a matching type
052: * generated from schema.
053: *
054: * @param empDoc The incoming XML.
055: * @return <code>true</code> if the XPath expression returned results;
056: * otherwise, <code>false</code>.
057: */
058: public boolean updateWorkPhone(XmlObject empDoc) {
059: boolean hasResults = false;
060:
061: // Print the XML received.
062: System.out
063: .println("XML as received by updateWorkPhone method: \n\n"
064: + empDoc.toString());
065:
066: // Create a variable with the query expression.
067: String pathExpression = "$this/xq:employees/xq:employee/xq:phone[@location='work']";
068:
069: // Execute the query.
070: XmlObject[] results = empDoc.selectPath(m_namespaceDeclaration
071: + pathExpression);
072: if (results.length > 0) {
073: hasResults = true;
074:
075: // <phone> elements returned from the expression will conform to the
076: // schema, so bind them to the appropriate XMLBeans type generated
077: // from the schema.
078: PhoneType[] phones = (PhoneType[]) results;
079:
080: // Change all the work phone numbers to the same number.
081: for (int i = 0; i < phones.length; i++) {
082: phones[i].setStringValue("(206)555-1234");
083: }
084: // Print the XML with updates.
085: System.out
086: .println("\nXML as updated by updateWorkPhone method (each work \n"
087: + "phone number has been changed to the same number): \n\n"
088: + empDoc.toString() + "\n");
089: }
090: return hasResults;
091: }
092:
093: /**
094: * Uses the XPath text() function to get values from <name>
095: * elements in received XML, then collects those values as the value of a
096: * <names> element created here.
097: * <p/>
098: * Demonstrates the following characteristics of the selectPath method:
099: * <p/>
100: * - It supports expressions that include XPath function calls.
101: * - selectPath called from an XmlCursor instance (instead of an XMLBeans
102: * type) places results (if any) into the cursor's selection set.
103: *
104: * @param empDoc The incoming XML.
105: * @return <code>true</code> if the XPath expression returned results;
106: * otherwise, <code>false</code>.
107: */
108: public boolean collectNames(XmlObject empDoc) {
109: boolean hasResults = false;
110:
111: // Create a cursor with which to execute query expressions. The cursor
112: // is inserted at the very beginning of the incoming XML, then moved to
113: // the first element's START token.
114: XmlCursor pathCursor = empDoc.newCursor();
115: pathCursor.toNextToken();
116:
117: // Execute the path expression, qualifying it with the namespace
118: // declaration.
119: pathCursor.selectPath(m_namespaceDeclaration
120: + "$this//xq:employee/xq:name/text()");
121:
122: // If there are results, then go ahead and do stuff.
123: if (pathCursor.getSelectionCount() > 0) {
124: hasResults = true;
125:
126: // Create a new <names> element into which names from the XML
127: // will be copied. Note that this element is in the default
128: // namespace; it's not part of the schema.
129: XmlObject namesElement = null;
130: try {
131: namesElement = XmlObject.Factory.parse("<names/>");
132: } catch (XmlException e) {
133: e.printStackTrace();
134: }
135:
136: // Add a cursor the new element and put it between its START and END
137: // tokens, where new values can be inserted.
138: XmlCursor namesCursor = namesElement.newCursor();
139: namesCursor.toFirstContentToken();
140: namesCursor.toEndToken();
141:
142: // Loop through the selections, appending the incoming <name> element's
143: // value to the new <name> element's value. (Of course, this could have
144: // been done with a StringBuffer, but that wouldn't show the cursor in
145: // use.)
146: while (pathCursor.toNextSelection()) {
147: namesCursor.insertChars(pathCursor.getTextValue());
148: if (pathCursor.hasNextSelection()) {
149: namesCursor.insertChars(", ");
150: }
151: }
152: // Dispose of the cursors now that they're not needed.
153: pathCursor.dispose();
154: namesCursor.dispose();
155:
156: // Print the new element.
157: System.out
158: .println("\nNames collected by collectNames method: \n\n"
159: + namesElement + "\n");
160: }
161: return hasResults;
162: }
163: }
|