#xpath #xslt-2.0
#xpath #xslt-2.0
Вопрос:
Я использую следующий 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) amp;> 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"
вывод правильный. Не уверен, что происходит?
Ответ №1:
Что ж, с любым XML, будь то созданный внутри вашего XSLT или прочитанный из источника, если у вас есть элементы в определенном пространстве имен, тогда, чтобы выбрать их с помощью XPath в XSLT, в XSLT 2 у вас есть два варианта, либо использовать xpath-default-namespace="http://www.test.com/services/test/test/v1"
(например <xsl:when test="count($mytree/foos/foo) amp;> 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) amp;> 1">
).
Вы можете использовать эти подходы для элемента-предка, например, корневого элемента таблицы стилей, если это не мешает другим выборкам, которые вы хотите сделать.
Комментарии:
1. спасибо, наконец-то я попробовал с <xsl:when test=»count($mytree/*:foos/*:foo) > 1″>
Ответ №2:
Вы должны указать полные имена элементов в вашем выражении 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) amp;> 1">
<xsl:copy-of select="$mytree"/>
</xsl:when>
<xsl:otherwise>
<error>test</error>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
…
</xsl:stylesheet>
смотрите Скрипту XSLT
Если бы у вас был только процессор XSLT 1.0, вам понадобилась бы функция node-set
EXSLT для доступа к $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) amp;> 1">
<xsl:copy-of select="$mytree"/>
</xsl:when>
<xsl:otherwise>
<error>test</error>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
…
</xsl:stylesheet>
Ответ №3:
Используйте код для удаления пространства имен
<xsl:template match="@*[namespace-uri() = 'http://www.test.com/services/test/test/v1']"/>