xml XSL:在模板之间传递变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2167444/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 12:56:57  来源:igfitidea点击:

XSL: passing variables between templates

xmlxslt

提问by binaryguy

Is it possible to pass a variable from one parent template to its child element ?

是否可以将一个变量从一个父模板传递给它的子元素?

<xsl:template match="structure">
  <xsl:variable name="var"><xsl:value-of select="@path" /></xsl:variable>
  <xsl:apply-templates select="folders">
    <xsl:with-param name="var1" select="'{var}'"/>
  </xsl:apply-templates>
</xsl:template> 

this template will match:

此模板将匹配:

<xsl:template match="folder">
  <xsl:param name="var1"/>
  <xsl:value-of select="$var1"/>
</xsl:template>

You see I wanna use var as var1 in the matched template.

你看我想在匹配的模板中使用 var 作为 var1。

How can I make this work?

我怎样才能使这项工作?

edit: the structure is like this:

编辑:结构是这样的:

<structure path="C:\xampplite\htdocs\xampp">
  <folders>
    <folder name="img">
      <date>01/28/10 21:59:00</date>
      <size>37.4 KB</size>
    </folder>
 </folders>
</structure>

edit2:

编辑2:

<xsl:template match="folder">
<xsl:variable name="var1"><xsl:value-of select="../../@path"/></xsl:variable>
<xsl:variable name="var2"><xsl:value-of select="@name" /></xsl:variable>
<xsl:variable name="var3"><xsl:value-of select="$var1"/>\<xsl:copy-of select="$var2"/>    </xsl:variable>
 <th colspan="2" align="left"  bgcolor="#FF5500"><a onclick="foo('{$var3}')"><xsl:value-of select="$var3"/></a></th>

in the jscript function the string is without its backslashes. anyone knows why?

在 jscript 函数中,字符串没有反斜杠。有谁知道为什么?

C:xampplitehtdocsxamppimg

C:xampplitehtdocsxamppimg

回答by Robert Rossney

You can pass parameters to named templates that you call via <xsl:call-template>, e.g.:

您可以将参数传递给您通过调用的命名模板<xsl:call-template>,例如:

<xsl:call-template name="name">
   <xsl:with-param name="param" select="xpathexpr"/>
</xsl:call-template>

<xsl:template name="name">
   <xsl:param name="param"/>
   ...
</xsl:template>

When you call a named template, the context node is the current context. So to call a named template for child nodes, you need to change the current context by using <xsl:for-each>:

当您调用命名模板时,上下文节点是当前上下文。因此,要为子节点调用命名模板,您需要使用以下命令更改当前上下文<xsl:for-each>

<xsl:for-each select="child">
   <xsl:call-template name="name">
      <xsl:with-param name="param" select="xpathexpr"/>
   </xsl:call-template>
</xsl:for-each>

In your case, though, there's no need to pass parameters, since the variable that you're trying to use is something that's navigable to from the context node. And you don't need to use all those variables (nor should you ever give a variable a name as useless as var1):

但是,在您的情况下,不需要传递参数,因为您尝试使用的变量是可以从上下文节点导航到的变量。并且您不需要使用所有这些变量(也不应该给变量一个像 一样无用的名称var1):

<xsl:template match="folder">
   <xsl:variable name="linkarg" value="concat(../../@path, '\', @name)"/>
   <xsl:variable name="linktext" value="concat(../../@path, '\', @name)"/>
   <th colspan="2" align="left"  bgcolor="#FF5500">
      <a onclick="foo('{$linkarg}')">
         <xsl:value-of select="$linktext"/>
      </a>
   </th>
</xsl:template>

Also, I'd be tempted to use ancestor::structure[1]/@pathrather than ../../@path, because it makes the intention a lot more explicit; your version means "get the pathattribute from the parent of the parent element", while my version means "traverse up the chain of ancestor elements until you find the first one named structure, and get its pathattribute."

另外,我很想使用ancestor::structure[1]/@path而不是../../@path,因为它使意图更加明确;你的版本意思是“path从父元素的父元素获取属性”,而我的版本意思是“遍历祖先元素链,直到找到第一个名为 的元素structure,并获取它的path属性。”

回答by cr7pt0gr4ph7

When using XSLT 2.0, it ispossible to pass parameters to child templates, by adding tunnel="yes"to the <xsl:with-param .../>at the callsite, and to the </xsl:with-param .../>element at the called template as well. Just do:

当使用XSLT 2.0,它可以将参数传递给子模板,加入tunnel="yes"<xsl:with-param .../>调用点,并以</xsl:with-param .../>元件在被叫模板也是如此。做就是了:

<xsl:template match="folder">
  <xsl:param name="var1" tunnel="yes"/> <!-- note the 'tunnel="yes"' attribute here! -->
  <xsl:value-of select="$var1"/>
</xsl:template>

<xsl:template match="structure">
  <xsl:variable name="var"><xsl:value-of select="@path" /></xsl:variable>
  <xsl:apply-templates select="folders">
    <xsl:with-param name="var1" select="$var" tunnel="yes"/> <!-- note the 'tunnel' attribute here, too! -->
  </xsl:apply-templates>
</xsl:template>

For further information, please refer to the section 10.1.2 Tunnel parametersin the XSLT 2.0 specification.

有关更多信息,请参阅10.1.2 Tunnel parametersXSLT 2.0 规范中的部分。



An extended example

一个扩展的例子

With tunnel parameters, you could even do this:

使用隧道参数,您甚至可以这样做:

<xsl:template match="structure">
   <!-- same as before -->
</xsl:template>

<xsl:template match="folder">
  <!-- Look, ma, no param declaration! -->
  <!-- ... -->
  <xsl:apply-templates select="date"/>
  <!-- ... -->
</xsl:template>

<xsl:template match="folder/date">
   <xsl:param name="var1" tunnel="yes"/>
   <xsl:value-of select="$var1"/>
</xsl:template>

Because of the tunnel attribute, the var1parameter is passed from the initial template through all intermediate templates into the "folder/date"template.

由于隧道属性,var1参数从初始模板通过所有中间模板传递到"folder/date"模板中。

Just remember that the tunnel="yes"attribute declaration must be present both on the <xsl:param name="var1" tunnel="yes"/>ANDthe corresponding <xsl:with-param name="var1" tunnel="yes" select="..."/>attribute.

请记住,tunnel="yes"属性声明必须同时出现在<xsl:param name="var1" tunnel="yes"/>AND对应的<xsl:with-param name="var1" tunnel="yes" select="..."/>属性上。

回答by Mads Hansen

Two problems with the structuretemplate:

structure模板的两个问题:

  1. You are applying templates selecting folders, but have a template matching on folder. Either change it to folder, or if you have a folderstemplate make sure that it passes the var1parameter value down to the foldertemplate.
  2. Your with-param @select uses '{var}', which selects that literal string {var}. If you want to select the varvariable, then remove the surrounding quotes and curly braces and just select $var.
  1. 您正在应用模板选择folders,但有一个模板匹配folder。将其更改为folder,或者如果您有folders模板,请确保它将var1参数值向下传递给folder模板。
  2. 您的 with-param @select 使用'{var}',它选择该文字 string {var}。如果要选择var变量,请删除周围的引号和花括号,然后选择$var.

Applied changes to your structuretemplate:

structure模板应用更改:

<xsl:template match="structure">
  <xsl:variable name="var"><xsl:value-of select="@path" /></xsl:variable>
  <xsl:apply-templates select="folder">
    <xsl:with-param name="var1" select="$var"/>
  </xsl:apply-templates>
</xsl:template>

回答by shawnwall

The exact code for the call would be:

调用的确切代码是:

<xsl:template match="structure">
  <xsl:variable name="var"><xsl:value-of select="@path" /></xsl:variable>
  <xsl:apply-templates select="folders/folder">
    <xsl:with-param name="var1" select="$var"/>
  </xsl:apply-templates>
</xsl:template>

Another way to access the @path attribute of the root node would be modifying your template to:

访问根节点的@path 属性的另一种方法是将模板修改为:

<xsl:template match="folder">
  <xsl:value-of select="../../../@path"/>
</xsl:template>