Created
September 10, 2014 22:23
-
-
Save tonyahowe/7751b363718ab3343b97 to your computer and use it in GitHub Desktop.
The templates file (?) stored in a different directory.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
xquery version "3.0"; | |
(:~ | |
: HTML templating module | |
: | |
: @version 2.1 | |
: @author Wolfgang Meier | |
: @contributor Adam retter | |
:) | |
module namespace templates="http://exist-db.org/xquery/templates"; | |
import module namespace inspect="http://exist-db.org/xquery/inspection" at "java:org.exist.xquery.functions.inspect.InspectionModule"; | |
import module namespace map="http://www.w3.org/2005/xpath-functions/map"; | |
import module namespace request="http://exist-db.org/xquery/request"; | |
import module namespace repo="http://exist-db.org/xquery/repo"; | |
import module namespace session="http://exist-db.org/xquery/session"; | |
import module namespace util="http://exist-db.org/xquery/util"; | |
declare namespace expath="http://expath.org/ns/pkg"; | |
declare variable $templates:CONFIG_STOP_ON_ERROR := "stop-on-error"; | |
declare variable $templates:CONFIG_APP_ROOT := "app-root"; | |
declare variable $templates:CONFIG_ROOT := "root"; | |
declare variable $templates:CONFIG_FN_RESOLVER := "fn-resolver"; | |
declare variable $templates:CONFIG_PARAM_RESOLVER := "param-resolver"; | |
declare variable $templates:CONFIGURATION := "configuration"; | |
declare variable $templates:CONFIGURATION_ERROR := QName("http://exist-db.org/xquery/templates", "ConfigurationError"); | |
declare variable $templates:NOT_FOUND := QName("http://exist-db.org/xquery/templates", "NotFound"); | |
declare variable $templates:TOO_MANY_ARGS := QName("http://exist-db.org/xquery/templates", "TooManyArguments"); | |
declare variable $templates:PROCESSING_ERROR := QName("http://exist-db.org/xquery/templates", "ProcessingError"); | |
declare variable $templates:TYPE_ERROR := QName("http://exist-db.org/xquery/templates", "TypeError"); | |
declare variable $templates:ATTR_DATA_TEMPLATE := "data-template"; | |
(:~ | |
: Start processing the provided content. Template functions are looked up by calling the | |
: provided function $resolver. The function should take a name as a string | |
: and return the corresponding function item. The simplest implementation of this function could | |
: look like this: | |
: | |
: <pre>function($functionName as xs:string, $arity as xs:int) { function-lookup(xs:QName($functionName), $arity) }</pre> | |
: | |
: @param $content the sequence of nodes which will be processed | |
: @param $resolver a function which takes a name and returns a function with that name | |
: @param $model a sequence of items which will be passed to all called template functions. Use this to pass | |
: information between templating instructions. | |
:) | |
declare function templates:apply($content as node()+, $resolver as function(xs:string, xs:int) as item()?, $model as map(*)?) { | |
templates:apply($content, $resolver, $model, ()) | |
}; | |
(:~ | |
: Start processing the provided content. Template functions are looked up by calling the | |
: provided function $resolver. The function should take a name as a string | |
: and return the corresponding function item. The simplest implementation of this function could | |
: look like this: | |
: | |
: <pre>function($functionName as xs:string, $arity as xs:int) { function-lookup(xs:QName($functionName), $arity) }</pre> | |
: | |
: @param $content the sequence of nodes which will be processed | |
: @param $resolver a function which takes a name and returns a function with that name | |
: @param $model a sequence of items which will be passed to all called template functions. Use this to pass | |
: information between templating instructions. | |
: @param $configuration a map of configuration parameters. For example you may provide a | |
: 'parameter value resolver' by mapping $templates:CONFIG_PARAM_RESOLVER to a function | |
: whoose job it is to provide values for templated parameters. The function signature for | |
: the 'parameter value resolver' is f($param-name as xs:string) as item()* | |
:) | |
declare function templates:apply($content as node()+, $resolver as function(xs:string, xs:int) as item()?, $model as map(*)?, | |
$configuration as map(*)?) { | |
let $model := if (exists($model)) then $model else map:new() | |
let $configuration := | |
if (exists($configuration)) then | |
map:new(( | |
$configuration, | |
map:entry($templates:CONFIG_FN_RESOLVER, $resolver), | |
if (map:contains($configuration, $templates:CONFIG_PARAM_RESOLVER)) then | |
() | |
else | |
map:entry($templates:CONFIG_PARAM_RESOLVER, templates:lookup-param-from-restserver#1) | |
)) | |
else | |
templates:get-default-config($resolver) | |
let $model := map:new(($model, map:entry($templates:CONFIGURATION, $configuration))) | |
for $root in $content | |
return | |
templates:process($root, $model) | |
}; | |
declare %private function templates:get-default-config($resolver as function(xs:string, xs:int) as item()?) as map(*) { | |
map { | |
$templates:CONFIG_FN_RESOLVER := $resolver, | |
$templates:CONFIG_PARAM_RESOLVER := templates:lookup-param-from-restserver#1 | |
} | |
}; | |
declare %private function templates:first-result($fns as function() as item()**) { | |
if(empty($fns))then | |
() | |
else | |
let $result := $fns[1]() return | |
if(exists($result))then | |
$result | |
else | |
templates:first-result(subsequence($fns, 2)) | |
}; | |
declare %private function templates:lookup-param-from-restserver($var as xs:string) as item()* { | |
templates:first-result(( | |
function() { request:get-parameter($var, ()) }, | |
function() { session:get-attribute($var) }, | |
function() { request:get-attribute($var) } | |
)) | |
}; | |
(:~ | |
: Continue template processing on the given set of nodes. Call this function from | |
: within other template functions to enable recursive processing of templates. | |
: | |
: @param $nodes the nodes to process | |
: @param $model a sequence of items which will be passed to all called template functions. Use this to pass | |
: information between templating instructions. | |
:) | |
declare function templates:process($nodes as node()*, $model as map(*)) { | |
let $config := templates:get-configuration($model, "") | |
for $node in $nodes | |
return | |
typeswitch ($node) | |
case document-node() return | |
for $child in $node/node() return templates:process($child, $model) | |
case element() return | |
let $dataAttr := $node/@data-template | |
return | |
if ($dataAttr) then | |
templates:call($dataAttr, $node, $model) | |
else | |
let $instructions := templates:get-instructions($node/@class) | |
return | |
if ($instructions) then | |
for $instruction in $instructions | |
return | |
templates:call($instruction, $node, $model) | |
else | |
element { node-name($node) } { | |
$node/@*, for $child in $node/node() return templates:process($child, $model) | |
} | |
default return | |
$node | |
}; | |
declare %private function templates:get-instructions($class as xs:string?) as xs:string* { | |
for $name in tokenize($class, "\s+") | |
where templates:is-qname($name) | |
return | |
$name | |
}; | |
declare %private function templates:get-configuration($model as map(*), $func as xs:string) { | |
if (not(map:contains($model, $templates:CONFIGURATION))) then | |
error($templates:CONFIGURATION_ERROR, "Configuration map not found in model. Tried to call: " || $func) | |
else | |
$model($templates:CONFIGURATION) | |
}; | |
declare %private function templates:call($classOrAttr as item(), $node as element(), $model as map(*)) { | |
let $parameters := | |
typeswitch ($classOrAttr) | |
case attribute() return | |
templates:parameters-from-attr($node) | |
default return | |
let $paramStr := substring-after($classOrAttr, "?") | |
return | |
templates:parse-parameters($paramStr) | |
let $func := | |
typeswitch ($classOrAttr) | |
case attribute() return | |
$classOrAttr/string() | |
default return | |
if (contains($classOrAttr, "?")) then | |
substring-before($classOrAttr, "?") | |
else | |
$classOrAttr | |
let $config := templates:get-configuration($model, $func) | |
let $call := templates:resolve($func, $config($templates:CONFIG_FN_RESOLVER)) | |
return | |
if (exists($call)) then | |
templates:call-by-introspection($node, $parameters, $model, $call) | |
else if ($model($templates:CONFIGURATION)($templates:CONFIG_STOP_ON_ERROR)) then | |
error($templates:NOT_FOUND, "No template function found for call " || $func) | |
else | |
(: Templating function not found: just copy the element :) | |
element { node-name($node) } { | |
$node/@*, for $child in $node/node() return templates:process($child, $model) | |
} | |
}; | |
declare %private function templates:call-by-introspection($node as element(), $parameters as map(xs:string, xs:string), $model as map(*), | |
$fn as function(*)) { | |
let $inspect := inspect:inspect-function($fn) | |
let $fn-name := prefix-from-QName(function-name($fn)) || ":" || local-name-from-QName(function-name($fn)) | |
let $param-lookup := templates:get-configuration($model, $fn-name)($templates:CONFIG_PARAM_RESOLVER) | |
let $args := templates:map-arguments($inspect, $parameters, $param-lookup) | |
return | |
templates:process-output( | |
$node, | |
$model, | |
templates:call-with-args($fn, $args, $node, $model), | |
$inspect | |
) | |
}; | |
declare %private function templates:call-with-args($fn as function(*), $args as (function() as item()*)*, | |
$node as element(), $model as map(*)) { | |
switch (count($args)) | |
case 0 return | |
$fn($node, $model) | |
case 1 return | |
$fn($node, $model, $args[1]()) | |
case 2 return | |
$fn($node, $model, $args[1](), $args[2]()) | |
case 3 return | |
$fn($node, $model, $args[1](), $args[2](), $args[3]()) | |
case 4 return | |
$fn($node, $model, $args[1](), $args[2](), $args[3](), $args[4]()) | |
case 5 return | |
$fn($node, $model, $args[1](), $args[2](), $args[3](), $args[4](), $args[5]()) | |
case 6 return | |
$fn($node, $model, $args[1](), $args[2](), $args[3](), $args[4](), $args[5](), $args[6]()) | |
case 7 return | |
$fn($node, $model, $args[1](), $args[2](), $args[3](), $args[4](), $args[5](), $args[6](), $args[7]()) | |
case 8 return | |
$fn($node, $model, $args[1](), $args[2](), $args[3](), $args[4](), $args[5](), $args[6](), $args[7](), $args[8]()) | |
case 9 return | |
$fn($node, $model, $args[1](), $args[2](), $args[3](), $args[4](), $args[5](), $args[6](), $args[7](), $args[8](), | |
$args[9]()) | |
case 10 return | |
$fn($node, $model, $args[1](), $args[2](), $args[3](), $args[4](), $args[5](), $args[6](), $args[7](), $args[8](), | |
$args[9](), $args[10]()) | |
case 11 return | |
$fn($node, $model, $args[1](), $args[2](), $args[3](), $args[4](), $args[5](), $args[6](), $args[7](), $args[8](), | |
$args[9](), $args[10](), $args[11]()) | |
case 12 return | |
$fn($node, $model, $args[1](), $args[2](), $args[3](), $args[4](), $args[5](), $args[6](), $args[7](), $args[8](), | |
$args[9](), $args[10](), $args[11](), $args[12]()) | |
case 13 return | |
$fn($node, $model, $args[1](), $args[2](), $args[3](), $args[4](), $args[5](), $args[6](), $args[7](), $args[8](), | |
$args[9](), $args[10](), $args[11](), $args[12](), $args[13]()) | |
case 14 return | |
$fn($node, $model, $args[1](), $args[2](), $args[3](), $args[4](), $args[5](), $args[6](), $args[7](), $args[8](), | |
$args[9](), $args[10](), $args[11](), $args[12](), $args[13](), $args[14]()) | |
case 15 return | |
$fn($node, $model, $args[1](), $args[2](), $args[3](), $args[4](), $args[5](), $args[6](), $args[7](), $args[8](), | |
$args[9](), $args[10](), $args[11](), $args[12](), $args[13](), $args[14](), $args[15]()) | |
default return | |
error($templates:TOO_MANY_ARGS, "Too many arguments to function " || function-name($fn)) | |
}; | |
declare %private function templates:process-output($node as element(), $model as map(*), $output as item()*, | |
$inspect as element(function)) { | |
let $wrap := | |
$inspect/annotation[ends-with(@name, ":wrap")] | |
[@namespace = "http://exist-db.org/xquery/templates"] | |
return | |
if ($wrap) then | |
element { node-name($node) } { | |
$node/@*, | |
templates:process-output($node, $model, $output) | |
} | |
else | |
templates:process-output($node, $model, $output) | |
}; | |
declare %private function templates:process-output($node as element(), $model as map(*), $output as item()*) { | |
typeswitch($output) | |
case map(*) return | |
templates:process($node/node(), map:new(($model, $output))) | |
default return | |
$output | |
}; | |
declare %private function templates:map-arguments($inspect as element(function), $parameters as map(xs:string, xs:string), $param-lookup as function(xs:string) as item()*) { | |
let $args := $inspect/argument | |
return | |
if (count($args) > 2) then | |
for $arg in subsequence($args, 3) | |
return | |
templates:map-argument($arg, $parameters, $param-lookup) | |
else | |
() | |
}; | |
declare %private function templates:map-argument($arg as element(argument), $parameters as map(xs:string, xs:string), $param-lookup as function(xs:string) as item()*) | |
as function() as item()* { | |
let $var := $arg/@var | |
let $type := $arg/@type/string() | |
let $looked-up-param := $param-lookup($var) | |
let $param-from-context := | |
if(exists($looked-up-param))then | |
$looked-up-param | |
else | |
$parameters($var) | |
let $param := | |
if (exists($param-from-context)) then | |
$param-from-context | |
else | |
templates:arg-from-annotation($var, $arg) | |
let $data := | |
try { | |
templates:cast($param, $type) | |
} catch * { | |
error($templates:TYPE_ERROR, "Failed to cast parameter value '" || $param || "' to the required target type for " || | |
"template function parameter $" || $var || " of function " || ($arg/../@name) || ". Required type was: " || | |
$type || ". " || $err:description) | |
} | |
return | |
function() { | |
$data | |
} | |
}; | |
declare %private function templates:arg-from-annotation($var as xs:string, $arg as element(argument)) { | |
let $anno := | |
$arg/../annotation[ends-with(@name, ":default")] | |
[@namespace = "http://exist-db.org/xquery/templates"] | |
[value[1] = $var] | |
for $value in subsequence($anno/value, 2) | |
return | |
string($value) | |
}; | |
declare %private function templates:resolve($func as xs:string, $resolver as function(xs:string, xs:int) as function(*)) { | |
templates:resolve(2, $func, $resolver) | |
}; | |
declare %private function templates:resolve($arity as xs:int, $func as xs:string, | |
$resolver as function(xs:string, xs:int) as function(*)) { | |
if ($arity > 10) then | |
() | |
else | |
let $fn := $resolver($func, $arity) | |
return | |
if (exists($fn)) then | |
$fn | |
else | |
templates:resolve($arity + 1, $func, $resolver) | |
}; | |
declare %private function templates:parameters-from-attr($node as node()) { | |
map:new( | |
for $attr in $node/@*[starts-with(local-name(.), $templates:ATTR_DATA_TEMPLATE)] | |
return | |
map:entry( | |
replace(local-name($attr), $templates:ATTR_DATA_TEMPLATE || "\-(.*)$", "$1"), | |
$attr/string() | |
) | |
) | |
}; | |
declare %private function templates:parse-parameters($paramStr as xs:string?) as map(xs:string, xs:string) { | |
map:new( | |
for $param in tokenize($paramStr, "&") | |
let $key := substring-before($param, "=") | |
let $value := substring-after($param, "=") | |
where $key | |
return | |
map:entry($key, $value) | |
) | |
}; | |
declare %private function templates:is-qname($class as xs:string) as xs:boolean { | |
matches($class, "^[^:]+:[^:]+") | |
}; | |
declare %private function templates:cast($values as item()*, $targetType as xs:string) { | |
for $value in $values | |
return | |
if ($targetType != "xs:string" and string-length($value) = 0) then | |
(: treat "" as empty sequence :) | |
() | |
else | |
switch ($targetType) | |
case "xs:string" return | |
string($value) | |
case "xs:integer" case "xs:int" case "xs:long" return | |
xs:integer($value) | |
case "xs:decimal" return | |
xs:decimal($value) | |
case "xs:float" case "xs:double" return | |
xs:double($value) | |
case "xs:date" return | |
xs:date($value) | |
case "xs:dateTime" return | |
xs:dateTime($value) | |
case "xs:time" return | |
xs:time($value) | |
case "element()" return | |
util:parse($value)/* | |
case "text()" return | |
text { string($value) } | |
default return | |
$value | |
}; | |
declare function templates:get-app-root($model as map(*)) as xs:string? { | |
$model($templates:CONFIGURATION)($templates:CONFIG_APP_ROOT) | |
}; | |
declare function templates:get-root($model as map(*)) as xs:string? { | |
let $appRoot := templates:get-app-root($model) | |
let $root := $model($templates:CONFIGURATION)($templates:CONFIG_ROOT) | |
return | |
if ($root) then $root else $appRoot | |
}; | |
(:----------------------------------------------------------------------------------- | |
: Standard templates | |
:-----------------------------------------------------------------------------------:) | |
declare function templates:include($node as node(), $model as map(*), $path as xs:string) { | |
let $appRoot := templates:get-app-root($model) | |
let $root := templates:get-root($model) | |
let $path := | |
if (starts-with($path, "/")) then | |
(: Search template relative to app root :) | |
concat($appRoot, "/", $path) | |
else | |
(: Locate template relative to HTML file :) | |
concat($root, "/", $path) | |
return | |
templates:process(doc($path), $model) | |
}; | |
declare function templates:surround($node as node(), $model as map(*), $with as xs:string, $at as xs:string?, | |
$using as xs:string?, $options as xs:string?) { | |
let $appRoot := templates:get-app-root($model) | |
let $root := templates:get-root($model) | |
let $path := | |
if (starts-with($with, "/")) then | |
(: Search template relative to app root :) | |
concat($appRoot, $with) | |
else | |
(: Locate template relative to HTML file :) | |
concat($root, "/", $with) | |
let $content := | |
if ($using) then | |
doc($path)//*[@id = $using] | |
else | |
doc($path) | |
return | |
if (empty($content)) then | |
if ($model($templates:CONFIGURATION)($templates:CONFIG_STOP_ON_ERROR)) then | |
error($templates:PROCESSING_ERROR, "surround: template not found at " || $path) | |
else | |
templates:process($node/node(), $model) | |
else | |
let $model := templates:surround-options($model, $options) | |
let $merged := templates:process-surround($content, $node, $at) | |
return | |
templates:process($merged, $model) | |
}; | |
declare %private function templates:surround-options($model as map(*), $optionsStr as xs:string?) as map(*) { | |
if (exists($optionsStr)) then | |
map:new(( | |
$model, | |
for $option in tokenize($optionsStr, "\s*,\s*") | |
let $keyValue := tokenize($option, "\s*=\s*") | |
return | |
if (exists($keyValue)) then | |
if (count($keyValue) = 1) then | |
map:entry($keyValue, true()) | |
else | |
map:entry($keyValue[1], $keyValue[2]) | |
else | |
() | |
)) | |
else | |
$model | |
}; | |
declare %private function templates:process-surround($node as node(), $content as node(), $at as xs:string) { | |
typeswitch ($node) | |
case document-node() return | |
for $child in $node/node() return templates:process-surround($child, $content, $at) | |
case element() return | |
if ($node/@id eq $at) then | |
element { node-name($node) } { | |
$node/@*, $content/node() | |
} | |
else | |
element { node-name($node) } { | |
$node/@*, for $child in $node/node() return templates:process-surround($child, $content, $at) | |
} | |
default return | |
$node | |
}; | |
declare | |
%templates:wrap | |
function templates:each($node as node(), $model as map(*), $from as xs:string, $to as xs:string) { | |
for $item in $model($from) | |
return | |
element { node-name($node) } { | |
$node/@*, templates:process($node/node(), map:new(($model, map:entry($to, $item)))) | |
} | |
}; | |
declare function templates:if-parameter-set($node as node(), $model as map(*), $param as xs:string) as node()* { | |
let $param := templates:get-configuration($model, "templates:if-parameter-set")($templates:CONFIG_PARAM_RESOLVER)($param) | |
return | |
if ($param and string-length($param) gt 0) then | |
templates:process($node/node(), $model) | |
else | |
() | |
}; | |
declare function templates:if-parameter-unset($node as node(), $model as item()*, $param as xs:string) as node()* { | |
let $param := templates:get-configuration($model, "templates:if-parameter-unset")($templates:CONFIG_PARAM_RESOLVER)($param) | |
return | |
if (not($param) or string-length($param) eq 0) then | |
templates:process($node/node(), $model) | |
else | |
() | |
}; | |
(: NOTE: to be moved to separate module because: | |
1) HTTP Attribute is specific to Java Servlets | |
2) Limits use to specifics to REST Server and URL Rewrite! | |
If desirable for use from REST Server should be implemented elsewhere, perhaps in a module that includes the templates module?!? | |
:) | |
declare function templates:if-attribute-set($node as node(), $model as map(*), $attribute as xs:string) { | |
let $isSet := | |
(exists($attribute) and request:get-attribute($attribute)) | |
return | |
if ($isSet) then | |
templates:process($node/node(), $model) | |
else | |
() | |
}; | |
declare function templates:if-model-key-equals($node as node(), $model as map(*), $key as xs:string, $value as xs:string) { | |
let $isSet := $model($key) = $value | |
return | |
if ($isSet) then | |
templates:process($node/node(), $model) | |
else | |
() | |
}; | |
(:~ | |
: Evaluates its enclosed block unless the model property $key is set to value $value. | |
:) | |
declare function templates:unless-model-key-equals($node as node(), $model as map(*), $key as xs:string, $value as xs:string) { | |
let $isSet := $model($key) = $value | |
return | |
if (not($isSet)) then | |
templates:process($node/node(), $model) | |
else | |
() | |
}; | |
(:~ | |
: Evaluate the enclosed block if there's a model property $key equal to $value. | |
:) | |
declare function templates:if-module-missing($node as node(), $model as map(*), $uri as xs:string, $at as xs:string) { | |
try { | |
util:import-module($uri, "testmod", $at) | |
} catch * { | |
(: Module was not found: process content :) | |
templates:process($node/node(), $model) | |
} | |
}; | |
(: NOTE: to be moved to separate module, because: | |
1) Makes an expectation on eXide being present. Only useable if eXide is present. | |
2) Limits use to specifics of REST Server and URL Rewrite! | |
If desirable for use with eXide should be implemented elsewhere, perhaps in a module that includes the templates module?!? | |
:) | |
declare function templates:load-source($node as node(), $model as map(*)) as node()* { | |
let $href := $node/@href/string() | |
let $link := templates:link-to-app("http://exist-db.org/apps/eXide", "index.html?open=" || templates:get-app-root($model) || "/" || $href) | |
return | |
element { node-name($node) } { | |
attribute href { $link }, | |
attribute target { "eXide" }, | |
attribute class { "eXide-open" }, | |
attribute data-exide-open { templates:get-app-root($model) || "/" || $href }, | |
$node/node() | |
} | |
}; | |
(: NOTE: To be moved to separate module, because: | |
1) Only used by commented out function templates:load-source (see above) | |
2) Makes an expectation on eXide being present. Only useable if eXide is present. | |
3) Limits use to specifics of REST Server and URL Rewrite! | |
If desirable for use with eXide should be implemented elsewhere, perhaps in a module that includes the templates module?!? | |
:) | |
(:~ | |
: Locates the package identified by $uri and returns a path which can be used to link | |
: to this package from within the HTML view of another package. | |
: | |
: $uri the unique name of the package to locate | |
: $relLink a relative path to be added to the returned path | |
:) | |
declare function templates:link-to-app($uri as xs:string, $relLink as xs:string?) as xs:string { | |
let $app := templates:resolve($uri) | |
let $path := string-join((request:get-context-path(), request:get-attribute("$exist:prefix"), $app, $relLink), "/") | |
return | |
replace($path, "/+", "/") | |
}; | |
(: NOTE: to be moved to separate module. :) | |
declare function templates:resolve($uri as xs:string) as xs:string? { | |
let $path := collection(repo:get-root())//expath:package[@name = $uri] | |
return | |
if ($path) then | |
substring-after(util:collection-name($path), repo:get-root()) | |
else | |
() | |
}; | |
(:~ | |
Processes input and select form controls, setting their value/selection to | |
values found in the request - if present. | |
:) | |
declare function templates:form-control($node as node(), $model as map(*)) as node()* { | |
let $control := local-name($node) | |
return | |
switch ($control) | |
case "input" return | |
let $type := $node/@type | |
let $name := $node/@name | |
let $value := templates:get-configuration($model, "templates:form-control")($templates:CONFIG_PARAM_RESOLVER)($name) | |
return | |
if ($value) then | |
switch ($type) | |
case "checkbox" case "radio" return | |
element { node-name($node) } { | |
$node/@* except $node/@checked, | |
attribute checked { "checked" }, | |
$node/node() | |
} | |
default return | |
element { node-name($node) } { | |
$node/@* except $node/@value, | |
attribute value { $value }, | |
$node/node() | |
} | |
else | |
$node | |
case "select" return | |
let $value := templates:get-configuration($model, "templates:form-control")($templates:CONFIG_PARAM_RESOLVER)($node/@name/string()) | |
return | |
element { node-name($node) } { | |
$node/@*, | |
for $option in $node/*[local-name(.) = "option"] | |
return | |
if (empty($value)) then | |
$option | |
else | |
element { node-name($option) } { | |
$option/@* except $option/@selected, | |
if ($option/@value = $value or $option/string() = $value) then | |
attribute selected { "selected" } | |
else | |
(), | |
$option/node() | |
} | |
} | |
default return | |
$node | |
}; | |
declare function templates:error-description($node as node(), $model as map(*)) { | |
let $input := templates:get-configuration($model, "templates:form-control")($templates:CONFIG_PARAM_RESOLVER)("org.exist.forward.error") | |
return | |
element { node-name($node) } { | |
$node/@*, | |
try { | |
util:parse($input)//message/string() | |
} catch * { | |
$input | |
} | |
} | |
}; | |
declare function templates:copy-node($node as element(), $model as item()*) { | |
element { node-name($node) } { | |
$node/@*, | |
templates:process($node/*, $model) | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment