【问题标题】:How to store the current path in xsl?如何将当前路径存储在 xsl 中?
【发布时间】:2010-12-11 22:58:52
【问题描述】:

我想存储当前节点的路径,以便在 XSLT 的表达式中重用它。有可能吗?

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

【问题讨论】:

  • 好问题,+1。请参阅我的答案以获得解释以及替代、更简单和现实的解决方案。

标签: xslt xslt-1.0


【解决方案1】:

你好,我想存储路径 当前节点,以便我可以重用它 XSLT 中的表达式。有可能吗?

任何给定节点都可以构造一个 XPath 表达式,在计算时,该表达式恰好选择该节点。事实上,存在不止一个选择同一个节点的 XPath 表达式。

有关构造此类 XPath 表达式的确切 XSLT 代码,请参阅 this answer

问题是这个 XPath 表达式不能在 XSLT 1.0 或 XSLT 2.0 中的同一转换期间计算,除非使用 EXSLT 扩展函数 dyn:evaluate(并且很少有 XSLT 1.0 处理器实现 dyn :evaluate())。

可以使用&lt;xsl:variable&gt; 指令在 XSLT 中以更简单的方式实现您想要的目标

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

此变量可以在其范围内的任何位置引用为$theNode,并且可以在应用或调用模板时作为参数传递。

【讨论】:

    【解决方案2】:

    不,这在 vanilla XSLT 1.0 中是不可能的。没有简单的方法来检索给定节点的 XPath 表达式字符串,而且绝对没有办法评估 看起来像 XPath 就像是 XPath 的字符串。

    有一些扩展支持 XPath 表达式的动态求值,但这些扩展并不与每个 XSLT 处理器兼容。

    无论如何,如果您提供更多关于您实际尝试做的事情的详细信息,则可能有另一种方法可以做到。

    【讨论】:

      【解决方案3】:

      正如@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
      

      【讨论】:

        猜你喜欢
        • 2023-03-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-10
        • 2016-06-04
        • 2018-03-11
        • 2018-02-06
        • 1970-01-01
        相关资源
        最近更新 更多