我对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>
答案 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保存在单独的文件中。