Joe Wicentowski developed a very nice example of TEI processing using XQuery/exist-db which he has used in teaching. I've just resurrected my version. This was originally written to use with the eXist URL-rewriting architecture. I've used it here as another test of the approach to URL-rewriting I'm working on.
It's all to easy to get Apache into infinite rewriting loops. I found it useful to adopt the convention of a capitalised name for the application, uncapitalised for its collection:
RewriteRule ^/Punch/(.*)$ /punch/xquery/content.xq?_path=${escape:$1} [QSA,P]
The general function in the URL library creates the Context object:
declare function url:parse-path($steps) {
if (count($steps) = 0)
then ()
else if (count($steps) = 1)
then element {$steps[1]} {()}
else (element {$steps[1]} {$steps[2]}, url:parse-path(subsequence($steps,3)))
};
declare function url:path-to-sig($steps) {
if (count($steps) = 0)
then ()
else if (count($steps) = 1)
then $steps[1]
else ($steps[1],"*",url:path-to-sig(subsequence($steps,3)))
};
declare function url:get-context() as element(context) {
let $path := request:get-parameter("_path",())
let $path := if (ends-with($path,"/")) then substring($path, 1, string-length($path) - 1) else $path
let $steps := tokenize($path,"/")
let $signature := string-join(url:path-to-sig($steps),"/")
return
element context {
for $param in request:get-parameter-names()
let $value := request:get-parameter($param,())
return element {$param} {$value},
element _signature {$signature},
url:parse-path($steps)
}
};
which is used to guide the construction of the page body:
declare function phtml:page($context) as element(div) {
let $sig := $context/_signature
return
<div>
{phtml:search-form($context/q)}
{if (exists($context/q))
then
let $hits := punch:section-selection($context/q)
return
(phtml:breadcrumbs(()), phtml:hits-in-context($hits))
else
if ($sig = ("","issue"))
then
(phtml:breadcrumbs(()), phtml:corpus-toc())
else
if ($sig = "issue/*")
then
let $issue := punch:issue($context/issue)
return
(phtml:breadcrumbs($issue), phtml:issue-toc($issue))
else if ($sig = "issue/*/section/*")
then
let $issue := punch:issue($context/issue)
let $section := punch:section($issue,$context/section)
return
(phtml:breadcrumbs($section), phtml:section($section))
else ()
}
</div>
};
Further functions build parts of the page, eg to build the table of contents
declare function phtml:corpus-toc() as element(div){
<div class="body" id="corpus-toc">
<ul>
{
for $issue in punch:all-issues()
let $title := punch:issue-title($issue)
let $issue-id := punch:issue-id($issue)
order by $issue/@xml:id
return
<li>{$title}</li>
}
</ul>
</div>
};
The main script builds the HTML, using ids in the returned page to distribute parts of the page around the web page:
import module namespace phtml = "http://kitwallace.me/punchhtml" at "../lib/punchhtml.xqm";
import module namespace url = "http://kitwallace.me/url" at "/db/lib/url.xqm";
declare option exist:serialize 'method=xhtml media-type=text/html indent=yes';
let $context := url:get-context()
let $page := phtml:page($context)
return
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Punch, or the London Charivari</title>
<link rel="stylesheet" href="/punch/css/blueprint/screen.css" type="text/css" media="screen, projection"/>
<link rel="stylesheet" href="/punch/css/blueprint/print.css" type="text/css" media="print"/>
<!--[if IE ]><link rel="stylesheet" href="/punch/css/blueprint/ie.css" type="text/css" media="screen, projection" /><![endif]-->
<link rel="stylesheet" href="/punch/css/screen.css" type="text/css" media="screen"/>
</head>
<body>
<div class="container">
<div class="span-24 last">
<div class="span-16">
<div class="banner">
<img alt="Punch" width="358" height="114" src="/punch/data/images/banner.png"/>
</div>
</div>
<div class="span-8 last">
{$page/div[@id='search-form']}
</div>
</div>
<div class="span-24 last">
<hr/>
</div>
<div class="span-24 last">
<div class="inner">
{$page/div[@id='breadcrumbs']}
</div>
</div>
<div class="span-24 last">
<hr/>
</div>
<div class="span-24 last">
<div class="inner">
{$page/div[@class='body']}
</div>
</div>
<div class="span-24 last">
<div class="inner">
<div class="footer bordered">
<div id="footerlinks">
TEI Consortium |
TEI@Oxford 2010 |
Kit Wallace |
eXist
</div>
</div>
</div>
</div>
</div>
</body>
</html>