411 REFERENCE · Wikibooks
XQuery/Navigating Collections
Reference material by Wikibooks contributors. This retains its source identity and is not 411 news reporting.
Motivation
You want to browse collections using an HTML web page and narrow your choices as you type.
Method
We will first create a server-side script that takes a single parameter. This is the collection path that the user is entering into an input field in a web page. With each character the user types the list of possible sub-collections is narrowed.
There are three parts to this script:
1) the server side XQuery script
2) the HTML form
3) the JavaScript file that implements the JavaScript with AJAX functions.
Sample Server-Side Script
get-child-collections.xq
xquery version "1.0";
declare function local:substring-before-last-slash($arg as xs:string?) as xs:string {
if (matches($arg, '/'))
then replace($arg,'^(.*)/.*','$1') (: by default matching is eager :)
else ''
};
(: if we don't get any value then use the root collection :)
let $collection := request:get-parameter("collection", '')
let $parent := local:substring-before-last-slash($collection)
let $leaf := substring-after($collection, concat($parent, '/'))
let $sub-collections := xmldb:get-child-collections($parent)
return
<div class="results">{
if (count($sub-collections) = 0)
then
<h1>There are no subcollections of {$collection}</h1>
else
<div class="selections">{
for $child in $sub-collections
let $child-path := concat($parent, '/', $child)
order by $child
return
if (starts-with($child, $leaf))
then
<div class="selection"><a href="browse-collection.xq?collection={$child-path}/">{$child}</a></div>
else ()
}</div>
}</div>
browse-collection.xq
xquery version "1.0";
declare option exist:serialize "method=xhtml media-type=text/html omit-xml-declaration=no indent=yes
doctype-public=-//W3C//DTD XHTML 1.0 Transitional//EN
doctype-system=http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd";
let $title := "Browse Collections (AJAX)"
let $collection := request:get-parameter("collection", '/db/')
return
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>{$title}</title>
<script type="text/javascript" src="ajax-collection.js"/>
<style type="text/css">
td {{background-color: #efe; font-size:14px;}}
th {{background-color: #ded; text-align: right; padding:3px; font-size:12px;}}
</style>
</head>
<body onload="getList();">
<h1>{$title}</h1>
<p>{$collection}</p>
<form onsubmit="getList(); return false" action="get">
<span>
<label for="collection">Collection:</label>
<input type="text" size="50" name="collection" id="collection" title="collection"
onkeyup="getList();" onfocus="getList();" value="{$collection}"/>
</span>
</form>
<!-- this is where the results are placed -->
<div id="results"/>
</body>
</html>
ajax-collection.js
function updateList() {
if (http.readyState == 4) {
var divlist = document.getElementById('results');
divlist.innerHTML = http.responseText;
isWorking = false;
}
}
function getList() {
if (!isWorking && http) {
var collectionid = document.getElementById("collection").value;
http.open("GET", "get-child-collections.xq?collection=" + collectionid);
http.onreadystatechange = updateList;
// this sets the call-back function to be invoked when a response from the HTTP request is returned
isWorking = true;
http.send(null);
}
}
function getHTTPObject() {
var xmlhttp;
/*@cc_on
@if (@_jscript_version >= 5)
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (E) {
xmlhttp = false;
}
}
@else
xmlhttp = false;
@end @*/
if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
try {
xmlhttp = new XMLHttpRequest();
xmlhttp.overrideMimeType("text/xml");
} catch (e) {
xmlhttp = false;
}
}
return xmlhttp;
}
var http = getHTTPObject(); // create the HTTP Object
var isWorking = false;