Motivation

edit

You want to use XQuery with your DOJO JavaScript library which uses a variation of JSON syntax.

Method

edit

DOJO is a framework for developing rich client side applets in javascript: from the nice to have to the core webapp. Some day you may want to deliver your data in a way, that you or other people can easily use from DOJO.

DOJO specifies its own idiosyncratic way of wrapping data in JSON formatted objects, so it can be consumed by lots of its widgets: trees, grids, comboboxes, input fields etc. Below example (note the use of single quotes, which makes this invalid JSON) is taken from its web supplied documentation:

{ identifier: 'abbr',
  label: 'name',
  items: [
    { abbr:'ec', name:'Ecuador',           capital:'Quito' },
    { abbr:'eg', name:'Egypt',             capital:'Cairo' }
]}

Now, if eg. you want to feed an incremental user input widget from a server side search, xquery (in eXist at least) makes this a piece of cake. Please read below script as an introduction to the concept, very likely it can be optimized. The search itself uses a lucene fulltext index, which returns very quickly.

xquery version "1.0";
import module namespace json="http://www.json.org";
declare namespace request="http://exist-db.org/xquery/request";
declare option exist:serialize "method=html media-type=text/javascript";

(: where the data lives:)
let $coll := "/db/apps/myapp/data"

(: what we are looking for, sanitize remote input :)
let $tmp := xs:string(request:get-parameter("q", ""))
let $querystring := replace($tmp, "[^0-9a-zA-Z\-,. ]", "")
let $query :=
	<query>
		<near slop="10" ordered="no">{$querystring}</near>
	</query>
return

(: fetch results, dont forget to create an index in collection.xconf :)
let $hits := collection($coll)//article[ft:query(., $query)]
let $count := count($hits)

let $result :=
<result>
   <identifier>id</identifier>
   <label>title</label>
   <count>{$count}</count>
   {
      for $item in $hits
      return
         <items>
            <id>{string($item/@id)}</id>
            {$item/title}
         </items>
   }
</result>
return

json:xml-to-json($result)

The xquery extension json:xml-to-json($node as node()) does all the magic. In the result variable the data structure is created in the way DOJO wants it (per default), as shown above. Another thing to note: DOJO expects the identifier to be unique. It is up to you to design your data to satisfy this. Another note: as of today (eXist trunk of early september 2010) numbers in the output are quoted, it is up to you to convert them on the client for optimal processing.