0

我对 XSL 有点陌生,但遇到了一些问题。根据我的研究,<xsl:variable>如果在顶层声明 XSL 变量是全局的,如果在模板中声明是局部的,并且您不能更改值。那么这是否意味着没有办法声明一个全局变量然后在模板中更改它的值?

我有以下情况,我正在遍历一个结果集,我有一些看起来像这样的东西:

<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>
4

3 回答 3

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 数据。我确信有更好的解决方案。

于 2013-04-08T15:17:05.983 回答
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>
于 2013-04-08T15:19:21.980 回答
0

如果在顶层声明 XSL 变量是全局的,如果在模板中声明是局部的,

不,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>包含单引号的 a。通过上述设置,您已经破坏了事件处理程序。

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

于 2013-04-08T16:12:05.877 回答