uia4j / uia-fop

create XSL-FO Template, generate PDF files using Apache FOP framework

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Creation of XSL-FO Template

Movtivation

I need to generate PDF documents based on XML model and XSLT style sheet. The Apach FOP framework is a good solution, but the XSL-FO the framework uses is hard to be prepared.

Therefore I created this libary to help me quickly create a temporary XSL-FO template which meets 60% of the requirements. Then I edited it to meet 100% requirements. Finally I used Apahe FOP framework to generate PDF files.

Due to my poor technology, this library is not a full solution. It just saves the time to initialize templates, you need the XSLT/XSL-FO knowledge to edit them to meet all your requirements.

The libary can export XSL-FO of Microsot Word. Maybe you can try to use Microsot Word to design documents and use this libary output XSL-FO result.

Simple Tutorial

The tutorial will create the document below.

  1. Choose content builders.
  • Form
  • Table
  • PageNumber
  • ... (depending on the requirements)
  1. Design XSL-FO template and output XML result.

  2. Integrated with XSLT.

  3. Ouput the PDF file.

1. Choose Content Builders

Form Builder

  1. Thinking of Layout

    row \ col 0 1
    row: 0 Name order/name WorkGroup order/workGroup
    1 Description order/description QA Group order/qaGroup
    2 Begin Time order/runBeginTime MA Type freqName
    3 End Time order/runEndTime
  2. The Java Code

    FormBuilder from = new FormBuilder(2)
        .addInfo("Name", 0, 0, "order/name")
        .addInfo("Description", 1, 0, "order/description")
        .addInfo("Begin Time", 2, 0, "order/runBeginTime")
        .addInfo("End Time", 3, 0, "order/runEndTime")
        .addInfo("Work Group", 0, 1, "order/workGroup")
        .addInfo("QA Group", 1, 1, "order/qaGroup")
        .addInfo("MA Type", 2, 1, "order/freqName");

Table Builder

  1. Thinking of Layout

    Seq No Item Name Result Remark
    seqNo itemName maResult maRemark
  2. The Java Code

    TableBuilder table = new TableBuilder(4)
        .createHeaders(new String[] { "Seq No", "Item Name", "Result", "Remark" })
        .createRowTemplate(new String[] {
            "seqNo",
            "itemName",
            "maResult",
            "maRemark"
        });

PageNumber Builder

  1. Thinking of Layout

    left center right
    Page Number
  2. The Java Code

    PageNumberBuilder pn = new PageNumberBuilder()

2. Design XSL-FO template

  1. The Java Code

    // 1. carete a XML builder (fo:root)
    FoXML xml = new FoXML();
    
    // 2. create a layout (fo:simple-page-master)
    xml.createLayout("MA_ORDER", Paper.A4)
        .enableHeader()
        .enableFooter();
    
    // 3. create a page (fo:page-sequence)
    FoPage page = xml.addPage("MA_ORDER");
    
    // 4. 'form' as part of the body of the page (fo:flow)
    form.applyToBody(page);
    // 5. 'table' as part of the body of the page (fo:flow)
    table.applyToBody(page);
    // 6. 'pageNumber' at the footer of the page (fo:static-content)
    pn.applyToFooter(page);
    
    // 7. generate the XSL-FO content
    String result = xml.build();
  2. Save XSL-FO Content

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
        <fo:layout-master-set>
            <fo:simple-page-master master-name="MA_ORDER_REPORT" page-height="29.7cm" page-width="21.0cm" margin="2cm">
                <fo:region-body region-name="region-body" margin-top="1cm" margin-bottom="1cm"/>
                <fo:region-before region-name="region-header"/>
                <fo:region-after region-name="region-footer"/>
            </fo:simple-page-master>
        </fo:layout-master-set>
        <fo:page-sequence master-reference="MA_ORDER_REPORT" font-family="Arial,sans-serif,SimHei">
            <fo:static-content flow-name="region-header">
                <fo:table margin-bottom="1cm">
                    <fo:table-column column-width="33%"/>
                    <fo:table-column column-width="33%"/>
                    <fo:table-column column-width="33%"/>
                    <fo:table-body>
                        <fo:table-row>
                            <fo:table-cell>
                                <fo:block margin-right="0.1mm"><xsl:value-of select="order/id" /></fo:block>
                            </fo:table-cell>
                            <fo:table-cell>
                                <fo:block margin-right="0.1mm">MA Order</fo:block>
                            </fo:table-cell>
                            <fo:table-cell>
                                <fo:block margin-right="0.1mm"><xsl:value-of select="order/runBeginTime" /></fo:block>
                            </fo:table-cell>
                        </fo:table-row>
                    </fo:table-body>
                </fo:table>
            </fo:static-content>
            <fo:static-content flow-name="region-footer">
                <fo:table margin-bottom="1cm">
                    <fo:table-column column-width="40%"/>
                    <fo:table-column column-width="20%"/>
                    <fo:table-column column-width="40%"/>
                    <fo:table-body>
                        <fo:table-row>
                            <fo:table-cell>
                                <fo:block/>
                            </fo:table-cell>
                            <fo:table-cell>
                                <fo:block text-align="center">
                                    <fo:page-number/>
                                </fo:block>
                            </fo:table-cell>
                            <fo:table-cell>
                                <fo:block text-align="right"/>
                            </fo:table-cell>
                        </fo:table-row>
                    </fo:table-body>
                </fo:table>
            </fo:static-content>
            <fo:flow flow-name="region-body">
                <fo:table margin-bottom="1cm">
                    <fo:table-column column-width="20%"/>
                    <fo:table-column column-width="30%"/>
                    <fo:table-column column-width="20%"/>
                    <fo:table-column column-width="30%"/>
                    <fo:table-body>
                        <fo:table-row>
                            <fo:table-cell>
                                <fo:block font-weight="bold" text-align="right" margin-right="0.1mm">Name</fo:block>
                            </fo:table-cell>
                            <fo:table-cell>
                                <fo:block><xsl:value-of select="order/name" /></fo:block>
                            </fo:table-cell>
                            <fo:table-cell>
                                <fo:block font-weight="bold" text-align="right" margin-right="0.1mm">Work Group</fo:block>
                            </fo:table-cell>
                            <fo:table-cell>
                                <fo:block><xsl:value-of select="order/workGroup" /></fo:block>
                            </fo:table-cell>
                        </fo:table-row>
                        <fo:table-row>
                            <fo:table-cell>
                                <fo:block font-weight="bold" text-align="right" margin-right="0.1mm">Description</fo:block>
                            </fo:table-cell>
                            <fo:table-cell>
                                <fo:block><xsl:value-of select="order/description" /></fo:block>
                            </fo:table-cell>
                            <fo:table-cell>
                                <fo:block font-weight="bold" text-align="right" margin-right="0.1mm">QA Group</fo:block>
                            </fo:table-cell>
                            <fo:table-cell>
                                <fo:block><xsl:value-of select="order/qaGroup" /></fo:block>
                            </fo:table-cell>
                        </fo:table-row>
                        <fo:table-row>
                            <fo:table-cell>
                                <fo:block font-weight="bold" text-align="right" margin-right="0.1mm">Begin Time</fo:block>
                            </fo:table-cell>
                            <fo:table-cell>
                                <fo:block><xsl:value-of select="order/runBeginTime" /></fo:block>
                            </fo:table-cell>
                            <fo:table-cell>
                                <fo:block font-weight="bold" text-align="right" margin-right="0.1mm">Type</fo:block>
                            </fo:table-cell>
                            <fo:table-cell>
                                <fo:block><xsl:value-of select="order/freqName" /></fo:block>
                            </fo:table-cell>
                        </fo:table-row>
                        <fo:table-row>
                            <fo:table-cell>
                                <fo:block font-weight="bold" text-align="right" margin-right="0.1mm">End Time</fo:block>
                            </fo:table-cell>
                            <fo:table-cell>
                                <fo:block><xsl:value-of select="order/runEndTime" /></fo:block>
                            </fo:table-cell>
                            <fo:table-cell/>
                            <fo:table-cell/>
                        </fo:table-row>
                    </fo:table-body>
                </fo:table>
                <fo:table table-layout="auto" border="solid 0.3mm black" margin="0.1mm">
                    <fo:table-column column-width="25%" border="solid 0.1mm black"/>
                    <fo:table-column column-width="25%" border="solid 0.1mm black"/>
                    <fo:table-column column-width="25%" border="solid 0.1mm black"/>
                    <fo:table-column column-width="25%" border="solid 0.1mm black"/>
                    <fo:table-header>
                        <fo:table-row border="solid 0.1mm black" background-color="#eeeeee">
                            <fo:table-cell>
                                <fo:block font-weight="bold" text-align="center">Seq No</fo:block>
                            </fo:table-cell>
                            <fo:table-cell>
                                <fo:block font-weight="bold" text-align="center">Item Name</fo:block>
                            </fo:table-cell>
                            <fo:table-cell>
                                <fo:block font-weight="bold" text-align="center">Result</fo:block>
                            </fo:table-cell>
                            <fo:table-cell>
                                <fo:block font-weight="bold" text-align="center">Remark</fo:block>
                            </fo:table-cell>
                        </fo:table-row>
                    </fo:table-header>
                    <fo:table-body>
                        <fo:table-row border="solid 0.1mm black">
                            <fo:table-cell>
                                <fo:block><xsl:value-of select="seqNo" /></fo:block>
                            </fo:table-cell>
                            <fo:table-cell>
                                <fo:block><xsl:value-of select="itemName" /></fo:block>
                            </fo:table-cell>
                            <fo:table-cell>
                                <fo:block><xsl:value-of select="maResult" /></fo:block>
                            </fo:table-cell>
                            <fo:table-cell>
                                <fo:block><xsl:value-of select="maRemark" /></fo:block>
                            </fo:table-cell>
                        </fo:table-row>
                    </fo:table-body>
                </fo:table>
            </fo:flow>
        </fo:page-sequence>
    </fo:root>

3. Integrated with XSLT

Commonly used tags of XSLT are xsl:for-each and value-of.

  1. Create a new XSLT file and manually add XSL-FO created above.

    <?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="/">
          <!-- XSL-FO template here -->
        </xsl:template>
    </xsl:stylesheet>
  2. Add xsl:for-each to bind data for fo:table-row.

    <xsl:for-each select="order/items/item">
        <fo:table-row>
          <!-- fo:table-cell -->
        </fo:table-row>
    </xsl:for-each>
  3. Add value-of to bind data in right block

    <fo:block>
        <xsl:value-of select="order/id" />
    </fo:block>
  4. Modify more to meet the requirements ...

4. Output the PDF file

  1. Prepare XML data

    <order>
        <id>MA-00419-191023-01</id>
        <name>MA-00419</name>
        <dscription>Line A</dscription>
        <runBeginTime>2019-10-23 08:00</runBeginTime>
        <runEndTime>2019-10-23 18:00</runEndTime>
        <workGroup>Line A WG009</workGroup>
        <qaGroup>QA 002</qaGroup>
        <freqName>Monthly</freqName>
        <items>
            <item>
                <seqNo>10</seqNo>
                <itemName>Item A</itemName>
                <maResult>OK</maResult>
                <maRemark></maRemark>
            </item>
            <item>
                <seqNo>20</seqNo>
                <itemName>Item B</itemName>
                <maResult>NG</maResult>
                <maRemark>Broken</maRemark>
            </item>
            <item>
                <seqNo>30</seqNo>
                <itemName>Item C</itemName>
                <maResult>OK</maResult>
                <maRemark></maRemark>
            </item>
            <item>
                <seqNo>40</seqNo>
                <itemName>Item D</itemName>
                <maResult>OK</maResult>
                <maRemark></maRemark>
            </item>
        </items>
    </order>
  2. The Java Code

    PdfFile.newInstance().save(
            new File("output.pdf"),
            new File("data.xml"),
            new File("data.xslt"));

Public References

About

create XSL-FO Template, generate PDF files using Apache FOP framework


Languages

Language:Java 98.8%Language:XSLT 1.2%