Создание переменной с шаблоном в XSLT с последующим применением xpath - PullRequest
0 голосов
/ 12 марта 2019

Я использую следующие xslt

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://www.test.com/services/test/test/v1">

    <xsl:output method="xml" encoding="UTF-8"
        omit-xml-declaration="yes" indent="yes" />
    <xsl:strip-space elements="*" />

    <xsl:template match="/">

            <xsl:variable name="mytree">
                <xsl:call-template name="myvariable">
                </xsl:call-template>
            </xsl:variable>

        <xsl:choose>    
            <xsl:when test="count($mytree/foos/foo) &gt; 1">
                <xsl:copy-of select="$mytree"/>
            </xsl:when>
            <xsl:otherwise>
                <error>test</error>
            </xsl:otherwise>
        </xsl:choose>

    </xsl:template>

    <xsl:template name="myvariable">
        <foos>
            <foo>bar1</foo>
            <foo>bar2</foo>
            <foo>bar3</foo>
            <foo>bar4</foo>
        </foos>
    </xsl:template>   

</xsl:stylesheet>

Когда я использую выше xslt, это должно быть следующим выводом

<foos xmlns="http://www.test.com/services/test/test/v1">
    <foo>bar1</foo>
    <foo>bar2</foo>
    <foo>bar3</foo>
    <foo>bar4</foo>
</foos>

но это

<error xmlns="http://www.test.com/services/test/test/v1">test</error>

когда я удаляю вывод xmlns="http://www.test.com/services/test/test/v1" правильный. Не уверен, что происходит?

Ответы [ 3 ]

2 голосов
/ 12 марта 2019

Ну, с любым XML, независимо от того, построен ли он внутри вашего XSLT или прочитан из источника, если у вас есть элементы в определенном пространстве имен, то, чтобы выбрать их с помощью XPath в XSLT, в XSLT 2 у вас есть два варианта, либо использоватьxpath-default-namespace="http://www.test.com/services/test/test/v1" (например, <xsl:when test="count($mytree/foos/foo) &gt; 1" xpath-default-namespace="http://www.test.com/services/test/test/v1">) или связать пространство имен с префиксом (например, <xsl:when xmlns:v1="http://www.test.com/services/test/test/v1" test="count($mytree/v1:foos/v1:foo) &gt; 1">).

Вы можете использовать эти подходы для элемента-предка, например корневого элемента таблицы стилей, если онне мешает другим выборам, которые вы хотите сделать.

1 голос
/ 12 марта 2019

Вы должны указать квалифицированные имена элементов в выражении XPath, чтобы адресовать элементы foos и foo в вашем пространстве имен по умолчанию http://www.test.com/services/test/test/v1:

  • Зарегистрируйте пространство имен по умолчанию еще раз с префиксом пространства имен (например, myns): xmlns:myns="http://www.test.com/services/test/test/v1"
  • Используйте этот префикс пространства имен в выражениях XPath для адресации узлов в этом пространстве имен (например, myns:foos/myns:foo).
  • Добавьте exclude-result-prefixes="myns", чтобы подавить префикс myns в вашем документе результатов.
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://www.test.com/services/test/test/v1"

    xmlns:myns="http://www.test.com/services/test/test/v1"
    exclude-result-prefixes="myns">
    …

    <xsl:template match="/">
       …
       <xsl:choose>
            <xsl:when test="count($mytree/myns:foos/myns:foo) &gt; 1">
                <xsl:copy-of select="$mytree"/>
            </xsl:when>
            <xsl:otherwise>
                <error>test</error>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    …
</xsl:stylesheet>

см. XSLT Fiddle


Если у вас под рукой только процессор XSLT 1.0, вам потребуется функция EXSLT node-set , чтобы получить доступ к $mytree переменным из дерева результатов:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://www.test.com/services/test/test/v1"

    xmlns:exsl="http://exslt.org/common"
    extension-element-prefixes="exsl"
    xmlns:myns="http://www.test.com/services/test/test/v1"
    exclude-result-prefixes="myns">
    …

    <xsl:template match="/">
       …
       <xsl:choose>
            <xsl:when test="count(exsl:node-set($mytree)/myns:foos/myns:foo) &gt; 1">
              <xsl:copy-of select="$mytree"/>
            </xsl:when>
            <xsl:otherwise>
                <error>test</error>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    …
</xsl:stylesheet>
0 голосов
/ 12 марта 2019

Использовать код для удаления пространства имен

<xsl:template match="@*[namespace-uri() = 'http://www.test.com/services/test/test/v1']"/>
...