XSLT 和 XSL-FO:创建多行表?

Mic*_*ker 1 xml xslt xsl-fo

我对 XSLT 还很陌生,我遇到了一个问题,我有一个包含未知数量的孩子的元素,我需要在表格中显示这些孩子,以便有 5-6 列可用于显示信息。

如果我得到一个如下所示的 XML 文件:

<books>
    <book>
        <author>Ralls, Kim</author>
        <title>Midnight Rain</title>
    </book>
    <book>
        <author>Corets, Eva</author>
        <title>Maeve Ascendant</title>
    </book>
    <book>
        <author>Corets, Eva</author>
        <title>Oberon's Legacy</title>
    </book>
    <book>
        <author>Randall, Cynthia</author>
        <title>Lover Birds</title>
    </book>
    <book>
        <author>Thurman, Paula</author>
        <title>Splish Splash</title>
    </book>
    <book>
        <author>Knorr, Stefan</author>
        <title>Creepy Crawlies</title>
    </book>
    <book>
        <author>Kress, Peter</author>
        <title>Paradox Lost</title>
    </book>
    <book>
        <author>Crichton, Michael</author>
        <title>Jurassic Park</title>
    </book>
    <book>
        <author>Orwell, George</author>
        <title>1984</title>
    </book>
    <book>
        <author>Martin, George</author>
        <title>A Song of Ice And Fire</title>
    </book>
</books>
Run Code Online (Sandbox Code Playgroud)

我想在一个由两行五列组成的表格中显示这 10 本书。

我已经走了这么远:

<xsl:template match="books" mode="table">
    <fo:table margin-left="auto" margin-right="auto">
        <fo:table-body>
            <fo:table-row table-layout="fixed">
                <xsl:for-each select="skill">
                    <fo:table-cell border="1">
                        <fo:block font-weight="bold">
                            <xsl:value-of select="name"/>
                        </fo:block>
                    </fo:table-cell>    
                </xsl:for-each>
            </fo:table-row>
        </fo:table-body>
    </fo:table>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

但这一切所做的就是将每个单元格放在同一行上。我正在寻找一种方法来检查循环是否运行了一定次数(5 或 6 次),并在发生这种情况时插入新行,但我不知道这是否可以在 XSL 中执行。

任何人都可以指出我正确的方向吗?

Kev*_*own 5

The previous answers are way to complicated for what should be (and is) easy. Recursion is not required for such a simple thing.

在 XSL FO 中,您不需要用行来构造表。您可以使用属性“ends-row”来指定您正在结束一行并开始新的一行。您可以轻松地调整这个简单的示例,甚至可以传入“列数”(请参阅​​ mod 5 ...这意味着每五分之一开始一个新行...更改为 4 或 8 或您希望的任何内容).. . 您只需在此之外创建表的结构(fo:table 和 fo:table-body)。在表格主体内,就像这个模板一样,将单元格作为子项放置:

  <xsl:template match="book">
    <xsl:variable name="pos" select="position()"/>
    <fo:table-cell>
        <xsl:if test="not($pos mod 5)">
            <xsl:attribute name="ends-row">true</xsl:attribute>
        </xsl:if>
        <fo:block>
            <xsl:value-of select="author"/>
        </fo:block>
    </fo:table-cell>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

所以把它放到一个简单的例子中你的数据......见下文。将您的 XML 格式化为每行五列。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    version="1.0">
<xsl:template match="/">
    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
        <fo:layout-master-set>
            <fo:simple-page-master margin-top="1in" margin-left="1in" margin-bottom="1in"
                margin-right="1in" page-width="8in" page-height="11in" master-name="first">
                <fo:region-body margin-top="0pt"/>
                <fo:region-before extent="0pt"/>
                <fo:region-after extent="0pt"/>
            </fo:simple-page-master>
        </fo:layout-master-set>
        <fo:page-sequence master-reference="first">
            <fo:flow flow-name="xsl-region-body" font-size="12pt" font-family="Helvetica">
    <xsl:apply-templates/>
            </fo:flow>
        </fo:page-sequence>
    </fo:root>
</xsl:template>
    <xsl:template match="books">
        <fo:table>
            <fo:table-body>
                <xsl:apply-templates/>
            </fo:table-body>
        </fo:table>
    </xsl:template>
    <xsl:template match="book">
        <xsl:variable name="pos" select="position()"/>
        <fo:table-cell border="1pt solid black">
            <xsl:if test="not($pos mod 5)">
                <xsl:attribute name="ends-row">true</xsl:attribute>
            </xsl:if>
            <fo:block>
                <xsl:value-of select="author"/>
            </fo:block>
        </fo:table-cell>
    </xsl:template>

</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)