2013-04-08 53 views
0

我对XSL有点新颖,并且遇到一些问题。根据我的研究,如果在顶层声明XSL变量<xsl:variable>是全局变量,如果在模板中声明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> 

正如你看到的,我所需要的值在“性别”和“schoolname”迭代期间第三个'如果'。如果我无法存储它们,我将如何访问它们?

编辑:修正了一些错别字,这里是从XML摘录是否有帮助:

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

请包含相应的XML代码段和所需的输出。 – Tomalak 2013-04-08 15:15:30

回答

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

0

首先,您确定XSL中的“变量”在赋值后无法更改。对于变换的执行,它只是“可变的”(即它对于不同的输入可能以不同的值结束),但在变换内不是“可变的”。其次,从你的例子看来,你仍然在考虑命令式的代码。您还没有给予足够的细节说清楚,但它听起来像是你有一个SQL型表中的XML文档,其中

SchoolName is in column 1 
Gender is in column 2 

还可以看出你在Table1要素数据本身,而不是内的元素。

一个写这将是

<!-- 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> 
+0

不推荐使用空模板覆盖默认规则。我认为这是在脚下射击自己。 – Tomalak 2013-04-08 15:20:44

+0

啊!那么没有'SchoolName'和'gender'元素?我想你是正确的。让我们拭目以待,看看OP是否想告诉我们! – Borodin 2013-04-08 15:22:36

+0

@Tomalak,我根据你的建议删除了这部分,因为它应该没有任何区别。在很多情况下,我不太确定输入格式是否会改变(我只想选择明确要求的内容),我更喜欢这种用法。我可能从Novatchev先生那里找到了答案,他通常在答案中包含它。但既然你也是XSL大师,我不得不重新考虑。 – harpo 2013-04-08 15:26:35

0

如果在顶层声明的XSL变量是全球性的,局部的,如果它的模板内声明更地道的方式,

不,XSL变量的范围对包含它的XSLT元素非常严格。如果你在<xsl:if>中声明它,它将在相应的</xsl:if>之后不可用。

并且您无法更改该值。

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

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

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


正如你看到的,我需要在第三个“如果”期间迭代“性别”和“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保存在一个单独的文件中。