Функция XSLT c (uri) или document (uri) не разрешает uri в контексте базы данных контента? - PullRequest
1 голос
/ 15 января 2020

Работа с последней версией MarkLogi c -10.0-2.1-amd64 на win10

В xquery я вызываю преобразование xslt:

xdmp:xslt-invoke("/tidy2html.xslt", doc($docurl))

И в этом преобразовании xslt я хочу чтобы получить дополнительную команду do c (с помощью uri sdp / xref. xml) из базы данных контента, в которой находится $ docurl.

<xsl:variable name="xref-uri" select="doc('sdp/xref.xml')"/>

Я уверен, глядя на консоль запросов, которая делает c ('sdp / xref. xml') существует с использованием контекста XQuery, указывающего на базу данных контента.

В XSLT я немного растерялся, поскольку do c ('sdp / xref. xml) ') возвращает Ничего , заставляя меня поверить, что мы можем быть контекстом базы данных модуля, в котором хранится xslt, а не контекстным базой данных, в которой я ожидаю находиться.

Есть ли способ, которым я можно ли получить (/ debug) xslt разрешение do c ('sdp / xref. xml')?

Я изучил document (), и это не приблизило меня к решению. И таблица стилей работает, когда она применяется в локальной файловой системе с использованием saxon XSLT.

Ответы [ 5 ]

2 голосов
/ 15 января 2020

Попробуйте document('sdp/xref.xml', /) вместо doc звонка, который у вас есть.

1 голос
/ 16 января 2020

Использование fn:doc внутри XSLT работает так же, как и в MarkLogi c. Я подозреваю, что с вашей переменной $xref-uri что-то пошло не так. Нет необходимости передавать весь документ как параметр:

xquery version "1.0-ml";

let $uri := cts:uris()[1]
return
  xdmp:xslt-eval(
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
      <xsl:param name="uri"/>
      <xsl:template match="/">
        <xsl:sequence select="doc($uri)"/>
      </xsl:template>
    </xsl:stylesheet>,
    document{ "" },
    map:entry("uri", $uri)
  )

HTH!

1 голос
/ 16 января 2020

Используйте параметр database для принудительного использования базы данных контента, используемой во время оценки XSLT:

xdmp:xslt-invoke(
  '/some/stylesheet.xsl',
  <input/>,
  <options xmlns="xdmp:eval">
    <database>{ xdmp:database('content-db') }</database>
  </options>)

Если вы хотите собрать больше информации, вы можете использовать следующее в вызывающем XQuery для двойной проверки какая база данных контента используется:

xdmp:database-name(xdmp:database())

Вы также можете использовать это (или каким-либо образом вставить xsl:value-of в вашу таблицу стилей), чтобы дважды проверить базу данных контента, используемую для оценки таблицы стилей, и количество документов он содержит:

xdmp:xslt-eval(
  <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                  xmlns:xdmp="http://marklogic.com/xdmp"
                  version="2.0">
    <xsl:template match="node()">
      <response>
        <database>
          <xsl:value-of select="xdmp:database-name(xdmp:database())"/>
        </database>
        <count>
          <xsl:value-of select="xdmp:estimate(collection())"/>
        </count>
      </response>
    </xsl:template>
  </xsl:stylesheet>,
  <placeholder/>)

И чтобы гарантировать, что возвращаемый результат doc() действительно действительно пустой, используйте атрибут as на вашем xsl:variable:

<xsl:variable name="xref-uri" select="doc('sdp/xref.xml')" as="node()"/>
1 голос
/ 15 января 2020

В качестве обходного пути я вызываю do c () на стороне XQuery и передаю его.

let $tocurl := 'sdp/xref.xml'
let $params := map:map()
let $_put := map:put($params, "xref", doc($tocurl))
return
    xdmp:xslt-invoke("/tidy2html.xslt", doc($docurl), $params)

Затем в XSLT возьмите xref

<xsl:stylesheet version="3.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns="http://www.w3.org/1999/xhtml"
  ...>
    <xsl:param name="xref" as="node()*"/>
    <!-- $xref contains doc('sdp/xref.xml') -->

Это работает.

0 голосов
/ 17 января 2020

Провел несколько дальнейших исследований по моему вопросу, проверил xdmp:xslt-invoke и xdmp:xslt-eval

xdmp: xslt-invoke

Дано: test-xslt.xqy

xquery version "1.0-ml";
let $xref := doc('sdp/xref.xml')
return
  xdmp:xslt-invoke(
    '/test-xslt.xslt',
    <dummy/>,
    map:entry("xref-param", $xref)
  )

Вызов test-xslt.xslt:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xdmp="http://marklogic.com/xdmp" version="2.0" xmlns="http://ing.com/vortex/sql/grammar">
    <xsl:param name="xref-param" as="document-node()?"/>
    <xsl:template match="node()">
        <response>
            <database>
                <xsl:value-of select="xdmp:database-name(xdmp:database())"/>
            </database>
            <count>
                <xsl:value-of select="xdmp:estimate(collection())"/>
            </count>
            <case name="internal doc">
                <xsl:variable name="xref" select="doc('sdp/xref.xml')" as="document-node()?"/>
                <xsl:choose>
                    <xsl:when test="empty($xref)">
                        <empty-doc/>
                    </xsl:when>
                    <xsl:otherwise>
                        <content>
                            <xsl:copy-of select="$xref"/>
                        </content>
                    </xsl:otherwise>
                </xsl:choose>
            </case>
            <case name="doc from param">
                <xsl:choose>
                    <xsl:when test="empty($xref-param)">
                        <empty-doc/>
                    </xsl:when>
                    <xsl:otherwise>
                        <content>
                            <xsl:copy-of select="$xref-param"/>
                        </content>
                    </xsl:otherwise>
                </xsl:choose>
            </case>
        </response>
    </xsl:template>
</xsl:stylesheet>

Я получаю результаты:

<response xmlns:xdmp="http://marklogic.com/xdmp" xmlns="http://ing.com/vortex/sql/grammar">
    <database>SqlXmlPub-content</database>
    <count>16968</count>
    <case name="internal doc">
        <empty-doc/>
    </case>
    <case name="doc from param">
        <content> 
            expected content
        </content>
    </case>
</response>

Наблюдения:

  • xdmp:xslt-invoke ведет нужную базу данных быть выбранным! (содержимое, а не база данных модулей)
  • Передача doc('sdp/xref.xml') из xq в xslt работает нормально
  • Разрешение doc('sdp/xref.xml') в xslt, вызываемом xdmp:xslt-invoke, не работает ??

xdmp: xslt-eval

Дано: test2-xslt.xqy

xquery version "1.0-ml";

let $xref := doc('sdp/xref.xml')
return
  xdmp:xslt-eval(
  <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xdmp="http://marklogic.com/xdmp" 
    xmlns="http://ing.com/vortex/sql/grammar"
    xmlns:f="http://ing.com/vortex/sql/functions">
    <xsl:import href="test-xslt.xslt"/>
    <xsl:param name="xref-param"/>
    <xsl:template match="node()">
        <results>
            <xsl:sequence select="f:test-doc(doc('sdp/xref.xml'), 'wrapper doc ref')"/>
            <xsl:sequence select="f:test-doc($xref-param, 'wrapper from param')"/>                       
            <xsl:call-template name="imported-context"/>
        </results>
    </xsl:template>
    <xsl:function name="f:test-doc">
        <xsl:param name="doc" as="node()*"/>
        <xsl:param name="name"/>
        <case name="{{$name}}" result="{{if (empty($doc)) then 'fail' else 'pass'}}"/>
    </xsl:function>    
  </xsl:stylesheet>,
    <dummy/>,
    map:entry("xref-param", $xref)
  )

И импортированная таблица стилей test-xslt.xslt

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xdmp="http://marklogic.com/xdmp" version="2.0" 
    xmlns="http://ing.com/vortex/sql/grammar"
    xmlns:f="http://ing.com/vortex/sql/functions">
    <xsl:param name="xref-param" as="document-node()?"/>
    <xsl:template name="imported-context">
        <response db="{xdmp:database-name(xdmp:database())}" est="{xdmp:estimate(collection())}">
            <xsl:sequence select="f:test-doc(doc('sdp/xref.xml'), 'substyle doc ref')"/>
            <xsl:sequence select="f:test-doc($xref-param, 'substyle from param')"/>                       
        </response>
    </xsl:template>
</xsl:stylesheet>

I получить результаты:

<results xmlns:xdmp="http://marklogic.com/xdmp" xmlns="http://ing.com/vortex/sql/grammar"
    xmlns:f="http://ing.com/vortex/sql/functions">
    <case name="wrapper doc ref" result="pass"/>
    <case name="wrapper from param" result="pass"/>
    <response db="SqlXmlPub-content" est="16968">
        <case name="substyle doc ref" result="fail"/>
        <case name="substyle from param" result="pass"/>
    </response>
</results>

Наблюдения:

  • Правильная база данных контента выбрана
  • в отношении doc() xdmp: xslt-eval имеет такие же проблемы, как xdmp:xslt-invoke. В подчиненной таблице стилей doc() возвращает пустое место, где ожидается некоторое содержимое.

Заключение

Примеры, предоставленные grtjn и Florent хорошо работать, а также помог мне проанализировать дальше. Было бы неплохо, если бы я мог найти лучший обходной путь, чем передача doc() в качестве параметра, чтобы получить доступ к ссылочным элементам uri в базе данных контента. Интересно, если это ошибка, пока у меня есть обходной путь. Спасибо!

...