Интересно, есть ли способ поделиться фрагментами кода html в eXist-db. У меня есть две разные (более ожидаемые позже) функции, возвращающие одну и ту же большую html-форму для разных результатов. Когда я что-то меняю в одном из них, мне неприятно поддерживать один и тот же код. Я пытался:

  1. Сохраните его как файл html и загрузите с помощью функции doc() (eXist жалуется, что это не файл xml, а двоичный.
  2. Сохранение его как глобальной переменной в отдельный модуль (eXist жалуется на проблемы с контекстами). Я не знаю, как передать такую ​​переменную без префикса пространства имен.
  3. Сохранение как функции, возвращающей собственную огромную переменную (eXist жалуется на проблемы с контекстами).

Какая лучшая практика?

ОБНОВЛЕНИЕ

Итак, я попытался поместить фрагмент в переменную insinde функции, загруженной как модуль. Для меня это кажется разумным. Однако я получил сообщение об ошибке при попытке вернуть это:

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 ()
};

Есть идеи, пожалуйста?

ОБНОВЛЕНИЕ II

Здесь у меня есть функция в модуле:

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). Кроме того, я пытался изменить возвращаемый тип element()*, но ничего не помогло.

0
Honza Hejzl 26 Янв 2016 в 15:22

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
};
1
Honza Hejzl 16 Фев 2016 в 12:41

Все ваши подходы должны работать. Позвольте мне обратиться к каждому:

  1. Является ли фрагмент HTML правильно сформированным XML? Если да, сохраните его, например, как form.xml или form.html (поскольку по умолчанию eXist предполагает, что файлы с расширением .html имеют правильный формат; см. Mime-types.xml в вашей установке eXist папку) и обратитесь к нему с помощью doc($path). Если он сформирован неправильно, вы можете сохранить его как form.txt и вытащить его с помощью util:binary-to-string(util:binary-doc($path)). Или сделайте HTML правильно сформированным и воспользуйтесь первой альтернативой.

  2. Это тоже верно, поэтому вы не должны правильно объявлять или ссылаться на глобальную переменную. Какую именно ошибку вы получаете? Можете ли вы опубликовать небольшой пример фрагмента, который мы могли бы запустить для воспроизведения ваших результатов?

  3. См. №2.

1
joewiz 26 Янв 2016 в 13:34