如何在 eXist-db 中的函数之间共享标记片段?

How to share markup snippets amongst functions in eXist-db?

我想知道是否有办法在 eXist-db 中共享 html 代码片段。我有两个不同的(稍后会有更多期望)函数 returning 相同的大 html 形式以获得不同的结果。当我更改其中一个代码时,维护相同的代码很烦人。我试过:

  1. 像 html 文件一样保存它并使用 doc() 函数加载它(eXist 抱怨它不是 xml 文件,它是二进制文件。
  2. 将它像全局变量一样保存到一个单独的模块中(eXist 抱怨上下文有问题)。我不知道如何传递没有名称空间前缀的变量。
  3. 像函数一样保存它return它自己的巨大变量(eXist 抱怨上下文有问题)。

最佳做法是什么?

更新

好吧,我已经尝试将片段 放入 变量 insinde 作为模块加载的函数。对我来说,这似乎是合理的。但是,当我尝试 return 时出现错误:

err:XPDY0002 Undefined context sequence for 'child::snip:snippet' [at line 62, column 13, source: /db/apps/karolinum-apps/modules/app.xql]
In function:a pp:book-search(node(), map, xs:string?) [34:9:/db/apps/karolinum-apps/modules/app.xql]

我是这样称呼它的:

declare function app:list-books($node as node(), $model as map(*)) {
    for $resource in collection('/db/apps/karolinum-apps/data/mono')
    let $author := $resource//tei:titleStmt/tei:author/text()
    let $bookName := $resource//tei:titleStmt/tei:title/text()
    let $bookUri := base-uri($resource)
    let $imgPath := replace($bookUri, '[^/]*?$', '')
    let $fileUri := ( '/exist/rest' || $bookUri )
    let $fileName := replace($bookUri, '.*?/', '')
    return
        if ($resource//tei:titleStmt/tei:title)
        then
            snip:snippet
        else ()
};

有什么想法吗?

更新二

这里我有模块中的函数:

module namespace snip = "http://46.28.111.241:8081/exist/db/apps/karolinum-apps/modules/snip";

declare function snip:snippet($node as node(), $model as map(*), $author as xs:string, $bookTitle as xs:string, $bookUri as xs:anyURI, $fileUri as xs:anyURI) as element()* {
    let $snippet := 
        (
            <div class="panel panel-default">
                <div class="panel-heading">
                    <h3 class="panel-title"><a href="{$fileUri}">{$bookTitle}</a> ({$author})</h3>
                </div>
                <div class="panel-body">
                ...
                </div>
        )
        return $snippet
};

这里我试着调用它:

declare function app:list-books($node as node(), $model as map(*)) {
    for $resource in collection('/db/apps/karolinum-apps/data/mono')
    let $author := $resource//tei:titleStmt/tei:author/text()
    let $bookTitle := $resource//tei:titleStmt/tei:title/text()
    let $bookUri := base-uri($resource)
    let $fileUri := ('/exist/rest' || $bookUri)
    let $fileName := replace($bookUri, '.*?/', '')
    where not(util:is-binary-doc($bookUri))
    order by $bookTitle, $author
    return
        snip:snippet($author, $bookTitle, $bookUri, $fileUri)
};

它抛出:

err:XPST0017 error found while loading module app: Error while loading module app.xql: Function snip:snippet() is not defined in namespace 'http://46.28.111.241:8081/exist/db/apps/karolinum-apps/modules/snip' [at line 35, column 9]

当我试图将代码片段放入一个变量时,无法将使用的那些局部变量传递到那里(它抛出了 $fileUri is not set)。除此之外,我尝试更改 returned 类型 element()* 但没有任何帮助。

您的所有方法都应该有效。让我逐一解决:

  1. HTML 片段是 well-formed XML 吗?如果是这样,将其另存为 form.xmlform.html(因为默认情况下 eXist 假定扩展名为 .html 的文件是 well-formed;请参阅 mime-types。xml 在你的 eXist 安装文件夹中)并用 doc($path) 引用它。如果不是well-formed,可以保存为form.txt,用util:binary-to-string(util:binary-doc($path))拉入。或者制作 HTML well-formed 并使用第一个替代方案。

  2. 这也是有效的,因此您不能正确声明或引用全局变量。您得到的确切错误是什么?您能否 post 一个我们可以 运行 重现您的结果的小示例片段?

  3. 参见 #2。

我很亲近。有必要以某种方式将参数传递给嵌套函数并省略 eXist 的典型 $node as node(), $model as map(*) 作为参数。

模板函数:

declare function app:list-books($node as node(), $model as map(*)) {
    for $resource in collection('/db/apps/karolinum-apps/data/mono')
    let $author := $resource//tei:titleStmt/tei:author/text()
    let $bookTitle := $resource//tei:titleStmt/tei:title/text()
    let $bookUri := base-uri($resource)
    let $bookId := xs:integer(util:random() * 10000)
    let $fileUri := ('/exist/rest' || $bookUri)
    let $fileName := replace($bookUri, '.*?/', '')
    where not(util:is-binary-doc($bookUri))
    order by $bookTitle, $author
    return
        snip:snippet($author, $bookTitle, $bookUri, $bookId, $fileUri)
};

片段函数:

declare function snip:snippet($author as xs:string, $bookTitle as xs:string, $bookUri as xs:anyURI, $bookId as xs:string, $fileUri as xs:anyURI) as element()* {
    let $snippet := 
        (
            <div class="panel panel-default">
            ...
           </div>
       )
   return $snippet
};