Basic XQuery Examples

This page contains a collection of simple XQuery examples which should give a first glimpse of what's possible with eXist and XQuery. To learn more about XQuery, we recommend to head over to the excellent XQuery Wikibook or buy one of the available books on XQuery.

Though the syntactic elements of XQuery can be learned quickly, it is a functional language and it may take some time to get a feel for it if you are coming from a procedural world.

Simple expressions using the full-text index

Find out where Juliet talks about love

In the following, Jon Bosak's edition of the Shakespeare's Hamlet, Macbeth, and Romeo and Juilet are queried..

    //SPEECH[ft:query(., 'love')][SPEAKER = "JULIET"]
            

Search for a phrase

    //SPEECH[ft:query(., '"fenny snake"')]

Find speeches in which "love" and "father" occur closely together, using XML query syntax:

let $query :=
    <query>
        <near slop="20"><term>love</term><near>father</near></near>
    </query>
return //SPEECH[ft:query(., $query)]
            

Find speeches in which "boil" and "bubble" occur, ordering them by full-text match score

for $m in //SPEECH[ft:query(., "boil bubble")]
let $score := ft:score($m)
order by $score descending
return <m score="{$score}">{$m}</m>

Functions and recursion

Compute the factorial of a given integer

xquery version "1.0";

declare function local:fact($n as xs:integer) {
    if ($n eq 1) then
        $n
    else
        $n * local:fact($n - 1)
};

local:fact(6)
            

Generating HTML

Create a 10x10 table and color the cells

xquery version "1.0";
(: $Id: table.xq 6434 2007-08-28 18:59:23Z ellefj $ :)
(: An example found in Saxon: creates a table with 10x10 cells :)

declare namespace f="http://my-namespaces.org";

declare function f:background-color($x as xs:double, $y as xs:integer)
as xs:string {    
	if($x mod 2 + $y mod 2 <= 0) then "lightgreen"
	else if($y mod 2 <= 0) then "yellow"
	else if($x mod 2 <= 0) then "lightblue"
	else "white"
};

<body>
	<table>{
	for $y in 1 to 10 return
		<tr>
		{
			for $x in 1 to 10 return
				let $bg := f:background-color($x, $y),
					$prod := $x * $y
				return
					<td bgcolor="{$bg}">
						{if ($y > 1 and $x > 1) then $prod else <b>{$prod}</b>}
					</td>
		}
		</tr>
	}</table>
</body>
            

Create a multiplication table

xquery version "1.0";
declare option exist:serialize "method=html5 media-type=text/html";
declare variable $max := 20;

<table border="1" width="100%">
    <th>1 x 1</th>
    {
        for $i in (1 to $max)
        return
            <th>{ $i}</th>
    }
      
    {
        for $a in (1 to $max)  
        return 
            <tr>
                <th>{ $a,"*"}</th>
                
                {
                    for $b in (1 to $max)
                    return
                        if ($a = $b) then
                            <td bgcolor="#F46978">{$a * $b}</td>
                        else if ($a mod 2) then
                            <td bgcolor="#A46978">{$a * $b}</td> 
                        else
                            <td bgcolor="#A09224">{$a * $b}</td> 
                }            
            </tr>
  
    }
</table>

Generate a list of the acts and scenes in Hamlet, with the roles appearing in each scene

declare option exist:serialize "method=html5 media-type=text/html";

<html>
    <body>{
        for $act in doc("/db/apps/demo/data/hamlet.xml")/PLAY/ACT
        return
            <ul>
                <li>
                    <h2>{$act/TITLE/text()}</h2>
                    <ul>
                    {
                        for $scene in $act/SCENE return
                            <li>
                                <h3>{$scene/TITLE/text()}</h3>
                                <ul>
                                {
                                    for $speaker in distinct-values($scene//SPEAKER)
                                    order by $speaker return
                                        <li>{$speaker}</li>
                                }
                                </ul>
                            </li>
                    }
                    </ul>
                </li>
            </ul>
    }</body>
</html>

To view the output of this query as HTML, save it to the database from within eXide, e.g. as /db/test.xql. You can then call it by entering the following URL into your browser:

http://localhost:8080/exist/rest/db/test.xql

Querying a database

The following queries use the Mondial database, a data set compiled by the Universität Göttingen.

For each country, list the 3 cities with the highest population

(:  This script accesses the mondial database, which can be
    found at http://dbis.informatik.uni-goettingen.de/Mondial/ :)
for $country in /mondial/country
let $cities := 
    (for $city in $country//city[population] 
    order by xs:integer($city/population[1]) descending 
    return $city)
order by $country/name
return
    <country name="{$country/name}">
    {
        subsequence($cities, 1, 3)
    }
    </country>

Find all Spanish provinces and their cities

xquery version "1.0";

let $country := /mondial/country[name = 'Spain']
for $province in $country/province
order by $province/name
return
    <province>
    	{$province/name}
		{
			for $city in $country//city[@province=$province/@id]
			order by $city/name
			return $city
		}
	</province>
            

Find the countries with the largest Roman Catholic population

for $country in /mondial/country
where some $r in $country/religions satisfies $r = "Roman Catholic"
order by $country/religions[. = "Roman Catholic"]/@percentage cast as xs:double descending
return
  <country name="{$country/name}">
    {$country/religions}
  </country>