xml 在 XSLT 中递增和检查计数器变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9608432/
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
Incrementing and checking the counter variable in XSLT
提问by Ron
I am having little difficulty in assigning a counter variable and incrementing it and then checking for a certain value in XSLT. Here is my code:
我在分配计数器变量并增加它然后检查 XSLT 中的某个值时几乎没有困难。这是我的代码:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" <xsl:variable name="empty_string"/>
<xsl:variable name="counter" select="0"/>
<xsl:template match="/Collection">
<xsl:for-each select="Content">
<xsl:sort select="Html/root/Event/start_date" order="ascending"/>
<xsl:variable name="isFutureEvent">
<xsl:value-of select="syscom:isFutureDate(Html/root/Event/start_date)" />
</xsl:variable>
<xsl:if test="Html/root/Event != $empty_string">
<xsl:if test="$isFutureEvent='true'">
<!-- Increment Counter -->
<xsl:value-of select="$counter + 1"/>
<!-- Test if Counter < 4 -->
<xsl:if test="$counter < 3">
<div class="media">
<!-- Do stuff here -->
</div>
</xsl:if> <!-- End if for counter -->
</xsl:if>
</xsl:if>
<!--</xsl:when>-->
<!--</xsl:choose>-->
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
But it doesnt seem to increment my counter and not exiting when the counter hits 3. Any help on this ?
但它似乎并没有增加我的计数器并且在计数器达到 3 时不退出。对此有什么帮助吗?
回答by MiMo
'Variables' in XSL are actually constants - you cannot change their value. This:
XSL 中的“变量”实际上是常量——你不能改变它们的值。这个:
<xsl:value-of select="$counter + 1"/>
will just output the value of $counter+1
只会输出值 $counter+1
To do loops you have to use recursion - e.g.:
要执行循环,您必须使用递归 - 例如:
<xsl:stylesheet
version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template name="loop">
<xsl:param name="i"/>
<xsl:param name="limit"/>
<xsl:if test="$i <= $limit">
<div>
<xsl:value-of select="$i"/>
</div>
<xsl:call-template name="loop">
<xsl:with-param name="i" select="$i+1"/>
<xsl:with-param name="limit" select="$limit"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template match="/">
<html>
<body>
<xsl:call-template name="loop">
<xsl:with-param name="i" select="0"/>
<xsl:with-param name="limit" select="10"/>
</xsl:call-template>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
altough it is better to try to avoid loops - in most cases the XSL can be written to avoid it, but I don't understand enough of what are you trying to achieve to give you the complete solution.
尽管尽量避免循环会更好 - 在大多数情况下,可以编写 XSL 来避免循环,但我不太了解您想要实现的目标,无法为您提供完整的解决方案。
回答by Taras Klym
I have same problem. I need increment value in loop. So the simplest way was include Saxon and use that value.
我有同样的问题。我需要循环中的增量值。所以最简单的方法是包含 Saxon 并使用该值。
if you use Saxon 6.5.5
如果您使用 Saxon 6.5.5
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
...
xmlns:saxon="http://icl.com/saxon"
extension-element-prefixes="saxon"
version="3.0">
if you use Saxon 9.4.0.4
如果您使用 Saxon 9.4.0.4
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
...
xmlns:saxon="http://saxon.sf.net/"
extension-element-prefixes="saxon"
version="3.0">
And after that you can simply use saxon variable :
之后,您可以简单地使用 saxon 变量:
<xsl:variable name="counter" select="0" saxon:assignable="yes"/> <!-- declare value -->
<saxon:assign name="counter" select="$counter+1"/> <!-- increment value, you can do it in loop for example-->
<xsl:value-of select="$counter"></xsl:value-of> <!-- print value -->
回答by Jeroen Landheer
If you want to know where you are in a for-each loop, you can use the built-in position() function.
如果您想知道自己在 for-each 循环中的位置,可以使用内置的 position() 函数。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Collection">
<xsl:for-each select="Content">
<xsl:if test="position() < 3">
<!-- Do this for nodes 1, 2 and 3 -->
</xsl:if>
<!-- Do this for every node -->
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
回答by Peter
In case any one wants to do this while using .net (XslCompiledTransform) you can use
如果有人想在使用 .net ( XslCompiledTransform) 时执行此操作,您可以使用
<xsl:stylesheet ... xmlns:customCode="urn:customCode">
<msxsl:script language="VB" implements-prefix="customCode">
<![CDATA[
private mCounter As Integer
Public Function AddToCounter() As Boolean
mCounter += 1
Return True
End Function
Public Function GetCounter() As Integer
Return mCounter
End Function
]]>
</msxsl:script>
Then you add a call to "customCode:AddToCounter()", and then you could write a message like this <xsl:message><xsl:value-of select="customCode:GetCounter()" /> rows remaining.</xsl:message>
然后你添加一个对“customCode:AddToCounter()”的调用,然后你可以写这样的消息 <xsl:message><xsl:value-of select="customCode:GetCounter()" /> rows remaining.</xsl:message>
回答by Mayank
We cant update xsl:variableas they are just like constants. But we can updated dp:local-variables, so here dp:local-variablecounter is initialized before starting for-loop. Each time loop is run counter will update itself by 1.
Try This:
我们无法更新,xsl:variable因为它们就像常量一样。但是我们可以更新dp:local-variables,所以这里dp:local-variable计数器在开始 for 循环之前被初始化。每次循环运行计数器都会将自身更新为 1。试试这个:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" <xsl:variable name="empty_string"/>
<xsl:template match="/Collection">
<dp:set-local-variable name="'counter'" value="0"/>
<xsl:for-each select="Content">
<dp:set-local-variable name="'counter'" value="dp:local-variable('counter')+1"/>
<xsl:sort select="Html/root/Event/start_date" order="ascending"/>
<xsl:variable name="isFutureEvent">
<xsl:value-of select="syscom:isFutureDate(Html/root/Event/start_date)" />
</xsl:variable>
<xsl:if test="Html/root/Event != $empty_string">
<xsl:if test="$isFutureEvent='true'">
<xsl:value-of select="dp:local-variable('counter')"/>
<!-- Test if Counter < 4 -->
<xsl:if test="dp:local-variable('counter') < 3">
<div class="media">
<!-- Do stuff here -->
</div>
</xsl:if>
<!-- End if for counter -->
</xsl:if>
</xsl:if>
<!--</xsl:when>-->
<!--</xsl:choose>-->
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
回答by Rem Sadikov
In my case I needed total of boxes in the shipment, this helped
在我的情况下,我需要在货件中总共装箱,这有帮助
<xsl:for-each select="ShippingConfirmation/Details/LicensePlates/LicensePlate">
<xsl:if test="position()=last()">
<xsl:value-of select="position()"/>
</xsl:if>
</xsl:for-each>

