Chapter 2 Examples
This chapter introduces X-OQL. It describes and illustrates basic
queries, and shows how they can be used to build more elaborate
ones.
In the following examples, we will consider two simple XML
documents, products.xml and persons.xml. Their
contents are given in Figures 2.1 and
2.2.
You can run these queries by starting the X-OQL console:
> java xoql.Console examples
<products>
<product reference="012458796">
<type> tv-set</type>
<description> a great color tv set </description>
<price>200</price>
<sales>
<sale>
<vendor> mike </vendor>
<date> 12-24-1998 </date>
</sale>
<sale>
<vendor>john</vendor>
<date>12-20-1998</date>
</sale>
</sales>
</product>
<product reference="6987654">
<description> video tape recorder </description>
<price>200</price>
<sale>
<vendor>mike</vendor>
</sale>
</product>
</products>
Figure 2.1: The products.xml example document
<persons>
<manager id="fbogus">
<first-name> fred </first-name>
<last-name> bogus </last-name>
</manager>
<vendors>
<vendor id="mike" manager="fbogus">
<age> 24 </age>
<salary>5000</salary>
<commission> 3000 </commission>
</vendor>
<vendor id="john" manager="fbogus">
<age/>
<salary> 10000 </salary>
</vendor>
</vendors>
<customers>
<customer>
<name> bart simpson </name>
<address> 10, down street </address>
<customs>
<custom> a tv set </custom>
</customs>
</customer>
</customers>
</persons>
Figure 2.2: The persons.xml example document
X-OQL allows querying denotable objects starting from their names, wich act as entry points into a
collection of XML documents. We will further call a datasource a dictionary in which some names have been defined in
order to denote some DOM nodes. Figure 2.3 illustrates the
use of a datasource to address the two example documents.
The
products document is supposed to be stored in a DOM compliant XML
repository, whereas the persons document is represented as a
in-memory DOM tree. The name vendors denotes the
root node of the corresponding subtree of the persons
document. Note that the name of the named object
vendors is the same as the label of the corresponding
node. This is an arbitrary choice, made for clarity and
consistency reasons.
Figure 2.3: A datasource
2.1 Datasource entry points
The simplest X-OQL query simply consists of an entry point:
customers;
Since the datasource contains an entry point whose name is customers, the result is:
<result>
<customers>
<customer>
<name> bart simpson </name>
<address> 10, down street </address>
<customs>
<custom> a tv set </custom>
</customs>
</customer>
</customers>
</result>
2.2 Simple queries
2.3 Path Expressions
One can enter a document through a named object. It is then
convenient to use a form of navigation based on path
expressions. The idea is to specify paths in the DOM tree based
on the sequence of labels on nodes. We describe here simple
path expressions, which allow users to obtain the set of nodes
reachable by following a sequence of labels starting from a named
object. A more powerful form of path expressions based on regular
expressions is described in the sequel.
2.3.1 Accessing subelements
To do this, we use the / operator, wich enables us to go inside
complex documents. For instance, the query :
vendors/vendor/salary;
means: start from the named object vendors, go inside the vendor
set of nodes to get and finally retrieve the salary subnodes. Its
result is:
<result>
<salary>5000</salary >
<salary>10000</salary>
</result>
Note that here we copied the data from the original document in
order to build the result. We can do better by
dealing with references into the original document. For instance,
using XLink/XPointer notation, the resulting document would be:
<result>
<link xml:link = "persons.xml/child(2).(1).(2)">
<link xml:link = "persons.xml/child(2).(2).(2)">
</result>
Such more complx results can be obtained using X-OQL as an embedded language
into a Java program.
2.3.2 Accessing attributes
Attributes can be accessed using the @ operator. For instance:
vendors/vendor/@id
retrieves the id attributes of the vendor elements, starting from
the named object vendors.
2.4 Select From Where construct
The basic syntax of X-OQL is based on OQL and illustrated with
the following query:
select v
from v in vendors/vendor;
Informally, the semantic of the query is to bind the variable v
to each node specified by the path expression.
<result>
<vendor
id="mike"
manager="fbogus">
<age>24</age>
<salary>5000</salary>
<commission>
3000
</commission>
</vendor>
<vendor
id="john"
manager="fbogus">
<age/>
<salary>10000</salary>
</vendor>
</result>
In our next example, we restrict the output by use of a condition
in the where clause of the query:
select v
from v in vendors/vendor
where v/age <= 24;
<result>
<vendor id="mike" manager="fbogus" >
<age> 24 </age>
<salary> 5000 </salary>
<commission> 3000 </commission>
</vendor>
</result>
In general, the semantics of a query select E from B where
P is defined in three steps. The first deals with from, the
second with where and the third with select. Assume that B
defines three variables X, Y and Z. In the first step, we
find the step of all bindings of those variables specified by
B. In the second step, we filter the bindings that satisfy
P. In the last step, we construct the expression which form
the result.
More formally, the general form of a select-from-where construct
is:
select e1(Y,X) ,..., em(Y,X)
from x1 in b1(Y), x2 in b2(Y,x1) ,..., xn in bn(Y,x1,..,xn-1)
where p(Y,X)
where
Y=(y1,..,yk) denotes the set of variables defined outside
the scope of this expression. In the particuliar case of a
standalone query, Y denotes the datasource.
X=(x1,...,xn) denotes the set of variables defined in the
from clause.
p is a boolean expression depending on the variable sets X and Y.
e1,...,em are X-OQL queries depending on the variable sets X
and Y.
b1,...,bn are X-OQL queries depending respectively on
variables (y1,...,yk),...,(y1,...,yk,x1,...,xn-1).
2.5 Predicates
The where clause can be used to define any predicate, that serves
to select data matching the predicate. Complex conditions can be
expressed using the boolean negation not and the boolean
connectors and, or.
2.6 Constructing elements
One can construct new elements, using a construct statement. The
basic syntax for constructing a new element is the following query:
<foo> bar </>;
that means "create an element with tag value foo and content
bar ". Its result is:
<result>
<foo>
bar
</foo>
</result>
Nested constructs can be used, like in:
<foo id="foo1">
<bar>
Hello
</>
, "World"
</>
that produces :
<result>
<foo id="foo1">
<bar>
Hello
</bar>
World
</foo>
</result>
The general form of a construct statement is:
<ename {attname = attvalue }>
[ econtent {, econtent ] }
</>
where ename, econtent, attname and attvalue are valid
X-OQL queries.
2.7 Joins
In the from clause, collections that are not directly related can be declared. As in SQL, this allows computation of joins between these collections. This example selects the sales made by each vendor, using a nested query to group them by vendor.
select
<v/@id>
select
<sold> p/@reference </>
from p in products/product
where p//vendor = v/@ID
</>
from v in vendors/vendor;
The meaning of this query is: for each vendor in vendors, denoted
as v, create a new element. The name of this element is given by
the query v/@id. Its content is the result of the evaluation of
the query:
select
<sold> p/@reference </>
from p in products/product
where p//vendor = v/@ID
for each product in products, denoted as p, if the value of one
vendor subelement of p equals to the value of v/@id, create an
element named sold, containing the value of the reference
attribute of p.
The whole query gives for result:
<result>
<mike>
<sold> 012458796 </sold>
<sold> 6987654 </sold>
</mike>
<John>
<sold> 012458796 </sold>
</John>
</result>