/* 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. */ package org.apache.xmlbeans.samples.xquery; import org.apache.xmlbeans.XmlCursor; import org.apache.xmlbeans.XmlObject; /** * This class demonstrates how to use the execQuery method to execute XQuery * expressions. Compare the code here with the code in the SelectPath class. * That class uses the selectPath method to execute XPath expressions. * <p/> * You can call the execQuery method from either an XmlObject or XmlCursor * instance. Calling from XmlObject returns an XmlObject array. Calling * from XmlCursor returns a new XmlCursor instance positioned at the root * of a fragment containing copies of the XML queried against. Results of the * query (if any) are sibling children of the fragment's root. */ public class ExecQuery { final static String m_namespaceDeclaration = "declare namespace xq='http://xmlbeans.apache.org/samples/xquery/employees';"; /** * Uses XQuery to retrieve work <phone> elements from the incoming XML, then * changes the number in the results. * * This method demonstrates the following characteristics of the execQuery method: * * - it supports XQuery. * - the XML it returns is a copy of the XML queried against; contrast this with * the selectPath method, which returns a portion of the original document. * Changes to returned XML do not impact the XML queried against. * - execQuery called from an XmlCursor returns a cursor positioned at * the STARTDOC token of a new XML fragment. Contrast this with the * XmlCursor.selectPath method, which stores results as "selections" in * the cursor used to execute the query. * * @param empDoc The incoming XML. * @return <code>true</code> if the XPath expression returned results; * otherwise, <code>false</code>. */ public boolean updateWorkPhone(XmlObject empDoc) { boolean hasResults = false; // A cursor instance to query with. XmlCursor empCursor = empDoc.newCursor(); // The expression: Get the <employee> elements with <state> elements whose // value is "WA". String queryExpression = "for $e in $this/xq:employees/xq:employee " + "let $s := $e/xq:address/xq:state " + "where $s = 'WA' " + "return $e//xq:phone[@location='work']"; // Execute the query. Results, if any, will be available at // the position of the resultCursor in a new XML document. XmlCursor resultCursor = empCursor.execQuery(m_namespaceDeclaration + queryExpression); System.out.println("The query results, <phone> element copies made " + "from the received document: \n"); System.out.println(resultCursor.getObject().toString() + "\n"); // If there are results, the results will be children of the fragment root // where the new cursor is positioned. This statement tests for children // and moves the cursor if to the first if it exists. if (resultCursor.toFirstChild()) { hasResults = true; // Use the cursor to loop through the results, printing each sibling // <employee> element returned by the query. int i = 0; do { // Change the phone numbers. XmlCursor editCursor = resultCursor.newCursor(); editCursor.toLastAttribute(); editCursor.toNextToken(); editCursor.removeXml(); editCursor.insertChars("(206)555-1234"); } while (resultCursor.toNextSibling()); resultCursor.toStartDoc(); System.out.println("The query results after changes: \n"); System.out.println(resultCursor.getObject().toString() + "\n"); System.out.println("The received document -- note that it is unchanged. " + "Changes were made to the copy created by the execQuery method. \n"); System.out.println(empDoc + "\n"); } return hasResults; } /** * Uses XQuery to retrieve work <zip> elements from the incoming XML, adding the * elements as children to a <zip-list> element. * * This method demonstrates the following characteristics of the execQuery method: * * - it supports XQuery. * - execQuery called from an XmlObject returns an array of XmlObject instances. * These are bound to copies of the received XML. * * @param empDoc The incoming XML. * @return <code>true</code> if the XPath expression returned results; * otherwise, <code>false</code>. */ public boolean collectZips(XmlObject empDoc) { // The query is designed to return results, so return // true if it does. boolean hasResults = false; // The expression: Get the <zip> elements and return them as children // of a new <zip-list> element. String queryExpression = "let $e := $this/xq:employees " + "return " + "<zip-list> " + "{for $z in $e/xq:employee/xq:address/xq:zip " + "return $z} " + "</zip-list>"; // Execute the query. Results will be copies of the XML queried against, // stored as members of an XmlObject array. XmlObject[] results = empDoc.execQuery(m_namespaceDeclaration + queryExpression); // Print the results. if (results.length > 0) { hasResults = true; System.out.println("The query results: \n"); System.out.println(results[0].toString() + "\n"); } return hasResults; } }