package com.cisetech.put.utils.fop;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
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.avalon.framework.logger.ConsoleLogger;
import org.apache.avalon.framework.logger.Logger;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.MimeConstants;
/**
* FopReport
* @author bin.yin 2012/12/23
*/
public class FopReport {
private static Logger log = new ConsoleLogger(ConsoleLogger.LEVEL_DEBUG);
// Step 1: Construct a FopFactory
private static final FopFactory fopFactory = FopFactory.newInstance();
/**
* 根据xsl模板及xml数据文件生成pdf
* @param xsltFile xsl模板
* @param xmlFile xml数据文件
* @return ReportData
* @throws Exception
* @author bin.yin 2012/12/25
*/
public static ReportData createReport(String xsltFile, String xmlFile) throws Exception {
ReportData reportData = new ReportData();
reportData.setContentType("application/pdf");
fopFactory.setUserConfig("conf/fop.xml");
// Step 2: Set up output stream.
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
// Step 3: Construct fop with desired output format
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, out);
// Step 4: Setup XSLT using identity transformer
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(new StreamSource(new File(xsltFile)));
// Step 5: Setup input and output for XSLT transformation
Source src = new StreamSource(new File(xmlFile));
// Source src = new StreamSource(new StringReader(myString));
// Step 6: Resulting SAX events (the generated FO) must be piped through to FOP
Result res = new SAXResult(fop.getDefaultHandler());
// Step 7: Start XSLT transformation and FOP processing
transformer.transform(src, res);
reportData.setData(out.toByteArray());
} catch(Exception e) {
throw e;
} finally {
out.close();
}
return reportData;
}
/**
* 根据xsl模板及xml字节数组生成pdf
* @param xsltFile xsl模板
* @param bXmlData xml字节数组 eg. StringBuffer buf = new StringBuffer(); buf.getBytes("UTF-8");
* @return ReportData
* @throws Exception
* @author bin.yin 2012/12/25
*/
public static ReportData createReport(String xsltFile, byte[] bXmlData) throws Exception {
ReportData reportData = new ReportData();
try {
// convert xml bytes to a temp file
File xmlFile = File.createTempFile("FOP", ".tmp");
FileOutputStream fos = new FileOutputStream(xmlFile);
fos.write(bXmlData);
fos.close();
reportData = createReport(xsltFile, xmlFile.getAbsolutePath());
// delete temp file
xmlFile.delete();
} catch (Exception e) {
throw e;
}
return reportData;
}
public static void main(String[] args) {
long t0 = System.currentTimeMillis();
try {
// StringBuffer buf = new StringBuffer();
// buf.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
// buf.append("<ItemListReport>");
// buf.append(" <ReportHeader>");
// buf.append(" <Title>附加条款</Title>");
// buf.append(" <PartyA>上海信息技术有限公司B</PartyA>");
// buf.append(" <PartyB>上海信息技术有限公司B</PartyB>");
// buf.append(" </ReportHeader>");
// buf.append(" <ReportBody>");
// buf.append(" <Table>");
// buf.append(" <TableRow>");
// buf.append(" <ItemName>附加条款1</ItemName>");
// buf.append(" <ItemTime>2012-12-23 09:03</ItemTime>");
// buf.append(" </TableRow>");
// buf.append(" <TableRow>");
// buf.append(" <ItemName>上海信息技术有限公司附加条款1</ItemName>");
// buf.append(" <ItemTime>2012-12-23 09:03</ItemTime>");
// buf.append(" </TableRow>");
// buf.append(" </Table>");
// buf.append(" </ReportBody>");
// buf.append(" <ReportFooter>");
// buf.append(" <PrintDate>2012-12-12</PrintDate>");
// buf.append(" <ReportNo>010123456789</ReportNo>");
// buf.append(" </ReportFooter>");
// buf.append("</ItemListReport>");
//
long t = System.currentTimeMillis();
//ReportData data = FopReport.createReport("report\\sample\\Sample.xsl", buf.toString().getBytes("UTF-8"));
ReportData data = FopReport.createReport("report\\sample\\Sample.xsl", "report\\sample\\Sample.xml");
long t1 = System.currentTimeMillis();
log.debug("time:" + (t1 - t));
FileOutputStream fos = new FileOutputStream("G:/sample.pdf");
fos.write(data.getData());
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
log.debug("use time:" + (System.currentTimeMillis() - t0));
}
}
package com.cisetech.put.utils.fop;
import java.io.Serializable;
/**
* <p>Title: </p>
* <p>Description: </p>
* @author bin.yin 2012/12/22
* @version 1.0
*/
public class ReportData implements Serializable {
private static final long serialVersionUID = -2722248902864797698L;
private byte[] mbData = null;
private String msContentType = null;
public byte[] getData() {
return mbData;
}
public void setData(byte[] pData) {
mbData = pData;
}
public String getContentType() {
return msContentType;
}
public void setContentType(String pContentType) {
msContentType = pContentType;
}
}
FOP.XML文件内容
<?xml version="1.0"?>
<!-- $Id: fop.xml 901793 2012-12-21 bin.yin $ -->
<!-- NOTE: This is the version of the configuration -->
<fop version="1.0">
<!-- Base URL for resolving relative URLs -->
<base>.</base>
<!-- Source resolution in dpi (dots/pixels per inch) for determining the size of pixels in SVG and bitmap images, default: 72dpi -->
<source-resolution>72</source-resolution>
<!-- Target resolution in dpi (dots/pixels per inch) for specifying the target resolution for generated bitmaps, default: 72dpi -->
<target-resolution>72</target-resolution>
<!-- Default page-height and page-width, in case value is specified as auto -->
<default-page-settings height="29.7cm" width="21cm"/>
<!-- Information for specific renderers -->
<!-- Uses renderer mime type for renderers -->
<renderers>
<renderer mime="application/pdf">
<filterList>
<!-- provides compression using zlib flate (default is on) -->
<value>flate</value>
</filterList>
<fonts>
<!-- embedded fonts -->
<!--
This information must exactly match the font specified
in the fo file. Otherwise it will use a default font.
For example,
<fo:inline font-family="Arial" font-weight="bold" font-style="normal">
Arial-normal-normal font
</fo:inline>
for the font triplet specified by:
<font-triplet name="Arial" style="normal" weight="bold"/>
If you do not want to embed the font in the pdf document
then do not include the "embed-url" attribute.
The font will be needed where the document is viewed
for it to be displayed properly.
possible styles: normal | italic | oblique | backslant
possible weights: normal | bold | 100 | 200 | 300 | 400
| 500 | 600 | 700 | 800 | 900
(normal = 400, bold = 700)
-->
<font metrics-url="conf/fonts/arial.xml" kerning="yes" embed-url="conf/fonts/arial.ttf">
<font-triplet name="Arial" style="normal" weight="normal"/>
<font-triplet name="Arial" style="italic" weight="normal"/>
</font>
<font metrics-url="conf/fonts/arialb.xml" kerning="yes" embed-url="conf/fonts/arialb.ttf">
<font-triplet name="Arial" style="normal" weight="bold"/>
<font-triplet name="Arial" style="italic" weight="bold"/>
</font>
<font metrics-url="conf/fonts/SimHei.xml" kerning="yes" embed-url="conf/fonts/SimHei.ttf">
<font-triplet name="SimHei" style="normal" weight="normal"/>
<font-triplet name="SimHei" style="normal" weight="bold"/>
<font-triplet name="SimHei" style="italic" weight="normal"/>
<font-triplet name="SimHei" style="italic" weight="bold"/>
</font>
<font metrics-url="conf/fonts/SimSun.xml" kerning="yes" embed-url="conf/fonts/SimSun.ttc">
<font-triplet name="SimSun" style="normal" weight="normal" />
<font-triplet name="SimSun" style="normal" weight="bold" />
<font-triplet name="SimSun" style="italic" weight="normal" />
<font-triplet name="SimSun" style="italic" weight="bold" />
</font>
<!--新宋体//-->
<font metrics-url="conf/fonts/NSimSun.xml" kerning="yes" embed-url="conf/fonts/SimSun.ttc">
<font-triplet name="NSimSun" style="normal" weight="normal" />
<font-triplet name="NSimSun" style="normal" weight="bold" />
<font-triplet name="NSimSun" style="italic" weight="normal" />
<font-triplet name="NSimSun" style="italic" weight="bold" />
</font>
<font metrics-url="conf/fonts/Code39Seven.xml" kerning="yes" embed-url="conf/fonts/Code39Seven.ttf">
<font-triplet name="Code39Seven" style="normal" weight="normal" />
</font>
</fonts>
<!-- This option lets you specify additional options on an XML handler -->
<!--xml-handler namespace="http://www.w3.org/2000/svg">
<stroke-text>false</stroke-text>
</xml-handler-->
</renderer>
<renderer mime="application/postscript">
<!-- This option forces the PS renderer to rotate landscape pages -->
<!--auto-rotate-landscape>true</auto-rotate-landscape-->
<!-- This option lets you specify additional options on an XML handler -->
<!--xml-handler namespace="http://www.w3.org/2000/svg">
<stroke-text>false</stroke-text>
</xml-handler-->
</renderer>
<renderer mime="image/png">
<!--transparent-page-background>true</transparent-page-background-->
</renderer>
<renderer mime="image/tiff">
<!--transparent-page-background>true</transparent-page-background-->
<!--compression>CCITT T.6</compression-->
</renderer>
<renderer mime="text/xml">
</renderer>
<!-- RTF does not have a renderer
<renderer mime="text/rtf">
</renderer>
-->
</renderers>
</fop>
Sample.xml文件内容
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="Sample.xsl" ?>
<ItemListReport>
<ReportHeader>
<Title>附加条款</Title>
<PartyA>中国科技</PartyA>
<PartyB>上海信息技术有限公司</PartyB>
</ReportHeader>
<ReportBody>
<Table>
<TableRow>
<ItemName>附加条款1</ItemName>
<ItemTime>2012-12-23 09:03</ItemTime>
</TableRow>
<TableRow>
<ItemName>上海信息技术有限公司附加条款1</ItemName>
<ItemTime>2012-12-23 09:03</ItemTime>
</TableRow>
<TableRow>
<ItemName>上海信息技术有限公司附加条款1</ItemName>
<ItemTime>2012-12-23 09:03</ItemTime>
</TableRow>
<TableRow>
<ItemName>上海信息技术有限公司附加条款1</ItemName>
<ItemTime>2012-12-23 09:03</ItemTime>
</TableRow>
<TableRow>
<ItemName>上海信息技术有限公司附加条款1</ItemName>
<ItemTime>2012-12-23 09:03</ItemTime>
</TableRow>
</Table>
</ReportBody>
<ReportFooter>
<PrintDate>2012-12-12</PrintDate>
<ReportNo>010123456789</ReportNo>
</ReportFooter>
</ItemListReport>
Sample.xls
<?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" exclude-result-prefixes="fo">
<!-- 根元素 -->
<xsl:template match="/">
<xsl:apply-templates select="ItemListReport" />
</xsl:template>
<!--主模板//-->
<xsl:template match="ItemListReport">
<xsl:processing-instruction name="cocoon-format">type="text/xslfo"</xsl:processing-instruction>
<!--在此可以定义一些全局的风格信息,如字体等-->
<fo:root font-family="SimSun" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<!--版面定义//-->
<fo:layout-master-set>
<fo:simple-page-master master-name="main" margin-top="1cm" margin-bottom="1cm" margin-left="1cm" margin-right="1cm">
<!--主体//-->
<fo:region-body margin-top="1cm" margin-bottom="1cm" />
<!--页眉//-->
<fo:region-before extent="1cm" />
<!--页脚//-->
<fo:region-after extent="1cm" />
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="main">
<!--页眉显示内容-->
<fo:static-content flow-name="xsl-region-before">
<fo:block font-size="10pt" text-align="end" line-height="12pt">PDF 报表样例</fo:block>
<!-- <fo:block text-align="end">
<fo:external-graphic src="report/sample/title.jpg"/>
</fo:block> -->
</fo:static-content>
<!--页脚显示内容-->
<fo:static-content flow-name="xsl-region-after">
<fo:block line-height="10pt" font-size="10pt" text-align="center">
共<fo:page-number-citation ref-id="endofdoc"/>页<xsl:text> </xsl:text>第<fo:page-number/>页
</fo:block>
</fo:static-content>
<!--页面主体内容-->
<fo:flow flow-name="xsl-region-body">
<!--报表头-->
<xsl:apply-templates select="ReportHeader" />
<!--报表体(若有多个部分内容,参照下面一行重复)-->
<xsl:apply-templates select="ReportBody" />
<!--报表尾-->
<xsl:apply-templates select="ReportFooter" />
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<!--报表头//-->
<xsl:template match="ReportHeader">
<!--标题-->
<fo:block font-size="24pt" font-weight="bold" line-height="30pt" vertical-align="top"
text-align-last="center" space-before.optimum="12pt">
<xsl:value-of select="Title" />
</fo:block>
<!--用一个表格来格式化显示其余信息-->
<fo:block font-size="12pt">
<fo:table table-layout="fixed" width="100%" border-collapse="separate">
<fo:table-column column-width="1.3cm" />
<fo:table-column column-width="17.7cm" />
<fo:table-body>
<fo:table-row>
<fo:table-cell text-align="start">
<fo:block><xsl:text>甲方:</xsl:text></fo:block>
</fo:table-cell>
<fo:table-cell text-align="start">
<fo:block><xsl:value-of select="PartyA" /></fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell text-align="start">
<fo:block><xsl:text>乙方:</xsl:text></fo:block>
</fo:table-cell>
<fo:table-cell text-align="start">
<fo:block><xsl:value-of select="PartyB" /></fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:block>
</xsl:template>
<!--报表主体(一般只有一个表格)//-->
<xsl:template match="ReportBody">
<xsl:apply-templates select="Table" />
</xsl:template>
<!--报表尾//-->
<xsl:template match="ReportFooter">
<fo:block font-size="12pt" line-height="15pt" text-align="start" space-before.optimum="12pt">
<xsl:text>签订时间:</xsl:text>
<xsl:value-of select="PrintDate" />
</fo:block>
<fo:block id="endofdoc"></fo:block>
<fo:block font-family="Code39Seven" font-size="14pt" line-height="18pt">*<xsl:value-of select="ReportNo" />*</fo:block>
</xsl:template>
<!--表格数据//-->
<xsl:template match="Table">
<fo:block font-size="12pt">
<fo:table table-layout="fixed" width="100%" border-collapse="separate"
text-align="center" border-width="0.5pt" border-style="solid" space-before.optimum="12pt">
<!-- 定义列(与实际列数严格一致) //-->
<fo:table-column column-width="13cm" />
<fo:table-column column-width="6cm" />
<!-- 定义表头 //-->
<fo:table-header>
<fo:table-row font-weight="bold" font-size="13pt" border-width="0.5pt" border-style="solid">
<fo:table-cell border-color="black" border-width="0.2pt" border-style="solid">
<fo:block>条款名称</fo:block>
</fo:table-cell>
<fo:table-cell border-color="black" border-width="0.2pt" border-style="solid">
<fo:block>录入时间</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-header>
<!-- 表格数据 //-->
<fo:table-body>
<xsl:apply-templates select="TableRow" />
</fo:table-body>
</fo:table>
</fo:block>
<fo:block space-before.optimum="12pt">注:显示表格每一行的模板</fo:block>
</xsl:template>
<!--显示表格每一行的模板//-->
<xsl:template match="TableRow">
<fo:table-row space-before.optimum="3pt">
<fo:table-cell border-color="black" border-width="0.2pt" border-style="solid">
<fo:block><xsl:value-of select="ItemName" /></fo:block>
</fo:table-cell>
<fo:table-cell border-color="black" border-width="0.2pt" border-style="solid">
<fo:block><xsl:value-of select="ItemTime" /></fo:block>
</fo:table-cell>
</fo:table-row>
</xsl:template>
</xsl:stylesheet>
需要额外导入font。。。。未完待续