Как разделить фрагменты разметки между функциями в eXist-db?

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

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

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

ОБНОВЛЕНИЕ

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

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()*, но ничего не помогло.


person Honza Hejzl    schedule 26.01.2016    source источник


Ответы (2)


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

  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.

person Joe Wicentowski    schedule 26.01.2016
comment
Большое спасибо. В общем, я имею в виду что-то вроде <div class="panel">...</div> В div есть вся большая форма. Я не уверен, что это строго допустимый XML (eXist не жалуется). Но он использует несколько переменных. Функция его просто не возвращает (пока). Ах, да, и эти переменные не активны (проходят как литералы). - person Honza Hejzl; 27.01.2016
comment
Если eXist не жалуется, то это правильный XML. Но не ожидайте, что переменные (под которыми, я думаю, вы должны понимать XQuery) будут работать, если они хранятся внутри файла .xml или .html; такие файлы рассматриваются как статические документы, а не как файлы .xq. Если вам нужно, чтобы ваша форма была динамичной, вам определенно нужно использовать методы № 2 или № 3. Или, четвертый вариант: используйте шаблонизатор eXist: exist-db.org/exist /apps/doc/templating.xml. Это вполне может подойти для вашей задачи. - person Joe Wicentowski; 27.01.2016
comment
Ну, я использую шаблонизатор, но не знаю, можно ли вкладывать функции. В шаблоне вызываю app:list-books, в результате получается список книг, для каждой из них есть форма. Можно ли использовать вызов функции шаблона внутри другой функции шаблона? - person Honza Hejzl; 27.01.2016

Я был очень близко. Нужно было как-то передать параметры во вложенную функцию и опустить типичные для 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
};
person Honza Hejzl    schedule 16.02.2016