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:
021: /**
022: * This class demonstrates how to use the execQuery method to execute XQuery
023: * expressions. Compare the code here with the code in the SelectPath class.
024: * That class uses the selectPath method to execute XPath expressions.
025: * <p/>
026: * You can call the execQuery method from either an XmlObject or XmlCursor
027: * instance. Calling from XmlObject returns an XmlObject array. Calling
028: * from XmlCursor returns a new XmlCursor instance positioned at the root
029: * of a fragment containing copies of the XML queried against. Results of the
030: * query (if any) are sibling children of the fragment's root.
031: */
032: public class ExecQuery {
033: final static String m_namespaceDeclaration = "declare namespace xq='http://xmlbeans.apache.org/samples/xquery/employees';";
034:
035: /**
036: * Uses XQuery to retrieve work <phone> elements from the incoming XML, then
037: * changes the number in the results.
038: *
039: * This method demonstrates the following characteristics of the execQuery method:
040: *
041: * - it supports XQuery.
042: * - the XML it returns is a copy of the XML queried against; contrast this with
043: * the selectPath method, which returns a portion of the original document.
044: * Changes to returned XML do not impact the XML queried against.
045: * - execQuery called from an XmlCursor returns a cursor positioned at
046: * the STARTDOC token of a new XML fragment. Contrast this with the
047: * XmlCursor.selectPath method, which stores results as "selections" in
048: * the cursor used to execute the query.
049: *
050: * @param empDoc The incoming XML.
051: * @return <code>true</code> if the XPath expression returned results;
052: * otherwise, <code>false</code>.
053: */
054: public boolean updateWorkPhone(XmlObject empDoc) {
055: boolean hasResults = false;
056:
057: // A cursor instance to query with.
058: XmlCursor empCursor = empDoc.newCursor();
059: empCursor.toNextToken();
060:
061: // The expression: Get the <employee> elements with <state> elements whose
062: // value is "WA".
063: String queryExpression = "for $e in $this/xq:employees/xq:employee "
064: + "let $s := $e/xq:address/xq:state "
065: + "where $s = 'WA' "
066: + "return $e//xq:phone[@location='work']";
067:
068: // Execute the query. Results, if any, will be available at
069: // the position of the resultCursor in a new XML document.
070: XmlCursor resultCursor = empCursor
071: .execQuery(m_namespaceDeclaration + queryExpression);
072:
073: System.out
074: .println("The query results, <phone> element copies made "
075: + "from the received document: \n");
076: System.out.println(resultCursor.getObject().toString() + "\n");
077:
078: // If there are results, the results will be children of the fragment root
079: // where the new cursor is positioned. This statement tests for children
080: // and moves the cursor if to the first if it exists.
081: if (resultCursor.toFirstChild()) {
082: hasResults = true;
083: // Use the cursor to loop through the results, printing each sibling
084: // <employee> element returned by the query.
085: int i = 0;
086: do {
087: // Change the phone numbers.
088: XmlCursor editCursor = resultCursor.newCursor();
089: editCursor.toLastAttribute();
090: editCursor.toNextToken();
091: editCursor.removeXml();
092: editCursor.insertChars("(206)555-1234");
093: } while (resultCursor.toNextSibling());
094:
095: resultCursor.toStartDoc();
096: System.out.println("The query results after changes: \n");
097: System.out.println(resultCursor.getObject().toString()
098: + "\n");
099:
100: System.out
101: .println("The received document -- note that it is unchanged. "
102: + "Changes were made to the copy created by the execQuery method. \n");
103: System.out.println(empDoc + "\n");
104: }
105: return hasResults;
106: }
107:
108: /**
109: * Uses XQuery to retrieve work <zip> elements from the incoming XML, adding the
110: * elements as children to a <zip-list> element.
111: *
112: * This method demonstrates the following characteristics of the execQuery method:
113: *
114: * - it supports XQuery.
115: * - execQuery called from an XmlObject returns an array of XmlObject instances.
116: * These are bound to copies of the received XML.
117: *
118: * @param empDoc The incoming XML.
119: * @return <code>true</code> if the XPath expression returned results;
120: * otherwise, <code>false</code>.
121: */
122: public boolean collectZips(XmlObject empDoc) {
123: // The query is designed to return results, so return
124: // true if it does.
125: boolean hasResults = false;
126:
127: // The expression: Get the <zip> elements and return them as children
128: // of a new <zip-list> element.
129: String queryExpression = "let $e := $this/xq:employees "
130: + "return " + "<zip-list> "
131: + "{for $z in $e/xq:employee/xq:address/xq:zip "
132: + "return $z} " + "</zip-list>";
133:
134: // Execute the query. Results will be copies of the XML queried against,
135: // stored as members of an XmlObject array.
136: XmlObject[] results = empDoc.execQuery(m_namespaceDeclaration
137: + queryExpression);
138:
139: // Print the results.
140: if (results.length > 0) {
141: hasResults = true;
142: System.out.println("The query results: \n");
143: System.out.println(results[0].toString() + "\n");
144: }
145: return hasResults;
146: }
147: }
|