blob: cf399384d459940d7063e45df1d25908e7c5c0eb [file] [log] [blame]
/* 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;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.samples.xquery.employees.PhoneType;
/**
* This class demonstrates how to use the selectPath method to execute XPath
* expressions. Compare the code here with the code in the ExecQuery class.
* That class uses the execQuery method to execute XQuery expressions.
* <p/>
* You can call the selectPath method from either an XmlObject or XmlCursor
* instance. Calling from XmlObject returns an XmlObject array. Calling
* from XmlCursor returns void, and you use methods of the cursor to
* navigate among returned "selections".
*/
public class SelectPath
{
// Declare a namespace corresponding to the namespace declared in the XML
// instance. The string here will be used as part of the XPath expression to
// ensure that the query finds namespace-qualified elements in the XML.
final static String m_namespaceDeclaration =
"declare namespace xq='http://xmlbeans.apache.org/samples/xquery/employees';";
/**
* Prints the XML bound to <em>empDoc</em>, uses XPath to
* retrieve elements containing work phone numbers, changes the numbers
* to another number, then prints the XML again to display the changes.
*
* This method demonstrates the following characteristics of the selectPath method:
*
* - it supports expressions that include predicates
* - the XML it returns is the XML queried against -- not a copy, as with results
* returned via execQuery methods and XQuery. Changes to this XML update
* the XML queried against.
* - selectPath called from an XMLBean type (instead of a cursor) returns an
* array of results (if any). These results can be cast to a matching type
* generated from schema.
*
* @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;
// Print the XML received.
System.out.println("XML as received by updateWorkPhone method: \n\n"
+ empDoc.toString());
// Create a variable with the query expression.
String pathExpression =
"$this/xq:employees/xq:employee/xq:phone[@location='work']";
// Execute the query.
XmlObject[] results = empDoc.selectPath(m_namespaceDeclaration
+ pathExpression);
if (results.length > 0)
{
hasResults = true;
// <phone> elements returned from the expression will conform to the
// schema, so bind them to the appropriate XMLBeans type generated
// from the schema.
PhoneType[] phones = (PhoneType[]) results;
// Change all the work phone numbers to the same number.
for (int i = 0; i < phones.length; i++)
{
phones[i].setStringValue("(206)555-1234");
}
// Print the XML with updates.
System.out.println("\nXML as updated by updateWorkPhone method (each work \n" +
"phone number has been changed to the same number): \n\n"
+ empDoc.toString() + "\n");
}
return hasResults;
}
/**
* Uses the XPath text() function to get values from <name>
* elements in received XML, then collects those values as the value of a
* <names> element created here.
* <p/>
* Demonstrates the following characteristics of the selectPath method:
* <p/>
* - It supports expressions that include XPath function calls.
* - selectPath called from an XmlCursor instance (instead of an XMLBeans
* type) places results (if any) into the cursor's selection set.
*
* @param empDoc The incoming XML.
* @return <code>true</code> if the XPath expression returned results;
* otherwise, <code>false</code>.
*/
public boolean collectNames(XmlObject empDoc)
{
boolean hasResults = false;
// Create a cursor with which to execute query expressions. The cursor
// is inserted at the very beginning of the incoming XML, then moved to
// the first element's START token.
XmlCursor pathCursor = empDoc.newCursor();
pathCursor.toFirstChild();
// Execute the path expression, qualifying it with the namespace
// declaration.
pathCursor.selectPath(m_namespaceDeclaration
+ "$this//xq:employee/xq:name/text()");
// If there are results, then go ahead and do stuff.
if (pathCursor.getSelectionCount() > 0)
{
hasResults = true;
// Create a new <names> element into which names from the XML
// will be copied. Note that this element is in the default
// namespace; it's not part of the schema.
XmlObject namesElement = null;
try
{
namesElement = XmlObject.Factory.parse("<names/>");
} catch (XmlException e)
{
e.printStackTrace();
}
// Add a cursor the new element and put it between its START and END
// tokens, where new values can be inserted.
XmlCursor namesCursor = namesElement.newCursor();
namesCursor.toFirstContentToken();
namesCursor.toEndToken();
// Loop through the selections, appending the incoming <name> element's
// value to the new <name> element's value. (Of course, this could have
// been done with a StringBuffer, but that wouldn't show the cursor in
// use.)
while (pathCursor.toNextSelection())
{
namesCursor.insertChars(pathCursor.getTextValue());
if (pathCursor.hasNextSelection())
{
namesCursor.insertChars(", ");
}
}
// Dispose of the cursors now that they're not needed.
pathCursor.dispose();
namesCursor.dispose();
// Print the new element.
System.out.println("\nNames collected by collectNames method: \n\n"
+ namesElement + "\n");
}
return hasResults;
}
}