【问题标题】:Passing local variable from one template to another in xslt在 xslt 中将局部变量从一个模板传递到另一个模板
【发布时间】:2018-06-12 07:06:30
【问题描述】:

我需要将一个模板中定义的局部变量的值传递给另一个模板 模板。

以下来源不起作用(即我无法将局部变量传递给另一个模板)。怎么了 ?提前非常感谢。

   `        <?xml version="1.0"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
      <xsl:output method="text"/>

      <xsl:template match="/">
        <xsl:apply-templates select="A/B/C">
        </xsl:apply-templates>
        <xsl:apply-templates select="A/B/D/E/F">
          <xsl:with-param name="XYZ" select="$XYZ" >
          </xsl:with-param>
        </xsl:apply-templates>
      </xsl:template>

      <xsl:template match="A/B/C">
        <xsl:variable name="XYZ">
          <xsl:value-of select="K/L/M/N/O"/>
        </xsl:variable>
      </xsl:template>

      <xsl:template match="A/B/D/E/F">
        <xsl:text>BLAH-BLAH-BLAH-111</xsl:text>
        <xsl:value-of select="$XYZ" />
        <xsl:text>BLAH-BLAH-BLAH-999</xsl:text>
      </xsl:template>
    </xsl:stylesheet>`

【问题讨论】:

  • 定义不起作用
  • 我无法将局部变量传递给另一个模板。还有其他编码方式吗?永远欢迎@Cid
  • 向我们展示不起作用的代码并不是解释您真正想要实现的目标的好方法。

标签: xml xslt xslt-1.0 xslt-2.0


【解决方案1】:

你需要声明参数,在匹配的模板中使用xsl:param

<xsl:template match="A/B/D/E/F">
    <xsl:param name="XYZ" />
    <xsl:text>BLAH-BLAH-BLAH-111</xsl:text>
    <xsl:value-of select="$XYZ" />
    <xsl:text>BLAH-BLAH-BLAH-999</xsl:text>
  </xsl:template>

但是,选择此模板的代码块存在问题

 <xsl:apply-templates select="A/B/D/E/F">
    <xsl:with-param name="XYZ" select="$XYZ" >
 </xsl:with-param>

xsl:with-param 正在选择一个变量名XYZ 作为参数传递,但该变量在模板中不存在。也许您希望它使用匹配“A/B/C”的模板中定义的变量?这不会发生,因为变量在声明它们的块的范围内是局部的。

也许您需要像这样编写 XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="text"/>

  <xsl:template match="/">
    <xsl:variable name="XYZ">
      <xsl:apply-templates select="A/B/C" />
    </xsl:variable>
    <xsl:apply-templates select="A/B/D/E/F">
      <xsl:with-param name="XYZ" select="$XYZ" />
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="A/B/C">
      <xsl:value-of select="K/L/M/N/O"/>
  </xsl:template>

  <xsl:template match="A/B/D/E/F">
    <xsl:param name="XYZ" />
    <xsl:text>BLAH-BLAH-BLAH-111</xsl:text>
    <xsl:value-of select="$XYZ" />
    <xsl:text>BLAH-BLAH-BLAH-999</xsl:text>
  </xsl:template>
</xsl:stylesheet>

当你把它应用到这个 XML 上时

<A>
  <B>
    <C>
      <K>
        <L>
          <M>
            <N>
              <O> *** Parameter *** </O>
            </N>
          </M>
        </L>
      </K>
    </C>
    <D>
      <E>
        <F>Test</F>
      </E>
    </D>
  </B>
</A>

以下是输出

BLAH-BLAH-BLAH-111 *** Parameter *** BLAH-BLAH-BLAH-999

【讨论】:

    【解决方案2】:

    你的非工作代码似乎做的是:

    • A 呼叫 B
    • B 设置一个局部变量 $XYZ
    • A 调用 C
    • 您希望 C 能够访问 $XYZ

    问题不在于将参数从 A 传递到 C:这很简单。问题是将 $XYZ 的值从 B 返回给它的调用者 A。

    执行此操作的方式取决于您使用的 XSLT 版本。

    • 在 XSLT 1.0 中,您可以从模板返回的唯一内容是一段 XML。模板 B 需要将它想要返回的所有内容包装在一个 XML 片段中,模板 A 需要将该 XML 片段捕获在一个变量中。为了有用,它需要 exslt:node-set() 扩展将 XML 片段转换为节点集,从中提取它需要的部分。

    • 在 XSLT 2.0 中,另一个选项是从模板返回一系列事物(例如 XML 节点):然后,调用者可以将该序列中的第一项复制到转换结果中,然后将序列中的第二项传递给另一个模板进行进一步处理。

    • 在 XSLT 3.0 中,您可以使用映射而不是序列,因此结果中的不同事物由名称而不是位置来标识。

    所有这些都是非常枯燥和学术的。如果您真的告诉我们您的转换正在尝试做什么(输入是什么,输出是什么以及它们之间的关系如何?),我们可以给您一个更好的答案。也许所有这些关于传递参数的东西意味着你以错误的方式进行工作,你最好使用完全不同的方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-30
      • 2020-07-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多