【问题标题】:Xslt Looping using xsl:variable使用 xsl:variable 进行 Xslt 循环
【发布时间】:2015-10-16 22:01:27
【问题描述】:

我想使用 xsl:variable 并根据它的计数循环,但我不确定它在 Xslt 中是否可行。例如,如果我有一个变量名计数

<xsl:variable name="count" as="xs:integer" select="4"/>

我可以使用以下形式的变量吗!!!

<xsl:if test="some condition"/>
loop from 0 to $count
...do something here
end loop
</xsl:if>

有可能吗?

我的输入 XML:

<Root>
<Element>
    <Value>1</Value>
    <Value>2</Value>
</Element>
<Element>
    <Value>1</Value>
    <Value>2</Value>
    <Value>3</Value>
    <Value>4</Value>
</Element>
    <Element>
    <Value>1</Value>
</Element>
</Root>

平面文件中的预期输出是(带换行符):

1,2,,
1,2,3,4
1,,,

任何帮助表示赞赏。谢谢先生。

【问题讨论】:

    标签: xslt


    【解决方案1】:

    使用 XSLT 2.0 的解决方案可能是:

    <xsl:stylesheet version="2.0"
                    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
        <xsl:output method="text" />
        <xsl:variable name="count" select="4" />
    
        <xsl:template match="Element">
            <xsl:value-of select="for $i in 1 to $count return concat(Value[$i], '')"
                          separator="," />
            <xsl:text>&#xA;</xsl:text>
        </xsl:template>
    
        <xsl:template match="text()" />
    
    </xsl:stylesheet>
    

    注意:您也可以使用 if 语句代替 concat 函数。


    为了完整起见,使用 XSLT 1.0 编写的解决方案:

    <xsl:stylesheet version="1.0"
                    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
        <xsl:output method="text" />
    
        <xsl:variable name="count" select="4" />
    
        <!-- Ignore all text elements -->    
        <xsl:template match="text()" />
    
        <xsl:template match="Element">
            <xsl:if test="$count > 0">
                <!-- Output existing values -->
                <xsl:apply-templates select="Value[position() &lt;= $count]" />
                <!-- Output remaining commas -->
                <xsl:call-template name="print-commas">
                    <xsl:with-param name="number"
                                    select="$count - count(Value)" />
                </xsl:call-template>            
                <!-- Line break -->
                <xsl:text>&#xA;</xsl:text>
            </xsl:if>
        </xsl:template>
    
        <!-- Print the first value without a comma preprended to the value -->
        <xsl:template match="Value[1]">
            <xsl:value-of select="." />
        </xsl:template>
    
        <!-- Print the reamaining value with a comma preprended to the value -->
        <xsl:template match="Value">
            <xsl:value-of select="concat(',', .)" />
        </xsl:template>
    
        <!-- Print the given amount of commas -->
        <xsl:template name="print-commas">
            <!-- Number of commas to be printed -->
            <xsl:param name="number" />
    
            <xsl:if test="$number > 0">
                <xsl:text>,</xsl:text>
                <!-- Recursive call decrementing the number of commas to
                     be printed -->
                <xsl:call-template name="print-commas">
                    <xsl:with-param name="number"
                                    select="$number - 1" />
                </xsl:call-template>
            </xsl:if>
        </xsl:template>
    
    </xsl:stylesheet>
    

    【讨论】:

    • 感谢 Pablo 您的解决方案也有效。了解许多不同的方式..谢谢
    【解决方案2】:

    是的,这在 XSLT 2.0 中是可能的(从您的示例中的as="xs:integer",我假设您正在使用它)。以下转换将从您的示例输入中产生您预期的输出:

    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="text" version="1.0" encoding="UTF-8" indent="yes"/>
        <xsl:variable name="count" select="4"/>
    
        <xsl:template match="text()" />
    
        <xsl:template match="Element">
            <xsl:variable name="curElement" select="."/>
            <xsl:for-each select="1 to $count">
                <xsl:variable name="curVal" select="."/>
                <xsl:value-of select="$curElement/Value[. = $curVal]"/>
                <xsl:if test="$curVal != $count">
                    <xsl:text>,</xsl:text>
                </xsl:if>
            </xsl:for-each>
            <xsl:text>&#xA;</xsl:text>
        </xsl:template>
    
    </xsl:stylesheet>
    

    【讨论】:

    • 表达式for $i in 1 to $count return $i可以更简洁地表示为1 to $count
    【解决方案3】:

    示例中的“循环”:

    http://www.w3schools.com/xsl/xsl_for_each.asp

    你可以“匹配”到每个“元素”,而不必“每个”

    <xsl:template match="element" >
      <xsl:if test="not(constant(value, ' '))">
         <xsl:value-of select="concat(value/text(), ',')"/>
      <xsl:if>
    </xsl:template>
    

    【讨论】:

      猜你喜欢
      • 2016-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多