blob: a5e13f84242eaf04c1b40f2ebb5a5cf592def525 [file] [log] [blame]
<!doctype HTML public "-//W3C//DTD HTML 4.0 Frameset//EN">
<html>
<head>
<!-- InstanceBeginEditable name="doctitle" -->
<title>Selecting XML with XQuery and XPath</title>
<!-- InstanceEndEditable -->
<!--(Meta)==========================================================-->
<meta http-equiv=Content-Type content="text/html; charset=$CHARSET;">
<!-- InstanceBeginEditable name="metatags" -->
<meta content="your name" name="author">
<meta content="A description of the topic contents." name="description">
<meta content="keywords to help in searches" name="keywords">
<meta content="10/25/02" name="date last modified">
<!-- InstanceEndEditable -->
<!--(Links)=========================================================-->
<!-- InstanceBeginEditable name="head" -->
<link href="../xmlbeans.css" rel="stylesheet" type="text/css">
<!-- InstanceEndEditable -->
<link href="../xmlbeans.css" rel="stylesheet" type="text/css">
<a href="../../../core/index.html" id="index"></a>
<script language="JavaScript" src="../../../core/topicInfo.js"></script>
<script language="JavaScript" src="../../../core/CookieClass.js"></script>
<script language="JavaScript" src="../../../core/displayContent.js"></script>
</head>
<!--(Body)==========================================================-->
<body>
<script language="JavaScript">
</script>
<!-- InstanceBeginEditable name="body" -->
<h1> Selecting XML with XQuery and XPath</h1>
<div id="topictext">
<p>You can use XQuery and XPath to retrieve specific pieces of XML as you might
retrieve data from a database. XQuery and XPath provide a syntax for specifying
which elements and attributes you're interested in. The XMLBeans API provides
two methods for executing XQuery and XPath expressions, and two differing
ways to use them. The methods are <span class="langinline">selectPath</span>
and <span class="langinline">execQuery</span>, and you can call them from
<a href="../reference/org/apache/xmlbeans/XmlObject.html"><span class="langinline">XmlObject</span></a>
(or an object inheriting from it) or <a href="../reference/org/apache/xmlbeans/XmlCursor.html"><span class="langinline">XmlCursor</span></a>.
The results for the methods differ somewhat. </p>
<h2>Using the selectPath Method</h2>
</div>
<div>
<p>The <span class="langinline">selectPath</span> method is the most efficient
way to execute XPath expressions. The <span class="langinline">selectPath</span>
method is optimized for XPath. When you use XPath with the <span class="langinline">selectPath</span>
method, the value returned is an array of values from the <em>current document</em>.
In contrast, when you use <span class="langinline">execQuery</span>, the value
returned is a <em>new document</em>.</p>
<h3>Calling from XmlObject</h3>
<p>When called from <span class="langinline">XmlObject</span> (or a type that
inherits from it), this method returns an array of objects. If the expression
is executed against types generated from schema, then the type for the returned
array is one of the Java types corresponding to the schema. </p>
<p>For example, imagine you have the following XML containing employee information.
You've compiled the schema describing this XML and the types generated from
schema are available to your code.</p>
<pre>
&lt;xq:employees xmlns:xq=&quot;http://openuri.org/selectPath&quot;&gt;
&lt;xq:employee&gt;
&lt;xq:name&gt;Fred Jones&lt;/xq:name&gt;
&lt;xq:address location=&quot;home&quot;&gt;
&lt;xq:street&gt;900 Aurora Ave.&lt;/xq:street&gt;
&lt;xq:city&gt;Seattle&lt;/xq:city&gt;
&lt;xq:state&gt;WA&lt;/xq:state&gt;
&lt;xq:zip&gt;98115&lt;/xq:zip&gt;
&lt;/xq:address&gt;
&lt;xq:address location=&quot;work&quot;&gt;
&lt;xq:street&gt;2011 152nd Avenue NE&lt;/xq:street&gt;
&lt;xq:city&gt;Redmond&lt;/xq:city&gt;
&lt;xq:state&gt;WA&lt;/xq:state&gt;
&lt;xq:zip&gt;98052&lt;/xq:zip&gt;
&lt;/xq:address&gt;
&lt;xq:phone location=&quot;work&quot;&gt;(425)555-5665&lt;/xq:phone&gt;
&lt;xq:phone location=&quot;home&quot;&gt;(206)555-5555&lt;/xq:phone&gt;
&lt;xq:phone location=&quot;mobile&quot;&gt;(206)555-4321&lt;/xq:phone&gt;
&lt;/xq:employee&gt;
&lt;/xq:employees&gt;
</pre>
If you wanted to find the phone numbers whose area code was 206, you could capture
the XPath expression in this way:
<pre>
String queryExpression =
&quot;declare namespace xq='http://openuri.org/selectPath'&quot; +
&quot;$this/xq:employees/xq:employee/xq:phone[contains(., '(206)')]&quot;
</pre>
<p>Notice in the query expression that the variable <span class="langinline">$this</span>
represents the current context node (the <span class="langinline">XmlObject</span>
that you are querying from). In this example you are querying from the document
level <span class="langinline">XmlObject</span>.</p>
<p>You could then print the results with code such as the following:</p>
<pre>
/*
* Retrieve the matching phone elements and assign the results to the corresponding
* generated type.
*/
PhoneType[] phones = (PhoneType[])empDoc.selectPath(queryExpression);
/*
* Loop through the results, printing the value of the phone element.
*/
for (int i = 0; i < phones.length; i++)
{
System.out.println(phones[i].stringValue());
} </pre>
<h3>Calling from XmlCursor</h3>
<p>When called from an <span class="langinline">XmlCursor</span> instance, the
<span class="langinline">selectPath</span> method retrieves a list of selections,
or locations in the XML. The selections are remembered by the cursor instance.
You can use methods such as <span class="langinline">toNextSelection</span>
to navigate among them.</p>
<div>
<p>The <span class="langinline">selectPath</span> method takes an XPath expression.
If the expression returns any results, each of those results is added as
a selection to the cursor's list of selections. You can move through these
selections in the way you might use <span class="langinline">java.util.Iterator</span>
methods to move through a collection.</p>
<p> For example, for a path such as <span class="langinline">$this/employees/employee</span>,
the results would include a selection for each employee element found by
the expression. Note that the variable <span class="langinline">$this</span>
is always bound to the current context node, which in this example is the
document. After calling the <span class="langinline">selectPath</span> method,
you would use various &quot;selection&quot;-related methods to work with
the results. These methods include:</p>
</div>
<ul>
<li>
<div><span class="langinline">getSelectionCount() </span>to retrieve the
number of selections resulting from the query.</div>
</li>
<li>
<div> <span class="langinline">toNextSelection()</span> to move the cursor
to the next selection in the list (such as to the one pointing at the
next employee element found).</div>
</li>
<li>
<div> <span class="langinline">toSelection(int)</span> to move the cursor
to the selection at the specified index (such as to the third employee
element in the selection).</div>
</li>
<li>
<div> <span class="langinline">hasNextSelection()</span> to find out if
there are more selections after the cursor's current position.</div>
</li>
<li>
<div><span class="langinline"> clearSelections()</span> clears the selections
from the current cursor. This doesn't modify the document (in other words,
it doesn't delete the selected XML); it merely clears the selection list
so that the cursor is no longer keeping track of those positions.</div>
</li>
</ul>
<div>
<p>The following example shows how you might use <span class="langinline">selectPath</span>,
in combination with the <span class="langinline">push</span> and <span class="langinline">pop</span>
methods, to maneuver through XML, retrieving specific values. </p>
<pre>
public void printZipsAndWorkPhones(XmlObject xml)
{
// Declare the namespace that will be used.
String xqNamespace =
&quot;declare namespace xq='http://openuri.org/selectPath'&quot;;
// Insert a cursor and move it to the first element.
XmlCursor cursor = xml.newCursor();
cursor.toFirstChild();
/*
* Save the cursor's current location by pushing it
* onto a stack of saved locations.
*/
cursor.push();
// Query for zip elements.
cursor.selectPath(xqNamespace + &quot;$this//xq:zip&quot;);
/*
* Loop through the list of selections, getting the value of
* each element.
*/
while (cursor.toNextSelection())
{
System.out.println(cursor.getTextValue());
}
// Pop the saved location off the stack.
cursor.pop();
// Query again from the top, this time for work phone numbers.
cursor.selectPath(xqNamespace + &quot;$this//xq:phone[@location='work']&quot;);
/*
* Move the cursor to the first selection, them print that element's
* value.
*/
cursor.toNextSelection();
System.out.println(cursor.getTextValue());
// Dispose of the cursor.
cursor.dispose();
}
</pre>
<p>Using selections is somewhat like tracking the locations of multiple cursors
with a single cursor. This becomes especially clear when you remove the
XML associated with a selection. When you do so the selection itself remains
at the location where the removed XML was, but now the selection's location
is immediately before the XML that was after the XML you removed. In other
words, removing XML created a kind of vacuum that was filled by the XML
after it, which shifted up into the space &#8212; up into position immediately
after the selection location. This is exactly the same as if the selection
had been another cursor.</p>
<p>Finally, when using selections keep in mind that the list of selections
is in a sense &quot;live&quot;. The cursor you're working with is keeping
track of the selections in the list. In other words, be sure to call the
<span class="langinline">clearSelections</span> method when you're finished
with the selections, just as you should call the <span class="langinline">XmlCursor.dispose()</span>
method when you're finished using the cursor.</p>
</div>
<h2>Using the execQuery Method</h2>
<p>Use the <span class="langinline">execQuery</span> method to execute XQuery
expressions that are more sophisticated than paths. These expressions include
more sophisticated loops and FLWR (For, Let, Where, and Results) expressions.
</p>
<p class="notepara"><strong>Note:</strong> Be sure to see the simpleExpressions
sample in the SamplesApp application for a sampling of XQuery expressions
in use.</p>
<h3>Calling from XmlObject</h3>
<p>Unlike <span class="langinline">selectPath</span>, calling <span class="langinline">execQuery</span>
from an <span class="langinline">XmlObject</span> instance will return an
<span class="langinline">XmlObject</span> array. If the <span class="langinline">XmlObject</span>
instances resulting from the XQuery match a recognized XMLBeans type (the
namespace and top level element name match up with an XMLBeans type) then
the <span class="langinline">XmlObject</span> will be typed; otherwise the
<span class="langinline">XmlObject</span> will be untyped.</p>
<h3>Calling from XmlCursor</h3>
</div>
<div>
<p>Calling <span class="langinline">execQuery</span> from an <span class="langinline">XmlCursor</span>
instance returns a new <span class="langinline">XmlCursor</span> instance.
The cursor returned is positioned at the beginning of a new xml document representing
the query results, and you can use it to move through the results, cursor-style
(for more information, see <a href="conNavigatingXMLwithCursors.html">Navigating
XML with Cursors</a>). If the document resulting from the query execution
represents a recognized XMLBeans type (the namespace and top level element
name match up with an XMLBeans type) then the document resulting from the
xquery will have that Java type; otherwise the resulting document will be
untyped.</p>
<h2>Related Topics</h2>
</div>
<p><a href="conGettingStartedwithXMLBeans.html">Getting Started with XMLBeans</a></p>
<!-- InstanceEndEditable -->
<script language="JavaScript">
</script>
</body>
</html>