xml转pdf xsl取值问题 语法问题

将xml文件转为pdf 以及xsl取值问题 语法问题


前言


一、转化思路

需要创建一个.xsl文件作为pdf模板,同时xsl文件中读取xml中的数据

二、使用步骤

1.引入maven依赖

代码如下(示例):

<dependency>
	<groupId>javax.xml.ws</groupId>
	<artifactId>jaxws-api</artifactId>
	<scope>test</scope>
</dependency>
<dependency>
     <groupId>org.apache.xmlgraphics</groupId>
     <artifactId>fop</artifactId>
     <version>2.1</version>
</dependency>

2.创建xsl文件

xls模板生成的图的大致是这样的,我做了部分截取,同时贴上的xsl文件也只是取了一部分
fo:table标签理解为table就好,fo:table-row就是行, 根据自己的需求加就行这个是简单
在这里插入图片描述

含有一些隐私信息我做了简化:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"
                version="1.0">
    <xsl:output encoding="UTF-8" indent="yes" method="xml" standalone="no" omit-xml-declaration="no"/>
    <xsl:template match="InvoiceXML">
        <fo:root language="EN">
            <fo:layout-master-set>
                <fo:simple-page-master master-name="A4-portrail" page-height="297mm" page-width="210mm" margin-top="5mm"
                                       margin-bottom="5mm" margin-left="5mm" margin-right="5mm">
                    <fo:region-body margin-top="25mm" margin-bottom="20mm"/>
                    <fo:region-before region-name="xsl-region-before" extent="25mm" display-align="before"
                                      precedence="true"/>
                    <fo:region-after region-name="xsl-region-after" extent="25mm" display-align="before"
                                     precedence="true"/>
                </fo:simple-page-master>
            </fo:layout-master-set>
            <fo:page-sequence master-reference="A4-portrail">
                <fo:static-content flow-name="xsl-region-before">
                    <fo:block border-top-width="2pt" border-top-style="solid" border-top-color="#d6d6d6"
                              text-align="center">
                    </fo:block>
                </fo:static-content>
                <fo:flow flow-name="xsl-region-body" border-collapse="collapse" reference-orientation="0">

                    <fo:list-block>
                        <fo:list-item relative-align="before">
                            <fo:list-item-label end-indent="label-end()">
                                <fo:block>
                                    <fo:external-graphic src="file:///C:/Users/test/Downloads/logo.png" width="10mm"
                                                         height="10mm" content-width="scale-to-fit"/>
                                </fo:block>
                            </fo:list-item-label>
                            <fo:list-item-body start-indent="body-start()">
                                <fo:block margin-left="2mm" margin-top="4mm" font-size="15pt">Invoice</fo:block>
                            </fo:list-item-body>
                        </fo:list-item>
                    </fo:list-block>

                    <fo:table table-layout="fixed" width="100%" font-size="8pt">
                        <fo:table-column column-width="proportional-column-width(20)"/>
                        <fo:table-column column-width="proportional-column-width(25)"/>
                        <fo:table-column column-width="proportional-column-width(20)"/>
                        <fo:table-column column-width="proportional-column-width(35)"/>
                        <fo:table-body>
                            <fo:table-row>
                                <fo:table-cell text-align="left" display-align="center" padding-left="2mm">
                                    <fo:block>
                                        ID
                                    </fo:block>
                                </fo:table-cell>
                                <fo:table-cell text-align="left" display-align="center" padding-left="2mm">
                                    <fo:block>
                                    <!-- 取值的意思就是按照元素从父元素到子元素-->
                                        <xsl:value-of select="invoiceDetails/id"/>
                                    </fo:block>
                                </fo:table-cell>
                                <fo:table-cell text-align="left" display-align="center" padding-left="2mm">
                                    <fo:block>
                                        Buyer
                                    </fo:block>
                                </fo:table-cell>
                                <fo:table-cell text-align="left" display-align="center" padding-right="2mm">
                                    <fo:block>
                                        <xsl:value-of select="buyer/details/buyerName"/>
                                    </fo:block>
                                </fo:table-cell>
                            </fo:table-row>

                           
                            <fo:table-row>
                                <fo:table-cell text-align="left" display-align="center" padding-left="2mm">
                                    <fo:block>
                                        End Date
                                    </fo:block>
                                </fo:table-cell>
                                <fo:table-cell text-align="left" display-align="center" padding-left="2mm">
                                    <fo:block>
                                        <xsl:value-of select="concat(substring-after(translate(invoiceDetails/worker/endDate,'-','/'),'/'),concat('/',substring-before(translate(invoiceDetails/worker/endDate,'-','/'),'/')))"/>
                                    </fo:block>
                                </fo:table-cell>
                                <fo:table-cell text-align="left" display-align="center" padding-left="2mm">
                                    <fo:block>
                                        Submitted By
                                    </fo:block>
                                </fo:table-cell>
                                <fo:table-cell text-align="left" display-align="center" padding-right="2mm">
                                    <fo:block>
                                         <xsl:value-of select="costCenterAmount[@type='adjustment']/amount"/>
                                    </fo:block>
                                </fo:table-cell>
                            </fo:table-row>

                        </fo:table-body>
                    </fo:table>
                      <fo:table table-layout="fixed" width="100%" font-size="8pt" margin-top="10mm">
                        <fo:table-column column-width="proportional-column-width(15)"/>
                        <fo:table-column column-width="proportional-column-width(10)"/>
                        <fo:table-column column-width="proportional-column-width(10)"/>
                        <fo:table-column column-width="proportional-column-width(10)"/>
                        <fo:table-body>
                            <fo:table-row font-size="10pt" background-color="#d6d6d6" border-bottom-width="0.2mm"
                                          border-bottom-style="solid" border-bottom-color="black">
                                <fo:table-cell text-align="left" display-align="center" padding-left="2mm">
                                    <fo:block>
                                        Cost Allocation (EUR)
                                    </fo:block>
                                </fo:table-cell>
                                <fo:table-cell text-align="left" display-align="center" padding-left="2mm">
                                    <fo:block>
                                    </fo:block>
                                </fo:table-cell>
                                <fo:table-cell text-align="left" display-align="center" padding-left="2mm">
                                    <fo:block>
                                    </fo:block>
                                </fo:table-cell>
                                <fo:table-cell text-align="left" display-align="center" padding-left="2mm">
                                    <fo:block>
                                    </fo:block>
                                </fo:table-cell>
                            </fo:table-row>
                            <fo:table-row border-bottom-width="0.001mm" border-bottom-style="solid"
                                          border-bottom-color="white">
                                <fo:table-cell text-align="left" display-align="center" padding-left="2mm">
                                    <fo:block>
                                        Cost Center
                                    </fo:block>
                                </fo:table-cell>
                                <fo:table-cell text-align="right" display-align="center" padding-left="2mm">
                                    <fo:block>
                                        Detail Amount
                                    </fo:block>
                                </fo:table-cell>
                                <fo:table-cell text-align="right" display-align="center" padding-left="2mm">
                                    <fo:block>
                                        Adjustment
                                    </fo:block>
                                </fo:table-cell>
                                <fo:table-cell text-align="right" display-align="center" padding-left="2mm">
                                    <fo:block>
                                        Amount
                                    </fo:block>
                                </fo:table-cell>
                            </fo:table-row>

                            <xsl:for-each select="accounting/costCenterAllocation/costCenter">
                                <fo:table-row border-bottom-width="0.1mm" border-bottom-style="solid"
                                              border-bottom-color="black">
                                    <fo:table-cell text-align="left" display-align="center" padding-left="2mm">
                                        <fo:block>
                                            <xsl:value-of
                                                    select="//lineItemDetails/lineItemDetails/timeSheets/timeSheetHoursWorked/billable/costCenterName"/>
                                        </fo:block>
                                    </fo:table-cell>
                                    <fo:table-cell text-align="right" display-align="center" padding-left="2mm">
                                        <fo:block>
                                            <!-- <costCenterAmount type="detailAmount" fgLabel="Detail Amount">-->
                                            <xsl:value-of select="costCenterAmount[@type='detailAmount']/amount"/>
                                        </fo:block>
                                    </fo:table-cell>
                                    <fo:table-cell text-align="right" display-align="center" padding-left="2mm">
                                        <fo:block>
                                            <!-- <costCenterAmount type="adjustment" fgLabel="Adjustment">-->
                                            <xsl:value-of select="costCenterAmount[@type='adjustment']/amount"/>
                                        </fo:block>
                                    </fo:table-cell>
                                    <fo:table-cell text-align="right" display-align="center" padding-left="2mm">
                                        <fo:block>
                                            <!-- <costCenterAmount type="amount" fgLabel="Amount">-->
                                            <xsl:value-of select="costCenterAmount[@type='amount']/amount"/>
                                        </fo:block>
                                    </fo:table-cell>
                                </fo:table-row>

                            </xsl:for-each>
                        </fo:table-body>




                </fo:flow>

            </fo:page-sequence>
        </fo:root>
    </xsl:template>
</xsl:stylesheet>

java的代码如下

package com.demo.invoice;
import org.apache.fop.apps.*;

import javax.xml.transform.*;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;

/**
 * @author shenyuan
 * @date 2022-03-08 5:38
 */
public class SwissDataConvertPdf {
    private static String INPUT_PATH="src/main/resources/input";
    private static String OUTPUT_PATH="src/main/resources/output";
    public static void main(String [] args){
        try{
            convertPdf();
        }catch (Exception e){
            e.printStackTrace();
        }

    }
    public static void  convertPdf () throws IOException, FOPException, TransformerException {
        // 这个定义好的模板文件
        File xsltFile = new File( INPUT_PATH+"/invoice_template_Swiss.xsl");
        long length = xsltFile.length();
        // 这个就是那个xml数据文件
        StreamSource xmlSource = new StreamSource(new File(INPUT_PATH + "/Swiss_data.xml"));
     
        FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());
        FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
        // 输出的pdf
        OutputStream out;
        out = new java.io.FileOutputStream(OUTPUT_PATH + "/ebay_invoice_Swiss.pdf");

        try {
            Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);
            TransformerFactory factory = TransformerFactory.newInstance();
            Transformer transformer = factory.newTransformer(new StreamSource(xsltFile));
            Result res = new SAXResult(fop.getDefaultHandler());
            transformer.transform(xmlSource, res);
        } finally {
            out.close();
        }
    }
}


总结

可能大家对xls取值会有一些疑问我举例子说名

//这是xsl中取值的 可以去我贴的xls代码中找
 <xsl:value-of select="invoiceDetails/id"/>
//对应的 xml元素是这样的
<invoiceDetails label="Invoice Details">
    <id label="ID">123455</id>
</invoiceDetails>  
//大家又有一个问题假如这样的层级有好多个呢
<invoiceDetails label="Invoice Details">
    <id label="ID">123455</id>
    <id label="IDS">23444</id>
</invoiceDetails> 
//xsl提供了这样的语法,以此类推
 <xsl:value-of select="invoiceDetails/id[@label='IDS']"/>
//可能又有这样的问题,表格中的行数是动态的 我需要查到所有的元素拼接到table上
//没关系 xsl提供了 <xsl:for-each> 去我贴的xsl代码中查找
//accounting/costCenterAllocation/costCenter 是外层元素
 <xsl:for-each select="accounting/costCenterAllocation/costCenter">
 //这是接着for-foreach元素的子元素 意思就是遍历每个 accounting/costCenterAllocation/costCenter元素中的 每个costCenterAmount
 <xsl:value-of select="costCenterAmount[@type='detailAmount']/amount"/>
 //如果有的行数据不是在for-each遍历的子元素下呢
 // 看以下的代码 lineItemDetail和accounting平级的 //lineItemDetail就能跳出到 accounting从lineItemDetail元素开始查找
 <xsl:value-of                                                  select="//lineItemDetails/lineItemDetails/timeSheets/timeSheetHoursWorked/billable/costCenterName"/>
 //关于对取到的值进行处理 xsl数值函数与字符串函数 我只举一个例子
  <xsl:value-of select="invoiceDetails/worker/endDate"/>
  //把取到的值中的-转换为/,用字符串转换函数这样写,支持函数嵌套
  <xsl:value-of select="translate(invoiceDetails/worker/endDate,'-','/')"/>
  //最后一个问题  xsl配置 例如
  <xsl:template match="InvoiceXML">这个别忘了
  InvoiceXML对应xml的根元素
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值