数据源
大约 9 分钟数据源
说明
数据源可分为手动模式(模板引擎)与自动模式(对象模式)
手动模式(模板引擎)需自行编写模板, 自动模式(对象模式)无需编写模板
手动模式(模板引擎)
说明
需自行编写模板,控制更灵活
freemarker 数据源
提示
默认数据源,想了解更多语法规则可参考freemarker中文教程
// 定义fop配置文件路径
String configPath = "E:\\pdf\\template\\fop.xconf";
// 定义xsl-fo模板路径
String templatePath = "E:\\pdf\\template\\freemarker";
// 定义pdf输出路径
String outputPath = "E:\\pdf\\test\\fo\\Freemarker.pdf";
// 设置模板路径
TemplateHandler.DataSource.Freemarker.setTemplatePath(templatePath);
// 定义数据map
Map<String, Object> data = new HashMap<>();
// 定义数据list
List<String> list = new ArrayList<>(2);
list.add("hello");
list.add("world");
// 设置值
data.put("list", list);
data.put("str", "hello world");
// 转换pdf
TemplateHandler.Template.build().setConfigPath(configPath).setDataSource(
TemplateHandler.DataSource.Freemarker.build().setTemplateName("template.fo").setTemplateData(data)
).transform(outputPath);
使用配置
<?xml version="1.0"?>
<!-- fop版本 -->
<fop version="1.0">
<!-- 当前路径(项目所在路径) -->
<base>.</base>
<!-- 默认源图像 dpi(每英寸点数像素) -->
<source-resolution>72</source-resolution>
<!-- 默认目标图像 dpi(每英寸点数像素),默认: 72dpi -->
<target-resolution>72</target-resolution>
<!-- 默认页面宽度与高度(A4) -->
<default-page-settings width="21cm" height="29.7cm"/>
<!-- 渲染器 -->
<renderers>
<!-- pdf 渲染器 -->
<renderer mime="application/pdf">
<!-- 过滤器 -->
<filterList>
<!-- 默认使用 flate 依赖压缩 -->
<value>flate</value>
</filterList>
<!-- 字体 -->
<fonts>
<!-- 自动扫描系统全部字体 -->
<auto-detect/>
</fonts>
</renderer>
</renderers>
</fop>
使用模板
<?xml version="1.0" encoding="utf-8"?>
<!--根标签-->
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:fox="http://xmlgraphics.apache.org/fop/extensions"
xmlns:xe="http://www.x-easypdf.cn/ns"
xmlns:svg="http://www.w3.org/2000/svg">
<!--页面模板-->
<fo:layout-master-set>
<!--单页面模板-->
<fo:simple-page-master master-name="A4">
<!--页面区域主体-->
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<!--页面序列-->
<fo:page-sequence master-reference="A4">
<!--页面流-->
<fo:flow flow-name="xsl-region-body">
<#list list as data>
<fo:block>${data}</fo:block>
</#list>
<#if str??>
<fo:block>${str}</fo:block>
<#else>
<fo:block>为空</fo:block>
</#if>
</fo:flow>
</fo:page-sequence>
</fo:root>
thymeleaf 数据源
提示
可选数据源,想了解更多语法规则可参考thymeleaf官方教程
// 定义fop配置文件路径
String configPath = "E:\\pdf\\template\\fop.xconf";
// 定义xsl-fo模板路径
String templatePath = "E:\\pdf\\template\\thymeleaf\\template.fo";
// 定义pdf输出路径
String outputPath = "E:\\pdf\\test\\fo\\Thymeleaf.pdf";
// 定义数据map
Map<String, Object> data = new HashMap<>();
// 设置值
data.put("data", "hello world");
// 转换pdf
TemplateHandler.Template.build().setConfigPath(configPath).setDataSource(
TemplateHandler.DataSource.Thymeleaf.build().setTemplatePath(templatePath).setTemplateData(data)
).transform(outputPath);
使用配置
<?xml version="1.0"?>
<!-- fop版本 -->
<fop version="1.0">
<!-- 当前路径(项目所在路径) -->
<base>.</base>
<!-- 默认源图像 dpi(每英寸点数像素) -->
<source-resolution>72</source-resolution>
<!-- 默认目标图像 dpi(每英寸点数像素),默认: 72dpi -->
<target-resolution>72</target-resolution>
<!-- 默认页面宽度与高度(A4) -->
<default-page-settings width="21cm" height="29.7cm"/>
<!-- 渲染器 -->
<renderers>
<!-- pdf 渲染器 -->
<renderer mime="application/pdf">
<!-- 过滤器 -->
<filterList>
<!-- 默认使用 flate 依赖压缩 -->
<value>flate</value>
</filterList>
<!-- 字体 -->
<fonts>
<!-- 自动扫描系统全部字体 -->
<auto-detect/>
</fonts>
</renderer>
</renderers>
</fop>
使用模板
<?xml version="1.0" encoding="utf-8"?>
<!--根标签-->
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:fox="http://xmlgraphics.apache.org/fop/extensions"
xmlns:xe="http://www.x-easypdf.cn/ns"
xmlns:svg="http://www.w3.org/2000/svg">
<!--页面模板-->
<fo:layout-master-set>
<!--单页面模板-->
<fo:simple-page-master master-name="A4">
<!--页面区域主体-->
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<!--页面序列-->
<fo:page-sequence master-reference="A4">
<!--页面流-->
<fo:flow flow-name="xsl-region-body">
<!--块-->
<fo:block text-align="center" th:text="${data}"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
jte 数据源
提示
可选数据源,想了解更多语法规则可参考jte官方教程
// 定义fop配置文件路径
String configPath = "/wiki/xsx/core/pdf/template/fop.xconf";
// 定义xsl-fo模板路径
String templatePath = "wiki/xsx/core/pdf/template/jte/template.jte";
// 定义pdf输出路径
String outputPath = "E:\\pdf\\test\\fo\\Jte.pdf";
// 定义数据map
Map<String, Object> data = new HashMap<>();
List<String> list = new ArrayList<>(2);
list.add("hello");
list.add("world");
// 设置值
data.put("list", list);
data.put("str", "hello world");
TemplateHandler.Template.build().setConfigPath(configPath).setDataSource(
TemplateHandler.DataSource.Jte.build().setTemplatePath(templatePath).setTemplateData(data)
).transform(outputPath);
使用配置
<?xml version="1.0"?>
<!-- fop版本 -->
<fop version="1.0">
<!-- 当前路径(项目所在路径) -->
<base>.</base>
<!-- 默认源图像 dpi(每英寸点数像素) -->
<source-resolution>72</source-resolution>
<!-- 默认目标图像 dpi(每英寸点数像素),默认: 72dpi -->
<target-resolution>72</target-resolution>
<!-- 默认页面宽度与高度(A4) -->
<default-page-settings width="21cm" height="29.7cm"/>
<!-- 渲染器 -->
<renderers>
<!-- pdf 渲染器 -->
<renderer mime="application/pdf">
<!-- 过滤器 -->
<filterList>
<!-- 默认使用 flate 依赖压缩 -->
<value>flate</value>
</filterList>
<!-- 字体 -->
<fonts>
<!-- 自动扫描系统全部字体 -->
<auto-detect/>
</fonts>
</renderer>
</renderers>
</fop>
使用模板
<%--不能留空行--%>
@import java.util.List
@param List<String> list
@param String str
<?xml version="1.0" encoding="utf-8"?>
<!--根标签-->
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:fox="http://xmlgraphics.apache.org/fop/extensions"
xmlns:xe="http://www.x-easypdf.cn/ns"
xmlns:svg="http://www.w3.org/2000/svg">
<!--页面模板-->
<fo:layout-master-set>
<!--单页面模板-->
<fo:simple-page-master master-name="A4">
<!--页面区域主体-->
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<!--页面序列-->
<fo:page-sequence master-reference="A4">
<!--页面流-->
<fo:flow flow-name="xsl-region-body">
@for(String data : list)
<fo:block>${data}</fo:block>
@endfor
@if(str!=null)
<fo:block>${str}</fo:block>
@else
<fo:block>为空</fo:block>
@endif
</fo:flow>
</fo:page-sequence>
</fo:root>
xml(xslt)数据源
提示
可选数据源,想了解更多语法规则可参考菜鸟教程
// 定义fop配置文件路径
String configPath = "E:\\pdf\\template\\fop.xconf";
// 定义xsl-fo模板路径
String templatePath = "E:\\pdf\\template\\xml\\template.fo";
// 定义xml数据路径
String xmlPath = "E:\\pdf\\template\\xml\\data.xml";
// 定义pdf输出路径
String outputPath = "E:\\pdf\\test\\fo\\xml.pdf";
// 转换pdf
TemplateHandler.Template.build().setConfigPath(configPath).setDataSource(
TemplateHandler.DataSource.XML.build().setTemplatePath(templatePath).setXmlPath(xmlPath)
).transform(outputPath);
使用配置
<?xml version="1.0"?>
<!-- fop版本 -->
<fop version="1.0">
<!-- 当前路径(项目所在路径) -->
<base>.</base>
<!-- 默认源图像 dpi(每英寸点数像素) -->
<source-resolution>72</source-resolution>
<!-- 默认目标图像 dpi(每英寸点数像素),默认: 72dpi -->
<target-resolution>72</target-resolution>
<!-- 默认页面宽度与高度(A4) -->
<default-page-settings width="21cm" height="29.7cm"/>
<!-- 渲染器 -->
<renderers>
<!-- pdf 渲染器 -->
<renderer mime="application/pdf">
<!-- 过滤器 -->
<filterList>
<!-- 默认使用 flate 依赖压缩 -->
<value>flate</value>
</filterList>
<!-- 字体 -->
<fonts>
<!-- 自动扫描系统全部字体 -->
<auto-detect/>
</fonts>
</renderer>
</renderers>
</fop>
使用模板
<?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"
xmlns:fox="http://xmlgraphics.apache.org/fop/extensions"
xmlns:xe="http://www.x-easypdf.cn/ns"
xmlns:svg="http://www.w3.org/2000/svg">
<!--模板-->
<xsl:template match="root">
<!--根标签-->
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<!--页面模板-->
<fo:layout-master-set>
<!--单页面模板-->
<fo:simple-page-master master-name="A4">
<!--页面区域主体-->
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<!--页面序列-->
<fo:page-sequence master-reference="A4">
<!--页面流-->
<fo:flow flow-name="xsl-region-body">
<!--块-->
<fo:block text-align="center">
<!--文本内容-->
<xsl:apply-templates select="data"/>
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>
使用数据
<?xml version="1.0" encoding="utf-8"?>
<root>
<data>hello world</data>
</root>
自动模式(对象模式)
说明
无需自行编写模板,以对象构建的方式生成 pdf 文档
document 数据源
// 定义pdf输出路径
String outputPath = "E:\\pdf\\test\\fo\\document.pdf";
// 转换pdf
TemplateHandler.Document.build().addPage(
TemplateHandler.Page.build().addBodyComponent(
TemplateHandler.Text.build().setText("hello world")
)
).transform(outputPath);
使用配置(默认配置)
<?xml version="1.0"?>
<!-- fop版本 -->
<fop version="1.0">
<!-- 当前路径(项目所在路径) -->
<base>.</base>
<!-- 默认源图像 dpi(每英寸点数像素) -->
<source-resolution>72</source-resolution>
<!-- 默认目标图像 dpi(每英寸点数像素),默认: 72dpi -->
<target-resolution>72</target-resolution>
<!-- 默认页面宽度与高度(A4) -->
<default-page-settings width="21cm" height="29.7cm"/>
<!-- 渲染器 -->
<renderers>
<!-- pdf 渲染器 -->
<renderer mime="application/pdf">
<!-- 过滤器 -->
<filterList>
<!-- 默认使用 flate 依赖压缩 -->
<value>flate</value>
</filterList>
<!-- 字体 -->
<fonts>
<!-- 自动扫描系统全部字体 -->
<auto-detect/>
</fonts>
</renderer>
</renderers>
</fop>
使用模板(默认模板)
<?xml version="1.0" encoding="utf-8"?>
<!--根标签-->
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:fox="http://xmlgraphics.apache.org/fop/extensions"
xmlns:xe="http://www.x-easypdf.cn/ns"
xmlns:svg="http://www.w3.org/2000/svg">
<!--页面模板-->
<fo:layout-master-set></fo:layout-master-set>
</fo:root>
提示
该配置可在 java 代码中进行替换
自定义数据源
说明
如果内置数据源不能满足需求,可自定义数据源
方式一:实现接口
public class MyDataSource implements TemplateDataSource {
/**
* 获取数据源读取器
*
* @return 返回数据源读取器
*/
@Override
public Reader getSourceReader() {
// TODO 实现模板读取器
return null;
}
/**
* 转换
*
* @param fopFactory fop工厂
* @param foAgent fo代理
* @param outputStream 输出流
*/
@Override
public void transform(FopFactory fopFactory, FOUserAgent foAgent, OutputStream outputStream) {
// TODO 实现转换逻辑
}
}
实现参考
public class TemplateDataSourceImpl implements TemplateDataSource {
/**
* 模板路径
*/
protected String templatePath;
/**
* 模板数据
*/
protected Map<String, Object> templateData;
/**
* 获取数据源读取器
*
* @return 返回数据源读取器
*/
@SneakyThrows
@Override
public Reader getSourceReader() {
return new InputStreamReader(this.loadTemplate(), StandardCharsets.UTF_8);
}
/**
* 转换
*
* @param fopFactory fop工厂
* @param foAgent fo代理
* @param outputStream 输出流
*/
@SneakyThrows
@Override
public void transform(FopFactory fopFactory, FOUserAgent foAgent, OutputStream outputStream) {
this.saxTransform(fopFactory, foAgent, outputStream);
}
/**
* 加载模板
*
* @return 返回模板输入流
*/
@SneakyThrows
private InputStream loadTemplate() {
try {
// 从资源路径加载模板
InputStream inputStream = this.getClass().getResourceAsStream(this.templatePath);
// 如果不为空,则返回,否则从绝对路径加载模板
return inputStream != null ? inputStream : Files.newInputStream(Paths.get(this.templatePath));
} catch (Exception e) {
// 提示错误信息
throw new IllegalArgumentException("the template can not be loaded,the path['" + this.templatePath + "'] is error");
}
}
}
方式二:继承抽象类
public class MyDataSource extends TemplateAbstractDataSource {
/**
* 处理模板
*
* @return 返回模板输入流
*/
@Override
protected InputStream processTemplate() {
// TODO 实现模板输入流
return null;
}
}
实现参考(freemarker)
public class FreemarkerDataSource extends AbstractDataSource {
/**
* 模板配置
*/
private static final Configuration CONFIGURATION = initConfiguration();
/**
* 设置模板名称
*
* @param templateName 模板名称
* @return 返回freemarker数据源
*/
public FreemarkerDataSource setTemplateName(String templateName) {
this.templatePath = templateName;
TemplateLoader templateLoader = CONFIGURATION.getTemplateLoader();
if (templateLoader instanceof DefaultURLTemplateLoader) {
((DefaultURLTemplateLoader) templateLoader).setTemplateName(templateName);
}
return this;
}
/**
* 设置模板数据
*
* @param templateData 模板数据
* @return 返回freemarker数据源
*/
public FreemarkerDataSource setTemplateData(Map<String, Object> templateData) {
this.templateData = templateData;
return this;
}
/**
* 处理模板
*
* @return 返回模板输入流
*/
@SneakyThrows
protected InputStream processTemplate() {
try (
// 创建输出流
ByteArrayOutputStream output = new ByteArrayOutputStream();
// 创建写入器
Writer writer = new BufferedWriter(new OutputStreamWriter(output))
) {
// 处理模板
FreemarkerDataSource.CONFIGURATION.getTemplate(this.templatePath).process(this.templateData, writer);
// 返回输入流
return new BufferedInputStream(new ByteArrayInputStream(output.toByteArray()));
}
}
/**
* 初始化配置
*
* @return 返回配置
*/
@SneakyThrows
private static Configuration initConfiguration() {
// 创建配置
Configuration config = new Configuration(Configuration.VERSION_2_3_31);
// 设置默认编码
config.setDefaultEncoding(StandardCharsets.UTF_8.name());
// 设置模板异常处理器
config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
// 设置模板异常日志
config.setLogTemplateExceptions(false);
// 设置未检查异常
config.setWrapUncheckedExceptions(true);
// 设置空循环变量回退
config.setFallbackOnNullLoopVariable(false);
// 获取模板路径
String templatePath = System.getProperty(Constants.FREEMARKER_TEMPLATE_PATH_KEY);
// 如果非资源路径,则为文件目录
if (Thread.currentThread().getContextClassLoader().getResource(templatePath) == null) {
try {
// 设置文件目录解析器
config.setDirectoryForTemplateLoading(Paths.get(templatePath).toFile());
} catch (Exception e) {
// 设置远程资源解析器
config.setTemplateLoader(new DefaultURLTemplateLoader(templatePath));
}
} else {
// 设置资源解析器
config.setTemplateLoader(new ClassTemplateLoader(FreemarkerDataSource.class, File.separator + templatePath));
}
// 返回配置
return config;
}
}
使用方式
说明
自定义数据源与内置数据源使用方式相同,传入模板对象即可
// 定义fop配置文件路径
String configPath = "E:\\pdf\\template\\fop.xconf";
// 定义pdf输出路径
String outputPath = "E:\\pdf\\test\\fo\\my.pdf";
// 转换pdf
TemplateHandler.Template.build().setConfigPath(configPath).setDataSource(
// 传入自定义数据源
new MyDataSource()
).transform(outputPath);