在XSL:FO中将行转换为列

时间:2010-08-11 14:40:18

标签: xml pdf xsl-fo

尝试创建一个表,其中行被转换为列,以便我可以在逻辑上将列分组为XML。 XML是这样的:

   <root>
   <field name="field1">
     <string>field1.row1</string>
     <string>field1.row2</string>
     <string>field1.row3</string>
     <string>field1.row4</string>
   </field> 
   <field name="field2">
     <string>field2.row1</string>
     <string>field2.row2</string>
     <string>field2.row3</string>
     <string>field2.row4</string>
   </field>
   <field name="field3">
     <string>field3.row1</string>
     <string>field3.row2</string>
     <string>field3.row3</string>
     <string>field3.row4</string>
   </field>
 </root>

这意味着每个字段都有多个单元格都显示在一列中,而不是字段跨越列,它会显示在多行上。

我尝试创建一些xsl(无效)将此信息显示为水平分组表。

关于如何做到这一点的任何想法?

1 个答案:

答案 0 :(得分:0)

此样式表生成一个简单的XSL-FO表。它将field元素转换为列,将string元素转换为行:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <xsl:output method="xml" indent="yes" />

    <xsl:variable name="fieldCount"  select="count(/root/field)" />
    <xsl:variable name="stringCount"  select="count(/root/field[1]/string)" />

    <xsl:template match="root">
        <fo:table-and-caption>
            <fo:table>
                <fo:table-header>
                    <fo:table-row>
                        <xsl:call-template name="header">
                            <xsl:with-param name="currentCol" select="'1'"/>
                            <xsl:with-param name="maxCols" select="$fieldCount"/>
                        </xsl:call-template>
                    </fo:table-row>
                </fo:table-header>
                <fo:table-body>
                    <xsl:call-template name="row">
                        <xsl:with-param name="currentRow" select="'1'"/>
                        <xsl:with-param name="maxRows" select="$stringCount" />
                    </xsl:call-template>
                </fo:table-body>
            </fo:table>
        </fo:table-and-caption>
    </xsl:template>

    <xsl:template name="header">
        <xsl:param name="currentCol"/>
        <xsl:param name="maxCols" />

        <fo:table-cell>
            <fo:block font-weight="bold">
                <xsl:text>Column </xsl:text>
                <xsl:value-of select="field[position()=$currentCol]/@name"/>
            </fo:block>
        </fo:table-cell>

        <xsl:if test="$currentCol &lt; $maxCols">
            <xsl:call-template name="header">
                <xsl:with-param name="currentCol" select="$currentCol+1"/>
                <xsl:with-param name="maxCols" select="$maxCols"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>

    <xsl:template name="row">
        <xsl:param name="currentRow"/>
        <xsl:param name="maxRows" />

        <fo:table-row>
            <xsl:call-template name="cell">
                <xsl:with-param name="currentRow" select="$currentRow" />
                <xsl:with-param name="currentCol" select="'1'" />
                <xsl:with-param name="maxCols" select="$fieldCount" />
            </xsl:call-template>
        </fo:table-row>

        <xsl:if test="$currentRow &lt; $maxRows">
            <xsl:call-template name="row">
                <xsl:with-param name="currentRow" select="$currentRow+1"/>
                <xsl:with-param name="maxRows" select="$maxRows" />
            </xsl:call-template>
        </xsl:if>

    </xsl:template>

    <xsl:template name="cell">
        <xsl:param name="currentRow"/>
        <xsl:param name="currentCol"/>
        <xsl:param name="maxCols" />

        <xsl:apply-templates select="field[position()=$currentCol]/string[position()=$currentRow]"/>

        <xsl:if test="$currentCol &lt; $maxCols">
            <xsl:call-template name="cell">
                <xsl:with-param name="currentRow" select="$currentRow"/>
                <xsl:with-param name="currentCol" select="$currentCol+1" />
                <xsl:with-param name="maxCols" select="$maxCols" />
            </xsl:call-template>
        </xsl:if>
    </xsl:template>

    <xsl:template match="string">
        <fo:table-cell>
            <fo:block>
                <xsl:value-of select="."/>
            </fo:block>
        </fo:table-cell>
    </xsl:template>

</xsl:stylesheet>

从示例XML生成的输出:

<?xml version="1.0" encoding="UTF-16"?>
<fo:table-and-caption xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <fo:table>
        <fo:table-header>
            <fo:table-row>
                <fo:table-cell>
                    <fo:block font-weight="bold">Column field1</fo:block>
                </fo:table-cell>
                <fo:table-cell>
                    <fo:block font-weight="bold">Column field2</fo:block>
                </fo:table-cell>
                <fo:table-cell>
                    <fo:block font-weight="bold">Column field3</fo:block>
                </fo:table-cell>
            </fo:table-row>
        </fo:table-header>
        <fo:table-body>
            <fo:table-row>
                <fo:table-cell>
                    <fo:block>field1.row1</fo:block>
                </fo:table-cell>
                <fo:table-cell>
                    <fo:block>field2.row1</fo:block>
                </fo:table-cell>
                <fo:table-cell>
                    <fo:block>field3.row1</fo:block>
                </fo:table-cell>
            </fo:table-row>
            <fo:table-row>
                <fo:table-cell>
                    <fo:block>field1.row2</fo:block>
                </fo:table-cell>
                <fo:table-cell>
                    <fo:block>field2.row2</fo:block>
                </fo:table-cell>
                <fo:table-cell>
                    <fo:block>field3.row2</fo:block>
                </fo:table-cell>
            </fo:table-row>
            <fo:table-row>
                <fo:table-cell>
                    <fo:block>field1.row3</fo:block>
                </fo:table-cell>
                <fo:table-cell>
                    <fo:block>field2.row3</fo:block>
                </fo:table-cell>
                <fo:table-cell>
                    <fo:block>field3.row3</fo:block>
                </fo:table-cell>
            </fo:table-row>
            <fo:table-row>
                <fo:table-cell>
                    <fo:block>field1.row4</fo:block>
                </fo:table-cell>
                <fo:table-cell>
                    <fo:block>field2.row4</fo:block>
                </fo:table-cell>
                <fo:table-cell>
                    <fo:block>field3.row4</fo:block>
                </fo:table-cell>
            </fo:table-row>
        </fo:table-body>
    </fo:table>
</fo:table-and-caption>