问题
I am working with eXist-db 4.2.1 and Xquery 3.1 using the eXist's default installation of controller.xql
and view.xq
.
I have a document.html
to which I pass any incoming url structured with /doc/some-requested-doc-id
at the end to produce a dynamically-created page based on some-requested-doc-id
.
So, the incoming url can be either http://localhost:8080/exist/apps/deheresi/doc/MS609-0001
or
http://localhost:8080/exist/apps/deheresi/doc/MS609-0001.xml
and they are treated the same...
In the file controller.xql
I have a condition for matching this request, which identifies /doc/
and cleans up the expected some-requested-doc-id
using a function which is passed to parameter name="currentdoc"
:
[...]
else if (starts-with($exist:path, "/doc/")) then
(: strip out any extensions and rename global variable as .xml:)
<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
<forward url="{$exist:controller}/document.html">
<add-parameter name="currentdoc"
value="{concat(functx:substring-before-match($exist:resource,'[.]'),'.xml')}"/>
</forward>
<view>
<forward url="{$exist:controller}/modules/view.xql"/>
</view>
</dispatch>
[...]
The requested .html file is as follows, which itself calls other HTML templates and/or dynamically created content in XQuery:
<div data-template="templates:surround" data-template-with="templates/site_wrapper.html" data-template-at="content">
<div data-template="document:title-bar"/>
<div class="col-sm-12">
<div class="col-md-2 sidebar">
<div data-template="document:doc-sidebar-sub1"/>
<div data-template="document:doc-sidebar-sub2"/>
<div data-template="document:doc-sidebar-sub3"/>
<div data-template="document:doc-sidebar-sub4"/>
</div>
<div class="col-md-10 document-view">
<div data-template="document:doc-xsl-docview"/>
</div>
</div>
</div>
The 5 data-template="document:...
calls depend on the same parameter provided by <add-parameter>
, for example <div data-template="document:title-bar"/>
calls:
declare function document:title-bar(
$node as node(),
$model as map(*),
$currentdoc as xs:string)
{
let $persid := person:person-name(data(doc(concat($globalvar:URIdata,$currentdoc))/tei:TEI/tei:text//tei:persName[@role="dep"]/@nymRef))
let $doctypeen := data(doc(concat($globalvar:URIdata,$currentdoc))/tei:TEI/tei:text//tei:div[@type="doc_type"]/@subtype)
let $x :=
<div class="col-md-12 document-title">
<h2><span class="en">{$doctypeen}: </span><span class="fr">{document:doc-type-french($doctypeen)} : </span>{$persid}</h2>
</div>
return $x
};
Even if I hard-code the parameter in the module controller.xql
:
<add-parameter name="currentdoc" value="MS609-00001.xml"/>
I still get the same error, which doesn't happen if I hard code the parameter in the template call:
The actual cardinality for parameter 3 does not match the
cardinality declared in the function's signature:
document:title-bar($node as node(), $model as map,
$currentdoc as xs:string) item()*.
Expected cardinality: exactly one, got 0.
The 'expected cardinality' suggests that the parameter is not coming into the function?
EDIT:
If I change the order of parameters in the function above to
declare function document:title-bar(
$currentdoc as xs:string,
$node as node(),
$model as map(*))
I get a different error:
Supplied argument 2 of function:
document:title-bar($currentdoc as xs:string,
$node as node(), $model as map) item()* does not
match required type. Required type node(), got map. `
Many thanks in advance.
回答1:
The <add-parameter>
directive needs to be moved to the 2nd <forward>
directive—so that modules/view.xql
has access to the parameter. The corrected version of this fragment of your controller is:
else if (starts-with($exist:path, "/doc/")) then
(: strip out any extensions and rename global variable as .xml:)
<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
<forward url="{$exist:controller}/document.html"/>
<view>
<forward url="{$exist:controller}/modules/view.xql">
<add-parameter name="currentdoc" value="{concat(functx:substring-before-match($exist:resource,'[.]'),'.xml')}"/>
</forward>
</view>
</dispatch>
The templating documentation also shows this - see the 2nd code sample under the "Set up" section here: https://exist-db.org/exist/apps/doc/templating#D3.35.
(There was a mistake in the answer you referenced - which I have now corrected. Apologies, and thanks for your thorough testing and well-articulated questions!)
来源:https://stackoverflow.com/questions/53067680/exist-db-passing-parameters-to-templates-through-controller-xql-url-mapping