XSL中的变量

时间:2013-04-08 15:03:54

标签: html xml xslt

我对XSL有点新意,我遇到了一些问题。根据我的研究,如果在顶级声明,则XSL变量<xsl:variable>是全局的,如果在模板中声明,则为本地,并且您不能更改该值。那么这是否意味着无法声明全局变量然后在模板中更改其值?

我有以下情况我在迭代结果集,我有一些看起来像这样:

<xsl:for-each select="NewDataSet/Table1">
 <xsl:if test="position()= 1">
  <xsl:value-of select="SchoolName"/>
 </xsl:if>

 <xsl:if test="position()= 2">
  <xsl:value-of select="gender"/>
 </xsl:if>

 <xsl:if test="position() = last()">
  <div onclick="showTallyBySchool(,'{SchoolName}','{gender}')">
   <xsl:value-of select="node()"/>
  </div>
 </xsl:if>
</xsl:for-each>

如您所见,我需要迭代期间第三个'if'中的'gender'和'schoolname'的值。如果我不能存储它们,我将如何访问它们?

编辑:修正了一些拼写错误,如果有帮助,这里是XML的摘录:

<NewDataSet>
 <Table1> 
  <SchoolName>Unknown School</SchoolName>  
  <Gender>Male</Gender> 
  <PS>0</PS> 
  <PK>0</PK> 
  <K>0</K> 
 </Table1>
</NewDataSet>

3 个答案:

答案 0 :(得分:2)

您可以相对访问当前节点。

我认为您对XML的结构感到困惑。例如,您从中选择SchoolName除了第一个 Table1。但代码会像这样。

<xsl:for-each select="NewDataSet/Table1[last()]">

  <xsl:variable name="school_name" select="../Table1[1]/SchoolName"/>
  <xsl:variable name="gender" select="../Table1[2]/gender"/>

  <div onclick="showTallyBySchool(,'{$school_name}',{$gender})">
    <xsl:value-of select="node()"/>
  </div>

</xsl:for-each>

请显示您的目标XML数据。我相信有更好的解决方案。

答案 1 :(得分:0)

首先,你认为XSL中的“变量”在分配后无法改变是正确的。它只对变换的执行是“可变的”(即,它可以以不同的输入结束不同的值),但它在变换中不是“可变的”。

其次,从您的示例看,您仍然在考虑命令性代码。你还没有给出足够详细的说明,但听起来你有一个SQL类型表的XML文档,其中

SchoolName is in column 1
Gender is in column 2

您似乎还拥有Table1元素本身的数据,而不是其中的Row元素。

写一个更惯用的方式是

<!-- tells what to do at the top level -->
<xsl:template match="/NewDataSet">
    <!-- This means, process child elements according to the templates I define -->
    <xsl:apply-templates/>
</xsl:template>

<xsl:template match="Table1">
    <!-- You should use the exact element names if they are known, couldn't tell from example -->
    <xsl:variable name="SchoolName" select="*[1]"/>
    <xsl:variable name="Gender"     select="*[2]"/>

    <div onclick="showTallyBySchool(,'{$SchoolName}',{$Gender})">
       <!-- it's not clear what you want here, but it's probably not this -->
       <xsl:value-of select="node()"/>
    </div>

</xsl:template>

答案 2 :(得分:0)

  

如果在顶层声明,则XSL变量是全局变量,如果在模板中声明,则为X本地,

不,XSL变量的范围非常严格地限定在包含它的XSLT元素中。如果您在<xsl:if>内声明它,则在相应的</xsl:if>之后将无法使用它。

  

并且您无法更改该值。

没错,所有XSLT变量都是不可变的。

  

这是否意味着无法声明全局变量然后在模板中更改其值?

正确,你永远不需要。作为一般规则:如果您发现自己试图在XSLT中更改变量值,那么您解决问题的方法是错误的。


  

如您所见,我需要迭代期间第三个'if'中的'gender'和'schoolname'的值。如果我不能存储它们,我将如何访问它们?

使用您的XML ...

<NewDataSet>
  <Table1> 
    <SchoolName>Unknown School</SchoolName>  
    <Gender>Male</Gender> 
    <PS>0</PS> 
    <PK>0</PK> 
    <K>0</K> 
  </Table1>
</NewDataSet>

......解决方案非常简单。您根本不需要任何变量。只需直接访问XML节点<SchoolName><Gender>

<xsl:template match="NewDataSet">
  <xsl:apply-templates select="Table1" />
</xsl:template>

<xsl:template match="Table1">
  <div>
    <xsl:value-of select="SchoolName" />
  </div>
  <div>
    <xsl:value-of select="Gender" />
  </div>
  <div onclick="showTallyBySchool('{SchoolName}', {Gender})">
    <xsl:text>Show Tally</xsl:text>
  </div>
</xsl:template>

虽然我一般建议不要混用HMTL和JavaScript,而尤其不要用XSLT生成JavaScript。这只会变得难看。

想象一下包含单引号的<SchoolName>。通过上面的设置,您已经破坏了事件处理程序。

另外,使用像onclick这样的内联事件处理程序违反了关注点分离的原则(在这种情况下是标记和页面逻辑),会产生丑陋的HTML并意味着在这种情况下你需要更改你的XSLT文件当你真的想修复JavaScript中的错误时。它可能有其他含义,例如与现代JS框架不兼容(甚至内存泄漏,尽管现在这种情况不太常见) - 简而言之,它通常不受欢迎。最好将所有JavaScript保存在单独的文件中。