XQuery/Incremental Searching
Motivation
[edit | edit source]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.
US Zip Code Example
[edit | edit source]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 dynamically.
The HTML page
[edit | edit source]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>
Javascript
[edit | edit source]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;
XQuery search
[edit | edit source]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>
XML data file
[edit | edit source]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> ...