(: rest.xq :) module namespace _ = 'http://xqerl.org/xquery/examples/rest'; declare %private function _:html-head() { element head { element style { text {'body {font-family: Arial, Helvetica, sans-serif;}'} } } }; declare %private function _:html-wrap($contents) { element html { _:html-head(), element body { $contents } } }; (: ~~~~~~~ ~~~~~~~ :) declare %rest:GET %rest:path('/') %output:method('html') %rest:produces('text/html') function _:landing() { _:people-by-route-summary-table() => _:html-wrap() }; declare %private function _:people-by-route-summary-table() { let $sum := _:people-by-route-summary() return { for $ent in $sum/entry let $r := $ent/@route => string() return }
Route Count Age
{ $r } { $ent/count => xs:integer() } { $ent/age => xs:double() }
}; declare %rest:GET %rest:path('/route/summary') function _:people-by-route-summary() { { for $doc in fn:collection('http://xqerl.org/lists') let $id := $doc/list/@route , $cnt := count($doc/list/person) , $age := sum($doc/list/person/age) order by $id group by $r := $id return element entry { attribute route {$r}, element count {sum($cnt)}, element age { sum($age) div sum($cnt) } } } }; (: ~~~~~~~ ~~~~~~~ :) declare %rest:GET %rest:path('/route/detail') %rest:query-param("id", "{$id}") %output:method('html') %rest:produces('text/html') function _:people-by-route-id($id) { _:people-by-route-table($id) => _:html-wrap() }; declare function _:people-by-route-table($id) { { for $doc in fn:collection('http://xqerl.org/lists')[./list/@route eq $id] let $h := $doc/list/@id => string() return }
Id Count Age
{ $h } { count($doc/list/person) } { avg($doc/list/person/age) }
}; (: ~~~~~~~ ~~~~~~~ :) declare %rest:GET %rest:path('/list/detail') %rest:query-param("id", "{$id}") %output:method('html') %rest:produces('text/html') function _:people-by-list($id) { _:people-by-list-table($id) => _:html-wrap() }; declare function _:people-by-list-table($id) { { let $doc := fn:doc('http://xqerl.org/lists/' || $id) for $p in $doc/list/person order by $p/name/last, $p/name/first return }
Last Name First Name Age
{ $p/name/last/text() } { $p/name/first/text() } { $p/age/text() }
}; (: ~~~~~~~ ~~~~~~~ :) declare %rest:GET %rest:path('/summary') function _:people-summary() { { let $docs := fn:collection('http://xqerl.org/lists') , $cnt := count($docs/list/person) , $age := sum($docs/list/person/age) return element entry { element count { $cnt }, element age { $age div $cnt } } } }; declare %rest:GET %rest:path('/summary/json') %rest:produces('application/json') %output:method('json') function _:people-summary-json() { let $sum := _:people-summary() return map{ 'count' : $sum/entry/count => xs:integer(), 'age' : $sum/entry/age => xs:double() } }; (: ~~~~~~~ ~~~~~~~ :) declare %rest:GET %rest:path('/route/summary/json') %rest:produces('application/json') %output:method('json') function _:people-by-route-summary-json() { array { let $sum := _:people-by-route-summary() for $ent in $sum/entry return map{ 'route' : $ent/@route => string(), 'count' : $ent/count => xs:integer(), 'age' : $ent/age => xs:double() } } }; (: ~~~~~~~ Dummy data stuff ~~~~~~~ :) declare %updating %rest:GET %rest:path('/insert') function _:insert-random-stuff() { ( for $r in ('a','b','c','d','e') , $j in 1 to 100 let $doc := _:random-document($r) return fn:put($doc,'http://xqerl.org/lists/' || $doc/*/@id) ) }; declare function _:random-document($r) { document { element list { attribute route { $r }, attribute id { random:uuid() }, (1 to (random:integer(40) + 10) ) ! _:random-person() } } }; (: top-20 given names in the USA :) declare variable $_:FNAMES := ('James','Mary','John','Patricia','Robert', 'Linda','Michael','Barbara','William', 'Elizabeth','David','Jennifer','Richard', 'Maria','Charles','Susan','Joseph', 'Margaret','Thomas','Dorothy'); declare variable $_:FSIZE := 20; (: top-40 surnames in the USA :) declare variable $_:LNAMES := ('Smith','Johnson','Williams','Brown','Jones', 'Miller','Davis','Garcia','Rodriguez','Wilson', 'Martinez','Anderson','Taylor','Thomas', 'Hernandez','Moore','Martin','Jackson', 'Thompson','White','Lopez','Lee','Gonzalez', 'Harris','Clark','Lewis','Robinson','Walker', 'Perez','Hall','Young','Allen','Sanchez', 'Wright','King','Scott','Green','Baker', 'Adams','Nelson'); declare variable $_:LSIZE := 40; declare function _:random-person() { let $f := random:integer($_:FSIZE) + 1 (: random name index :) let $l := random:integer($_:LSIZE) + 1 let $a := random:integer(87) + 13 (: random age between 13 and 99 :) return element person { element name { element first { $_:FNAMES[$f] }, element last { $_:LNAMES[$l] } }, element age { $a } } };