基于列值在 xsl fo:table 中跨越动态行数

dynamic rows-number-spanned in xsl fo:table based on column values

您好,我正在尝试根据 column two 中的值对单元格进行分组, 使用它来使用 apache FOP

创建 PDF

我的密码是

document.xml

    <data>
    <data-body>
        <table-header>
            <column-one>Column One</column-one>
            <column-two>Column Two</column-two>
            <column-three>Column Three</column-three>
            <column-four>Column Four</column-four>
        </table-header>
        <table-data>
            <column-one>One</column-one>
            <column-two>5000</column-two>
            <column-three>Three</column-three>
            <column-four>Four</column-four>
        </table-data>
        <table-data>
            <column-one>One</column-one>
            <column-two>5000</column-two>
            <column-three>Three</column-three>
            <column-four>Four</column-four>
        </table-data>
        <table-data>
            <column-one>One</column-one>
            <column-two>1200</column-two>
            <column-three>Three</column-three>
            <column-four>Four</column-four>
        </table-data>
        <table-data>
            <column-one>One</column-one>
            <column-two>2000</column-two>
            <column-three>Three</column-three>
            <column-four>Four</column-four>
        </table-data>
        <table-data>
            <column-one>One</column-one>
            <column-two>2000</column-two>
            <column-three>Three</column-three>
            <column-four>Four</column-four>
        </table-data>
         </data-body>
    </data>

template.xsl

<?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:fo="http://www.w3.org/1999/XSL/Format">
        <xsl:template match="data">
            <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
                <fo:layout-master-set>
                    <fo:simple-page-master master-name="simple"
                        page-height="8.5in" page-width="11in" margin-top=".5in"
                        margin-bottom=".5in" margin-left=".5in" margin-right=".5in">
                        <fo:region-body margin-top="2cm" margin-bottom="2cm" />
                        <fo:region-before extent="2cm" overflow="hidden" />
                        <fo:region-after extent="1cm" overflow="hidden" />
                    </fo:simple-page-master>
                </fo:layout-master-set>
                <fo:page-sequence master-reference="simple"
                    initial-page-number="1">
                    <fo:static-content flow-name="xsl-region-before">
                        <fo:block font-size="13.0pt" font-family="serif"
                            padding-after="2.0pt" space-before="4.0pt" text-align="center"
                            border-bottom-style="solid" border-bottom-width="1.0pt">
                            <xsl:text>PDF Test</xsl:text>
                        </fo:block>
                    </fo:static-content>
                    <fo:static-content flow-name="xsl-region-after">
                        <fo:block font-size="12.0pt" font-family="sans-serif"
                            padding-after="2.0pt" space-before="2.0pt" text-align="center"
                            border-top-style="solid" border-bottom-width="1.0pt">
                            <xsl:text>Page</xsl:text>
                            <fo:page-number />
                        </fo:block>
                    </fo:static-content>
                    <fo:flow flow-name="xsl-region-body">
                        <xsl:apply-templates select="data-body" />
                    </fo:flow>
                </fo:page-sequence>
            </fo:root>
        </xsl:template>
        <xsl:template match="data-body">
            <fo:block text-align="center">
                <fo:table table-layout="fixed" width="100%"
                    border-style="dashed">
                    <fo:table-column border-style="solid" />
                    <fo:table-column border-style="solid" />
                    <fo:table-column border-style="solid" />
                    <fo:table-header>
                        <xsl:apply-templates select="table-header" />
                    </fo:table-header>
                    <fo:table-body>
                        <xsl:apply-templates select="table-data" />
                    </fo:table-body>
                </fo:table>
            </fo:block>
        </xsl:template>
        <xsl:template match="table-header">
            <fo:table-row keep-together.within-page="always"
                border-style="solid">
                <fo:table-cell>
                    <fo:block font-size="10pt" font-family="sans-serif"
                        padding-top="3pt">
                        <xsl:value-of select="column-one"></xsl:value-of>
                    </fo:block>
                </fo:table-cell>
                <fo:table-cell>
                    <fo:block font-size="10pt" font-family="sans-serif"
                        padding-top="3pt">
                        <xsl:value-of select="column-two"></xsl:value-of>
                    </fo:block>
                </fo:table-cell>
                <fo:table-cell>
                    <fo:block font-size="10pt" font-family="sans-serif"
                        padding-top="3pt">
                        <xsl:value-of select="column-three"></xsl:value-of>
                    </fo:block>
                </fo:table-cell>
            </fo:table-row>
        </xsl:template>
        <xsl:template match="table-data">
            <fo:table-row keep-together.within-page="always"
                border-style="solid">
                <fo:table-cell>
                    <fo:block font-size="10pt" font-family="sans-serif"
                        padding-top="3pt">
                        <xsl:value-of select="column-one"></xsl:value-of>
                    </fo:block>
                </fo:table-cell>
                <fo:table-cell>
                    <fo:block font-size="10pt" font-family="sans-serif"
                        padding-top="3pt">
                        <xsl:value-of select="column-two"></xsl:value-of>
                    </fo:block>
                </fo:table-cell>
                <fo:table-cell>
                    <fo:block font-size="10pt" font-family="sans-serif"
                        padding-top="3pt">
                        <xsl:value-of select="column-three"></xsl:value-of>
                    </fo:block>
                </fo:table-cell>
            </fo:table-row>
        </xsl:template>
    </xsl:stylesheet>

GeneratePDF.java

    package com.test.pdf;
    import java.io.File;
    import java.io.OutputStream;
    import javax.xml.transform.Result;
    import javax.xml.transform.Source;
    import javax.xml.transform.Transformer;
    import javax.xml.transform.TransformerFactory;
    import javax.xml.transform.sax.SAXResult;
    import javax.xml.transform.stream.StreamSource;
    import org.apache.fop.apps.FOUserAgent;
    import org.apache.fop.apps.Fop;
    import org.apache.fop.apps.FopFactory;
    import org.apache.fop.apps.MimeConstants;
    public class GeneratePDF {
        public static void main(String[] args) {
            try {
                System.out.println("FOP ExampleXML2PDF\n");
                System.out.println("Preparing...");
                // Setup input and output files
                File xmlfile = new File("src/", "document.xml");
                File xsltfile = new File("src/", "template.xsl");
                File pdffile = new File("C:\Users\Punithan Antony\Downloads\pdf", "ResultPDF.pdf");
                System.out.println("Input: XML (" + xmlfile + ")");
                System.out.println("Stylesheet: " + xsltfile);
                System.out.println("Output: PDF (" + pdffile + ")");
                System.out.println();
                System.out.println("Transforming...");
                // configure fopFactory as desired
                FopFactory fopFactory = FopFactory.newInstance(new File("src/fop.xconf"));
                //new File("src/fop.xconf");
                FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
                // configure foUserAgent as desired
                // Setup output
                OutputStream out = new java.io.FileOutputStream(pdffile);
                out = new java.io.BufferedOutputStream(out);
                try {
                    // Construct fop with desired output format
                    Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF,
                            foUserAgent, out);
                    // Setup XSLT
                    TransformerFactory factory = new net.sf.saxon.TransformerFactoryImpl();
                    Transformer transformer = factory
                            .newTransformer(new StreamSource(xsltfile));
                    // Set the value of a <param> in the stylesheet
                    // Setup input for XSLT transformation
                    Source src = new StreamSource(xmlfile);
                    // Resulting SAX events (the generated FO) must be piped through
                    // to FOP
                    Result res = new SAXResult(fop.getDefaultHandler());
                    // Start XSLT transformation and FOP processing
                    transformer.transform(src, res);
                } finally {
                    out.close();
                }
                System.out.println("Success!");
            } catch (Exception e) {
                System.out.print("ERROR!!");
                e.printStackTrace(System.err);
                System.exit(-1);
            }
        }
    }

对于特定列,如果 5000 在同一列中重复,我需要按顺序合并重复值 我需要根据值

动态合并单个单元格中的 5000

我也尝试过 ** xsl:for-each-group** group-adjacent="column-two" , column-grouping -key() 但它并没有像我预期的那样分组, 请帮助,提前致谢。

我想你想使用 group-adjacent 然后你需要传递组项目的计数和当前组索引来填充 number-rows-spanned 属性并阻止输出相邻组中的任何第二个 column-two 单元格:

<?xml version="1.0" encoding="UTF-8"?>
<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="#all"
    version="3.0">

  <xsl:output method="xml" indent="yes"/>

    <xsl:template match="data">
        <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
            <fo:layout-master-set>
                <fo:simple-page-master master-name="simple"
                    page-height="8.5in" page-width="11in" margin-top=".5in"
                    margin-bottom=".5in" margin-left=".5in" margin-right=".5in">
                    <fo:region-body margin-top="2cm" margin-bottom="2cm" />
                    <fo:region-before extent="2cm" overflow="hidden" />
                    <fo:region-after extent="1cm" overflow="hidden" />
                </fo:simple-page-master>
            </fo:layout-master-set>
            <fo:page-sequence master-reference="simple"
                initial-page-number="1">
                <fo:static-content flow-name="xsl-region-before">
                    <fo:block font-size="13.0pt" font-family="serif"
                        padding-after="2.0pt" space-before="4.0pt" text-align="center"
                        border-bottom-style="solid" border-bottom-width="1.0pt">
                        <xsl:text>PDF Test</xsl:text>
                    </fo:block>
                </fo:static-content>
                <fo:static-content flow-name="xsl-region-after">
                    <fo:block font-size="12.0pt" font-family="sans-serif"
                        padding-after="2.0pt" space-before="2.0pt" text-align="center"
                        border-top-style="solid" border-bottom-width="1.0pt">
                        <xsl:text>Page</xsl:text>
                        <fo:page-number />
                    </fo:block>
                </fo:static-content>
                <fo:flow flow-name="xsl-region-body">
                    <xsl:apply-templates select="data-body" />
                </fo:flow>
            </fo:page-sequence>
        </fo:root>
    </xsl:template>
    <xsl:template match="data-body">
        <fo:block text-align="center">
            <fo:table table-layout="fixed" width="100%"
                border-style="dashed">
                <fo:table-column border-style="solid" />
                <fo:table-column border-style="solid" />
                <fo:table-column border-style="solid" />
                <fo:table-header>
                    <xsl:apply-templates select="table-header" />
                </fo:table-header>
                <fo:table-body>
                    <xsl:for-each-group select="table-data" group-adjacent="column-two">
                        <xsl:apply-templates select="current-group()">
                            <xsl:with-param name="row-span" select="count(current-group())" tunnel="yes"/>
                        </xsl:apply-templates>
                    </xsl:for-each-group>
                </fo:table-body>
            </fo:table>
        </fo:block>
    </xsl:template>

    <xsl:template match="table-header">
        <fo:table-row keep-together.within-page="always"
            border-style="solid">
            <fo:table-cell>
                <fo:block font-size="10pt" font-family="sans-serif"
                    padding-top="3pt">
                    <xsl:value-of select="column-one"></xsl:value-of>
                </fo:block>
            </fo:table-cell>
            <fo:table-cell>
                <fo:block font-size="10pt" font-family="sans-serif"
                    padding-top="3pt">
                    <xsl:value-of select="column-two"></xsl:value-of>
                </fo:block>
            </fo:table-cell>
            <fo:table-cell>
                <fo:block font-size="10pt" font-family="sans-serif"
                    padding-top="3pt">
                    <xsl:value-of select="column-three"></xsl:value-of>
                </fo:block>
            </fo:table-cell>
        </fo:table-row>
    </xsl:template>

    <xsl:template match="table-data">
        <fo:table-row keep-together.within-page="always"
            border-style="solid">
            <xsl:apply-templates>
                <xsl:with-param name="row-group-index" tunnel="yes" select="position()"/>
            </xsl:apply-templates>
        </fo:table-row>
    </xsl:template>

    <xsl:template match="table-data/column-four" priority="2"/>

    <xsl:template match="table-data/*">
        <fo:table-cell>
            <fo:block font-size="10pt" font-family="sans-serif"
                padding-top="3pt">
                <xsl:value-of select="."></xsl:value-of>
            </fo:block>
        </fo:table-cell>
    </xsl:template>

    <xsl:template match="table-data/column-two">
        <xsl:param name="row-span" tunnel="yes"/>
        <xsl:param name="row-group-index" tunnel="yes"/>
        <xsl:choose>
            <xsl:when test="$row-span = 1">
                <xsl:next-match/>
            </xsl:when>
            <xsl:when test="$row-span > 1 and $row-group-index = 1">
                <fo:table-cell number-rows-spanned="{$row-span}">
                    <fo:block font-size="10pt" font-family="sans-serif"
                        padding-top="3pt">
                        <xsl:value-of select="."></xsl:value-of>
                    </fo:block>
                </fo:table-cell>                
            </xsl:when>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/3NSSEuY/1