The XQuery Query Languages

It might seem odd, but the XML Query Language will have more than one syntax. One syntax will be expressed in non-XML syntax and the other, XQueryX, will be expressed in a syntax that is compliant with the requirements of XML version 1.0. The non-XML syntax, XQuery, will be more easily human readable, and will be similar to XPath syntax.

XQuery

XQuery is the non-XML syntax for the XML Query Language.

One form of XQuery query uses a path expression syntax, so called because of its close similarities to XPath 1.0 syntax.

For example, if you had a document called book.xml that contained several chapter elements—each of which had a title element nested within it—you could retrieve the title of all the chapters in the book by issuing a query similar to the following:

document("book.xml")//chapter/title 

Similarly, you could retrieve the titles of all appendixes in the book with a query such as

document("book.xml")//appendices/title 

XQuery expressions make extensive use of the so-called “flower” expressions. The name arises from the initials of the keywords FOR, LET, WHERE, and RETURN.

A FLWR expression uses at least two of the four keywords just mentioned. Because we will invariably want something to be returned (at least in non-update queries), the RETURN keyword will always be used.

Listing 20.5 shows a highly simplified inventory of items to which we can apply an XQuery query.

Listing 20.5. An Inventory of Items with Prices (Inventory.xml)
<?xml version='1.0'?>
<Inventory>
<Article>
 <Name>Article 1</Name>
 <Price>21.50</Price>
</Article>
<Article>
 <Name>Article 2</Name>
 <Price>41.00</Price>
</Article>
<Article>
 <Name>Article 3</Name>
 <Price>25.00</Price>
</Article>
<Article>
 <Name>Article 4</Name>
 <Price>55.00</Price>
</Article>
<Article>
 <Name>Article 5</Name>
 <Price>19.99</Price>
</Article>
<Article>
 <Name>Article 6</Name>
 <Price>21.50</Price>
</Article>
</Inventory>

A query to select all articles in which there was a unique value for the Price element that was less than 30.00 is shown in Listing 20.6.

Listing 20.6. Testing for Unique Values of the Price Element That Are Less Than 30.00 (ItemQuery.txt)
<Results>
  {
    FOR $Price in distinct-values(document("Inventory.xml")//Article/Price)
    LET $Name := $Price/../Name
    WHERE $Price < 30.00
    RETURN
      <Article price={ $Price/text() }>
        <Name>{ $Name/text() }</Name>
      </Article>
  }
</Results>

Let's walk through the query line by line. The first line indicates that a literal start tag for a Results element is to be output. The { character indicates the start of an XQuery expression.

The FOR statement applies the distinct-values() function to the result of applying the document() function to the file Inventory.xml and the path expression //Article/Price. If we review Listing 20.5, we see that the value of the Price element for the first and sixth Article elements is the same—21.50. Strictly, the choice of which of two nodes is discarded in this situation is up to an individual application. We will assume that the first is retained and the later duplicate is discarded.

Thus, we have five Price element nodes that satisfy line 3 of the code in Listing 20.6.

The LET statement simply assigns to the variable $Name the value of the Name element node, which is a sibling of the Price element used in the SPrice variable.

The WHERE statement applies a test to the value of the $Price variable. If its value is less than 30.00, the RETURN statement is applied. If its value is 30.00 or greater, the RETURN statement is bypassed.

The value contained in the Price element for the second and fourth articles exceeds 30.00. Therefore, the RETURN statement is bypassed for those articles.

For the first, third, and fifth articles, the RETURN statement causes a literal Article element to be output with a price attribute whose value is obtained from the XQuery expression $Price/text(). The content of each Article element also includes a Name element whose content is defined by the XQuery expression $Name/text().

Listing 20.7 shows the document output.

Listing 20.7. Results from Applying the Listing 20.6 Query to the Listing 20.5's Input Document (InventoryOut.xml)
<Inventory>
 <Article price="21.50">
  <Name>Article 1</Name>
 </Article>
 <Article price="25.00">
  <Name>Article 3</Name>
 </Article>
 <Article price="19.99">
  <Name>Article 5</Name>
 </Article>
</Inventory>

The FOR, LET, WHERE, and RETURN statements can be combined in potentially very complex nested constructs to allow multiple criteria to be applied in a single search.

XQueryX

One of the requirements contained in the XQuery Requirements document is that the functionality of XQuery should be expressed in an XML-based query syntax. XQueryX is the XML syntax currently under development at W3C.

At the time of writing, the XQueryX working draft has not been updated to take account of subsequent syntax changes in XQuery. Listing 20.8 is an example from the June 2001 Working Draft that shows equivalent XQuery and XQueryX syntax for a query.

Listing 20.8. A Query Expressed in XQuery (AQuery.txt)
FOR $b IN document("bib.xml")//book
WHERE $b/publisher = "Morgan Kaufmann" AND $b/year = "1998"
RETURN $b/title

Contrast that with Listing 20.9, which is expressed in XQueryX.

Listing 20.9. The Query of Listing 20.8 Expressed in XQueryX (AQuery.xml)
<?xml version='1.0'?>
<q:query xmlns:q="http://www.w3.org/2001/06/xqueryx">
  <q:flwr>
    <q:forAssignment variable="$b">
      <q:step axis="SLASHSLASH">
        <q:function name="document">
          <q:constant datatype="CHARSTRING">bib.xml</q:constant>
        </q:function>
        <q:identifier>book</q:identifier>
      </q:step>
    </q:forAssignment>
    <q:where>
      <q:function name="AND">
        <q:function name="EQUALS">
          <q:step axis="CHILD">
            <q:variable>$b</q:variable>
            <q:identifier>publisher</q:identifier>
          </q:step>
          <q:constant datatype="CHARSTRING">Morgan Kaufmann</q:constant>
        </q:function>
        <q:function name="EQUALS">
          <q:step axis="CHILD">
            <q:variable>$b</q:variable>
            <q:identifier>year</q:identifier>
          </q:step>
          <q:constant datatype="CHARSTRING">1998</q:constant>
        </q:function>
      </q:function>
    </q:where>
    <q:return>
      <q:step axis="CHILD">
        <q:variable>$b</q:variable>
        <q:identifier>title</q:identifier>
      </q:step>
    </q:return>
  </q:flwr>
</q:query>

The XQueryX version is obviously much more verbose than the XQuery version of the query. The XQuery version is also more readable. Apart from situations in which XQueryX is generated by, for example, XSLT, it is difficult to envisage XQueryX often being hand coded because of the sheer length of even simple queries.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.94.153