XQuery/Incremental Searching
Contents |
[edit] Motivation
You have a large data set and you want to use JavaScript to asynchronously communicate with a server to narrow the scope of the search as a user types.
[edit] US Zip Code Example
There are around 43,000 5 digit ZipCodes in the US. There are a number of applications to convert a zip code to a location, for example Ben Fry's Java applet written using Processing
This example uses a client-side XHTML page using Ajax to request a subset of codes from a server-side search of an XML database of Zipcodes, updating the page dyamically.
[edit] The HTML page
Generated by an XQuery although the content is static.
declare option exist:serialize "method=xhtml media-type=text/html indent=yes";
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>ZIP Code to City and State using XmlHttpRequest</title>
<script language="javascript" src="ajaxzip.js"/>
</head>
<body>
<h1>US Zipcode decoder</h1>
<form onSubmit="getList(); return false">
<p>ZIP code:
<input type="text" size="5" name="zip" id="zip" onkeyup="getList();" onfocus="getList();" />
e.g. 95472
</p>
</form>
<div id="list"/>
</body>
</html>
[edit] Javascript
Uses XMLHttpRequest to request the subset and innerHTML to update the page.
function updateList() {
if (http.readyState == 4) {
var divlist = document.getElementById('list');
divlist.innerHTML = http.responseText;
isWorking = false;
}
}
function getList() {
if (!isWorking && http) {
var zipcode = document.getElementById("zip").value;
http.open("GET", "getzip.xq?zipcode=" + escape(zipcode), true);
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;
[edit] XQuery search
The Server-side XQuery to perform the search in the XML database and generate the XHTML. This uses the eXist full text index and the exist-specific &= operator.
let $zipcode := request:get-parameter("zipcode",())
return
<div>
{if (string-length($zipcode) > 1) (: too slow :)
then
let $search := concat('^',$zipcode)
for $zip in //Zipcode[matches(Code,$search)]
return
<div>{string-join(($zip/Code,$zip/Area,$zip/State),' ')}</div>
else ()
}
</div>
[edit] XML data file
The data was originally a CSV file, converted to XML using Excel and the XML add-in. This is a sample of the data.
<Zipcodes>
<Zipcode>
<Code>210</Code>
<Area>Portsmouth</Area>
<State>NH</State>
</Zipcode>
<Zipcode>
<Code>211</Code>
<Area>Portsmouth</Area>
<State>NH</State>
</Zipcode>
<Zipcode>
<Code>212</Code>
<Area>Portsmouth</Area>
<State>NH</State>
</Zipcode>
<Zipcode>
<Code>213</Code>
<Area>Portsmouth</Area>
<State>NH</State>
</Zipcode>
...
This page may need to be