XSL:FO:在循环中重复同一表行

时间:2018-08-27 10:20:57

标签: xml xsl-fo

我正在通过XSL:FO生成标签。标签将是相同的文本。因此,我的PDF页面由一个表组成,该表仅包含n次相同的行,直到页面结束:

<fo:table-row>
  <fo:table-cell>
   <fo:block>
    <xsl:value-of select = "foo"/>
   </fo:block>
  </fo:table-cell>
  <fo:table-cell>
   <fo:block>
    <xsl:value-of select = "bar"/>
   </fo:block>
  </fo:table-cell>
</fo:table-row>

我不想n次复制并粘贴代码以填充页面。我试图进行某种循环,使行数增加n倍。

我找到了这个结构:

<xsl:for-each select="1 to 20">..</xsl:for-each>

没有工作,但是引发了错误。

有什么简单的方法可以在XSL:FO中循环吗?

先谢谢了。

1 个答案:

答案 0 :(得分:1)

就像@ martin-honnen刚才说的,但是带有代码:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fo="http://www.w3.org/1999/XSL/Format"
    exclude-result-prefixes="xs" version="2.0">
    <xsl:variable name="root" select="/" />
    <xsl:template match="/">
        <xsl:for-each select="1 to 10">
            <xsl:for-each select="$root">
                <fo:table-row>
                    <fo:table-cell>
                        <fo:block>
                            <xsl:value-of select="foo" />
                        </fo:block>
                    </fo:table-cell>
                    <fo:table-cell>
                        <fo:block>
                            <xsl:value-of select="bar" />
                        </fo:block>
                    </fo:table-cell>
                </fo:table-row>
            </xsl:for-each>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

<xsl:for-each select="1 to 10">内,上下文是1 to 10的当前整数值,您不能选择相对于整数的节点。您需要通过为当前节点创建变量来重新建立上下文,并在内部xsl:for-each(如上所述)或select属性中使用该变量。哪个更好,很大程度上取决于个人喜好,这可以归结为您必须在select属性中重复变量引用的次数。


如果您坚持使用XSLT 1.0,则xsl:for-each需要能够(实际上,从任何地方)选择足够的节点,以便能够重复正确的次数:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fo="http://www.w3.org/1999/XSL/Format"
    exclude-result-prefixes="xs" version="1.0">
    <xsl:variable name="document" select="/*" />
    <xsl:template match="/*">
        <xsl:for-each select="(//node())[position() &lt;= 10]">
            <xsl:for-each select="$document">
                <fo:table-row>
                    <fo:table-cell>
                        <fo:block>
                            <xsl:value-of select="foo" />
                        </fo:block>
                    </fo:table-cell>
                    <fo:table-cell>
                        <fo:block>
                            <xsl:value-of select="bar" />
                        </fo:block>
                    </fo:table-cell>
                </fo:table-row>
            </xsl:for-each>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

但是,IMO最好改掉xsl:for-each等,然后递归执行:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fo="http://www.w3.org/1999/XSL/Format"
    exclude-result-prefixes="xs" version="1.0">
    <xsl:template match="/*" name="row">
        <xsl:param name="count" select="1" />
        <fo:table-row>
            <fo:table-cell>
                <fo:block>
                    <xsl:value-of select="foo" />
                </fo:block>
            </fo:table-cell>
            <fo:table-cell>
                <fo:block>
                    <xsl:value-of select="bar" />
                </fo:block>
            </fo:table-cell>
        </fo:table-row>
        <xsl:if test="$count &lt; 10">
            <xsl:call-template name="row">
                <xsl:with-param name="count" select="$count + 1" />
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>