Как сохранить текущий путь в xsl?

Я хотел бы сохранить путь к текущему узлу, чтобы повторно использовать его в выражении XSLT. Является ли это возможным?

<!-- . into $path? -->    
<xsl:value-of select="$path" />

person Aftershock    schedule 11.12.2010    source источник
comment
Хороший вопрос, +1. Смотрите мой ответ для объяснения и альтернативного, более простого и реалистичного решения.   -  person Dimitre Novatchev    schedule 12.12.2010


Ответы (3)


Нет, это невозможно с vanilla XSLT 1.0. Не существует простого способа получить строку выражения XPath для заданного узла, и определенно нет способа оценить строку, которая выглядит как XPath, как если бы она была XPath.

Существуют расширения, поддерживающие динамическую оценку выражений XPath, но они совместимы не со всеми процессорами XSLT.

В любом случае, если вы предоставите более подробную информацию о том, что вы на самом деле пытаетесь сделать, может быть другой способ сделать это.

person Tomalak    schedule 11.12.2010

Привет, я хотел бы сохранить путь к текущему узлу, чтобы я мог повторно использовать его в выражении в XSLT. Является ли это возможным?

Для любого заданного узла возможно создание выражения XPath, которое при оценке выбирает именно этот узел. На самом деле существует более одного выражения XPath, которое выбирает один и тот же узел.

Точный код XSLT, который создает такие выражение XPath.

Проблема в том, что это выражение XPath нельзя вычислить во время того же преобразования в XSLT 1.0 или XSLT 2.0, если только не используется функция расширения EXSLT dyn:evaluate (и очень немногие процессоры XSLT 1.0 реализуют dyn:evaluate( ) ).

То, что вы хотите, может быть достигнуто более простым способом в XSLT с помощью инструкции <xsl:variable>:

<xsl:variable name="theNode" select="."/>

На эту переменную можно ссылаться в любом месте ее области действия как $theNode, и ее можно передавать в качестве параметра при применении или вызове шаблонов.

person Dimitre Novatchev    schedule 12.12.2010

Как отмечают @Dimitre и @Tomalak, я не думаю, что это имеет какое-то значение в том же преобразовании, чтобы получить строку, представляющую выражение XPath для данного узла, а затем выбрать узел, «анализирующий "такая строка. Я вижу некоторую ценность в выполнении этих операций в различных преобразованиях.

Кроме того, эта таблица стилей:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes"/>
    <xsl:template match="/">
        <xsl:for-each select=".|//node()|//@*">
            <xsl:variable name="vPath">
                <xsl:apply-templates select="." mode="getPath"/>
            </xsl:variable>
            <xsl:value-of select="concat($vPath,'&#xA;')"/>
            <xsl:call-template name="select">
                <xsl:with-param name="pPath" select="$vPath"/>
            </xsl:call-template>
            <xsl:text>&#xA;</xsl:text>
        </xsl:for-each>
    </xsl:template>
    <xsl:template match="/|node()|@*" mode="getPath" name="getPath">
        <xsl:apply-templates select="parent::*" mode="getPath"/>
        <xsl:text>/</xsl:text>
        <xsl:choose>
            <xsl:when test="self::*">
                <xsl:value-of select="concat(name(),'[',
                                             count(preceding-sibling::*
                                                     [name() =
                                                      name(current())]) + 1,
                                             ']')"/>
            </xsl:when>
            <xsl:when test="count(.|../@*)=count(../@*)">
                <xsl:value-of select="concat('@',name())"/>
            </xsl:when>
            <xsl:when test="self::text()">
                <xsl:value-of
                     select="concat('text()[',
                                    count(preceding-sibling::text()) + 1,
                                    ']')"/>
            </xsl:when>
            <xsl:when test="self::comment()">
                <xsl:value-of
                     select="concat('comment()[',
                                    count(preceding-sibling::comment()) + 1,
                                    ']')"/>
            </xsl:when>
            <xsl:when test="self::processing-instruction()">
                <xsl:value-of
                     select="concat('processing-instruction()[',
                                    count(preceding-sibling::
                                             processing-instruction()) + 1,
                                    ']')"/>
            </xsl:when>
        </xsl:choose>
    </xsl:template>
    <xsl:template name="select">
        <xsl:param name="pPath"/>
        <xsl:param name="pContext" select="/"/>
        <xsl:param name="pInstruction" select="'value-of'"/>
        <xsl:variable name="vPosition"
                      select="number(
                                 substring-before(
                                    substring-after($pPath,
                                                    '['),
                                    ']'))"/>
        <xsl:variable name="vTest"
                      select="substring-before(
                                 substring-after($pPath,
                                                 '/'),
                                 '[')"/>
        <xsl:variable name="vPath" select="substring-after($pPath,']')"/>
        <xsl:choose>
            <xsl:when test="$vPath">
                <xsl:call-template name="select">
                    <xsl:with-param name="pPath" select="$vPath"/>
                    <xsl:with-param name="pContext"
                                    select="$pContext/*[name()=$vTest]
                                                          [$vPosition]"/>
                    <xsl:with-param name="pInstruction"
                                    select="$pInstruction"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:variable name="vContext"
                              select="$pContext/node()
                                          [self::*[name()=$vTest]|
                                           self::comment()[$vTest='comment()']|
                                           self::text()[$vTest='text()']|
                                           self::processing-instruction()
                                              [$vTest =
                                               'processing-instruction()']]
                                          [$vPosition]|
                                      $pContext[$pPath='/']|
                                      $pContext/@*[name() =
                                                   substring($pPath,3)]
                                                  [not($vTest)]"/>
                <xsl:choose>
                    <xsl:when test="$pInstruction='value-of'">
                        <xsl:value-of select="$vContext"/>
                    </xsl:when>
                    <xsl:when test="$pInstruction='copy-of'">
                        <xsl:copy-of select="$vContext"/>
                    </xsl:when>
                </xsl:choose>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

С этим вводом:

<?somePI pseudoAttributes?>
<root>
    <!-- This is a comment -->
    <node attribute="Value">text</node>
</root>

Выход:

/
  text 
/processing-instruction()[1]
pseudoAttributes
/root[1]
  text 
/root[1]/comment()[1]
 This is a comment 
/root[1]/node[1]
text
/root[1]/node[1]/@attribute
Value
/root[1]/node[1]/text()[1]
text
person Community    schedule 12.12.2010