1 /* Copyright 2004 The Apache Software Foundation 2 * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 package org.apache.xmlbeans.samples.xquery; 17 18 import org.apache.xmlbeans.XmlCursor; 19 import org.apache.xmlbeans.XmlObject; 20 21 /** 22 * This class demonstrates how to use the execQuery method to execute XQuery 23 * expressions. Compare the code here with the code in the SelectPath class. 24 * That class uses the selectPath method to execute XPath expressions. 25 * <p/> 26 * You can call the execQuery method from either an XmlObject or XmlCursor 27 * instance. Calling from XmlObject returns an XmlObject array. Calling 28 * from XmlCursor returns a new XmlCursor instance positioned at the root 29 * of a fragment containing copies of the XML queried against. Results of the 30 * query (if any) are sibling children of the fragment's root. 31 */ 32 public class ExecQuery 33 { 34 final static String m_namespaceDeclaration = 35 "declare namespace xq='http://xmlbeans.apache.org/samples/xquery/employees';"; 36 37 /** 38 * Uses XQuery to retrieve work <phone> elements from the incoming XML, then 39 * changes the number in the results. 40 * 41 * This method demonstrates the following characteristics of the execQuery method: 42 * 43 * - it supports XQuery. 44 * - the XML it returns is a copy of the XML queried against; contrast this with 45 * the selectPath method, which returns a portion of the original document. 46 * Changes to returned XML do not impact the XML queried against. 47 * - execQuery called from an XmlCursor returns a cursor positioned at 48 * the STARTDOC token of a new XML fragment. Contrast this with the 49 * XmlCursor.selectPath method, which stores results as "selections" in 50 * the cursor used to execute the query. 51 * 52 * @param empDoc The incoming XML. 53 * @return <code>true</code> if the XPath expression returned results; 54 * otherwise, <code>false</code>. 55 */ 56 public boolean updateWorkPhone(XmlObject empDoc) 57 { 58 boolean hasResults = false; 59 60 // A cursor instance to query with. 61 XmlCursor empCursor = empDoc.newCursor(); 62 63 // The expression: Get the <employee> elements with <state> elements whose 64 // value is "WA". 65 String queryExpression = 66 "for $e in $this/xq:employees/xq:employee " + 67 "let $s := $e/xq:address/xq:state " + 68 "where $s = 'WA' " + 69 "return $e//xq:phone[@location='work']"; 70 71 // Execute the query. Results, if any, will be available at 72 // the position of the resultCursor in a new XML document. 73 XmlCursor resultCursor = 74 empCursor.execQuery(m_namespaceDeclaration + queryExpression); 75 76 System.out.println("The query results, <phone> element copies made " + 77 "from the received document: \n"); 78 System.out.println(resultCursor.getObject().toString() + "\n"); 79 80 // If there are results, the results will be children of the fragment root 81 // where the new cursor is positioned. This statement tests for children 82 // and moves the cursor if to the first if it exists. 83 if (resultCursor.toFirstChild()) 84 { 85 hasResults = true; 86 // Use the cursor to loop through the results, printing each sibling 87 // <employee> element returned by the query. 88 int i = 0; 89 do 90 { 91 // Change the phone numbers. 92 XmlCursor editCursor = resultCursor.newCursor(); 93 editCursor.toLastAttribute(); 94 editCursor.toNextToken(); 95 editCursor.removeXml(); 96 editCursor.insertChars("(206)555-1234"); 97 } while (resultCursor.toNextSibling()); 98 99 resultCursor.toStartDoc(); 100 System.out.println("The query results after changes: \n"); 101 System.out.println(resultCursor.getObject().toString() + "\n"); 102 103 System.out.println("The received document -- note that it is unchanged. " + 104 "Changes were made to the copy created by the execQuery method. \n"); 105 System.out.println(empDoc + "\n"); 106 } 107 return hasResults; 108 } 109 110 /** 111 * Uses XQuery to retrieve work <zip> elements from the incoming XML, adding the 112 * elements as children to a <zip-list> element. 113 * 114 * This method demonstrates the following characteristics of the execQuery method: 115 * 116 * - it supports XQuery. 117 * - execQuery called from an XmlObject returns an array of XmlObject instances. 118 * These are bound to copies of the received XML. 119 * 120 * @param empDoc The incoming XML. 121 * @return <code>true</code> if the XPath expression returned results; 122 * otherwise, <code>false</code>. 123 */ 124 public boolean collectZips(XmlObject empDoc) 125 { 126 // The query is designed to return results, so return 127 // true if it does. 128 boolean hasResults = false; 129 130 // The expression: Get the <zip> elements and return them as children 131 // of a new <zip-list> element. 132 String queryExpression = 133 "let $e := $this/xq:employees " + 134 "return " + 135 "<zip-list> " + 136 "{for $z in $e/xq:employee/xq:address/xq:zip " + 137 "return $z} " + 138 "</zip-list>"; 139 140 // Execute the query. Results will be copies of the XML queried against, 141 // stored as members of an XmlObject array. 142 XmlObject[] results = 143 empDoc.execQuery(m_namespaceDeclaration + queryExpression); 144 145 // Print the results. 146 if (results.length > 0) 147 { 148 hasResults = true; 149 System.out.println("The query results: \n"); 150 System.out.println(results[0].toString() + "\n"); 151 } 152 return hasResults; 153 } 154 }