如何用 Java 从 XML 创建 PDF?

2024-04-21

目前,我正在 Java 中创建一个 XML 文件,并通过使用 XSL/XSLT 对其进行转换来将其显示在 JSP 页面中。现在我需要获取该 XML 文件并在 PDF 中显示相同的信息。有没有办法通过使用某种 XSL 文件来做到这一点?

我见过iText http://www.lowagie.com/iText/Java-PDF 库,但我找不到任何将它与 XML 和样式表一起使用的方法。

任何帮助将不胜感激。提前致谢!


A - 解释

你应该使用阿帕奇FOP框架生成pdf输出。只需您提供数据xml格式化并渲染页面xsl-fo文件并指定参数,例如margin, 页面布局在这个xsl-fo file.

我将提供一个简单的演示,我使用maven构建工具来收集所需的 jar 文件。请注意,在页面末尾,有一个嵌入 pdf 中的 svg 图形。我还想演示您可以在 pdf 中嵌入 svg 图形。

B - 示例 XML 输入数据

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="application/xml"?>
<users-data>
    <header-section>
        <data-type id="019">User Bill Data</data-type>
        <process-date>Thursday December 9 2016 00:04:29</process-date>
    </header-section>
    <user-bill-data>
        <full-name>John Doe</full-name>
        <postal-code>34239</postal-code>
        <national-id>123AD329248</national-id>
        <price>17.84</price>
    </user-bill-data>
    <user-bill-data>
        <full-name>Michael Doe</full-name>
        <postal-code>54823</postal-code>
        <national-id>942KFDSCW322</national-id>
        <price>34.50</price>
    </user-bill-data>
    <user-bill-data>
        <full-name>Jane Brown</full-name>
        <postal-code>66742</postal-code>
        <national-id>ABDD324KKD8</national-id>
        <price>69.36</price>
    </user-bill-data>
</users-data>

C - XSL-FO 模板

<?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="users-data">
        <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:simple-page-master>
            </fo:layout-master-set>
            <fo:page-sequence master-reference="A4-portrail">
                <fo:static-content flow-name="xsl-region-before">
                    <fo:table table-layout="fixed" width="100%" font-size="10pt" border-color="black" border-width="0.4mm" border-style="solid">
                        <fo:table-column column-width="proportional-column-width(20)"/>
                        <fo:table-column column-width="proportional-column-width(45)"/>
                        <fo:table-column column-width="proportional-column-width(20)"/>
                        <fo:table-body>
                            <fo:table-row>
                                <fo:table-cell text-align="left" display-align="center" padding-left="2mm">
                                    <fo:block>
                                        Bill Id:<xsl:value-of select="header-section/data-type/@id"/>
                                        , Date: <xsl:value-of select="header-section/process-date"/>
                                    </fo:block>
                                </fo:table-cell>
                                <fo:table-cell text-align="center" display-align="center">
                                    <fo:block font-size="150%">
                                        <fo:basic-link external-destination="http://www.example.com">XXX COMPANY</fo:basic-link>
                                    </fo:block>
                                    <fo:block space-before="3mm"/>
                                </fo:table-cell>
                                <fo:table-cell text-align="right" display-align="center" padding-right="2mm">
                                    <fo:block>
                                        <xsl:value-of select="data-type"/>
                                    </fo:block>
                                    <fo:block display-align="before" space-before="6mm">Page <fo:page-number/> of <fo:page-number-citation ref-id="end-of-document"/>
                                    </fo:block>
                                </fo:table-cell>
                            </fo:table-row>
                        </fo:table-body>
                    </fo:table>
                </fo:static-content>
                <fo:flow flow-name="xsl-region-body" border-collapse="collapse" reference-orientation="0">
                    <fo:block>MONTHLY BILL REPORT</fo:block>
                    <fo:table table-layout="fixed" width="100%" font-size="10pt" border-color="black" border-width="0.35mm" border-style="solid" text-align="center" display-align="center" space-after="5mm">
                        <fo:table-column column-width="proportional-column-width(20)"/>
                        <fo:table-column column-width="proportional-column-width(30)"/>
                        <fo:table-column column-width="proportional-column-width(25)"/>
                        <fo:table-column column-width="proportional-column-width(50)"/>
                        <fo:table-body font-size="95%">
                            <fo:table-row height="8mm">
                                <fo:table-cell>
                                    <fo:block>Full Name</fo:block>
                                </fo:table-cell>
                                <fo:table-cell>
                                    <fo:block>Postal Code</fo:block>
                                </fo:table-cell>
                                <fo:table-cell>
                                    <fo:block>National ID</fo:block>
                                </fo:table-cell>
                                <fo:table-cell>
                                    <fo:block>Payment</fo:block>
                                </fo:table-cell>
                            </fo:table-row>
                            <xsl:for-each select="user-bill-data">
                                <fo:table-row>
                                    <fo:table-cell>
                                        <fo:block>
                                            <xsl:value-of select="full-name"/>
                                        </fo:block>
                                    </fo:table-cell>
                                    <fo:table-cell>
                                        <fo:block>
                                            <xsl:value-of select="postal-code"/>
                                        </fo:block>
                                    </fo:table-cell>
                                    <fo:table-cell>
                                        <fo:block>
                                            <xsl:value-of select="national-id"/>
                                        </fo:block>
                                    </fo:table-cell>
                                    <fo:table-cell>
                                        <fo:block>
                                            <xsl:value-of select="price"/>
                                        </fo:block>
                                    </fo:table-cell>
                                </fo:table-row>
                            </xsl:for-each>
                        </fo:table-body>
                    </fo:table>
                    <fo:block id="end-of-document">
                        <fo:instream-foreign-object>
                            <svg width="200mm" height="150mm" version="1.1" xmlns="http://www.w3.org/2000/svg">
                                <path d="M153 334
C153 334 151 334 151 334
C151 339 153 344 156 344
C164 344 171 339 171 334
C171 322 164 314 156 314
C142 314 131 322 131 334
C131 350 142 364 156 364
C175 364 191 350 191 334
C191 311 175 294 156 294
C131 294 111 311 111 334
C111 361 131 384 156 384
C186 384 211 361 211 334
C211 300 186 274 156 274" style="fill:yellow;stroke:red;stroke-width:2"/>
                            </svg>
                        </fo:instream-foreign-object>
                    </fo:block>
                </fo:flow>
            </fo:page-sequence>
        </fo:root>
    </xsl:template>
</xsl:stylesheet>

D - 项目目录结构

E - Pom 文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.levent.fopdemo</groupId>
    <artifactId>apache-fop-demo</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>apache-fop-demo</name>
    <url>http://maven.apache.org</url>

    <properties>
        <fop.version>2.1</fop.version>
    </properties>

    <dependencies>      
        <!-- https://mvnrepository.com/artifact/org.apache.xmlgraphics/fop -->
        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>fop</artifactId>
            <version>${fop.version}</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>Apache Fop Demo</finalName>

        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

F - 演示代码:PdfGenerationDemo.java

package com.levent.fopdemo;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;

import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.fop.apps.FOPException;
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 PdfGenerationDemo 
{
    public static final String RESOURCES_DIR;
    public static final String OUTPUT_DIR;

    static {
        RESOURCES_DIR = "src//main//resources//";
        OUTPUT_DIR = "src//main//resources//output//";
    }

    public static void main( String[] args )
    {
        try {
            convertToPDF();
        } catch (FOPException | IOException | TransformerException e) {
            e.printStackTrace();
        }
    }

    public static void convertToPDF() throws IOException, FOPException, TransformerException {
        // the XSL FO file
        File xsltFile = new File(RESOURCES_DIR + "//template.xsl");
        // the XML file which provides the input
        StreamSource xmlSource = new StreamSource(new File(RESOURCES_DIR + "//data.xml"));
        // create an instance of fop factory
        FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());
        // a user agent is needed for transformation
        FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
        // Setup output
        OutputStream out;
        out = new java.io.FileOutputStream(OUTPUT_DIR + "//output.pdf");

        try {
            // Construct fop with desired output format
            Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);

            // Setup XSLT
            TransformerFactory factory = TransformerFactory.newInstance();
            Transformer transformer = factory.newTransformer(new StreamSource(xsltFile));

            // Resulting SAX events (the generated FO) must be piped through to
            // FOP
            Result res = new SAXResult(fop.getDefaultHandler());

            // Start XSLT transformation and FOP processing
            // That's where the XML is first transformed to XSL-FO and then
            // PDF is created
            transformer.transform(xmlSource, res);
        } finally {
            out.close();
        }
    }
}

G - 示例输出:output.pdf

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何用 Java 从 XML 创建 PDF? 的相关文章

  • Android 上 WebRTC 的自定义视频源

    Overview 我想使用自定义视频源通过 WebRTC Android 实现来直播视频 如果我理解正确的话 现有的实现仅支持 Android 手机上的前置和后置摄像头 以下类与此场景相关 Camera1Enumerator java ht
  • [重复]

    这个问题在这里已经有答案了 有什么区别List
  • 由于 maven-surefire-plugin,Maven 构建失败

    我这里有类似的问题eclipse 中缺少 maven surefire plugin https stackoverflow com questions 23588957 maven surefire plugin missing in e
  • Spring Security 的 AJAX 请求给出 403 Forbidden

    我有一个基于spring boot spring security thymeleaf的网站 在某些情况下我也使用ajax 问题 我在 Spring Security 中使用表单登录安全性 在浏览器中 登录后我可以使用rest API GE
  • HTTPURLConnection 不遵循从 HTTP 到 HTTPS 的重定向

    我不明白为什么JavaHttpURLConnection不遵循从 HTTP 到 HTTPS URL 的 HTTP 重定向 我使用以下代码来获取页面https httpstat us https httpstat us import java
  • 如何在Java中实现复合模式?

    我想实现一个复合模式Java以便绘制软件开发组织图 因此 我们假设有多个项目经理和多个开发人员 每个开发人员都被分配给一位项目经理 并且每个开发人员都能够使用各种编程语言进行编码 项目经理领导开发人员并准确了解他们的工作量 我对这个设计模式
  • 版本差异? Java 中的正则表达式转义

    看来正则表达式转义在不同版本的 Java 中的工作方式不同 在 Java openjdk 16 0 1 中编译工作正常 在 Java openjdk 11 0 11 中抛出此编译错误 test java 15 error illegal e
  • Spring Boot 1.4:Liquibase完成后的执行方法

    我有一个基于 Spring Boot 1 4 0 的项目 该项目使用 Liquibase liquibase 完成后是否可以执行方法 像 Bean 后处理器之类的东西 我想要做的是当应用程序在开发模式下启动时向我的数据库添加一些数据 在开发
  • 无法为对象堆保留足够的空间

    每次尝试运行该程序时 我都会重复出现以下异常 VM初始化期间发生错误 无法为对象堆保留足够的空间 无法创建Java虚拟机 我尝试增加虚拟内存 页面大小 和 RAM 大小 但无济于事 我怎样才能消除这个错误 运行 JVM XX MaxHeap
  • XML 文档结构必须在同一实体内开始和结束

    我是 eclipse 的新手 我刚刚开始编写一些代码 实际上只是从网站复制并粘贴 谁能帮我解决这个问题 错误出现在最后一行
  • Jersey/JAX-RS:如何自动使用@Valid递归级联bean验证?

    我正在 Jersey 的 REST 资源端点中验证我的 POJO public class Resource POST public Response post NotNull Valid final POJO pojo public cl
  • AWS Lambda 和 S3 - 上传的 pdf 文件为空/损坏

    我有一个 Spring 应用程序 在 AWS Lambda 上运行 它获取文件并将其上传到 AWS S3 Spring控制器发送一个MultipartFile到我的方法 使用 Amazon API Gateway 将其上传到 AWS S3
  • CTRL-C 在 Python 中的行为有所不同

    I ve recently started learning Python long time Java programmer here and currently in the process of writing some simple
  • 无法实例化类对象的类型 (Java)

    这是我收到错误的代码 在 new 之后的第二个 Killer 处 String classes new String 5 kills 0 Brian Moser kills 1 James Doakes kills 2 Lila Tourn
  • Java编译错误:包不存在

    在我的工作区 wsPrivate 中 我有 3 个 gradle 项目 刽子手 像素视图 Reports PixelView 和 Reports 项目编译良好 然而 Hangman 使用这两个项目 并且有些在编译时找不到包 请参阅以下错误
  • 计算事件之间的天数 - Android

    我一直在研究 Android API 并一直在寻找一种方法来计算当前日期和未来日期之间的天数 我对 android 还很陌生 而且我已经有几年没有做过 java 了 计算这个最简单的方法是什么 Thanks 最简单的方法是使用乔达时间 ht
  • 使用 XSLT 合并 2 个具有匹配“id”属性的 XML 文件

    当存在匹配的 id 属性时 我想使用 XSLT 合并 2 个 XML 文件 myFile1 xml 这是第一个输入文件
  • 如何使用 log4j2.xml 配置 hibernate 日志记录?

    我最近切换到 Apache log4j2 但仍然找不到使用 log4j2 xml 配置 hibernate 日志记录的方法 因为我找不到解决此问题的方法 所以我仍然显式使用 log4j properties 文件进行休眠 这不是最好的解决方
  • 与 System.in.read() 一起使用的文件结尾/流键盘组合是什么

    如果这个小问题已经得到解答 我深表歉意 我无法在SO找到它 使用以下 Java 简单代码从 IDE 控制台读取行 Windows 7 和 Eclipse Kepler int v try while v System in read 1 S
  • Java 和 SQL Server 中的精度噩梦

    我一直在与 Java 和 SQL Server 中的精确噩梦作斗争 直到我不再知道了 就我个人而言 我理解这个问题及其根本原因 但向地球另一端的客户解释这一点是不可行的 至少对我来说 情况是这样的 我在 SQL Server 中有两列 Qt

随机推荐

  • 如何在 Ionic 3 中高效存储和使用身份验证

    我目前正在开发一个离子 3 4 适用于 iOS Android 的应用程序 我不熟悉身份验证过程或应用程序 在提供程序中使用 HTTP 请求后 我得到了我的对象 用户 但我完全不知道如何存储或处理它 有哪些好的做法 我是否应该将对象存储在提
  • 适用于 iPhone 视网膜显示屏的图像

    我有一个可以工作的应用程序 我已经在我的 iPod touch 上测试过了 一切都很好 我的标签栏图标和启动屏幕图像位于资源文件夹中的单独文件夹中 Resources gt images 现在 我知道对于 iPhone4 我需要使用 2x
  • 如何将列高设置为等于布尔玛(flexbox)中最长的列?

    我正在使用 Bulma 0 4 0 尽管答案可能与 Bulma 本身无关 如何将列高设置为与其他列相同 见下面的截图 编辑 codepen 包含更多显示实际行为的文本 https codepen io anon pen vmKVbx htt
  • Plon 全文索引 Excel 文件

    如何自定义 Plone 搜索引擎以激活 excel 文件的全文索引 我已经安装了 pdftotext 和 wv 用于 pdf word 文件全文索引 如果你添加产品 OpenXml https pypi python org pypi Pr
  • 在类中为其自己的字段使用 getter/setter 有什么好处吗? [复制]

    这个问题在这里已经有答案了 通常 在我自己的项目中 我使用 getter 和 setter 进行任何字段访问 并且我在工作中也遵循同样的做法 不久前 我们项目的技术负责人问我为什么要这样做 以及为什么这比仅仅使用字段本身更好 如果需要由子类
  • 由于频繁断网,repo 同步卡在 99%

    我尝试重新同步cyanogenmod源 一直到99 阶段 但是这个阶段好像有一个大文件 而且由于我的网络连接经常断开 所以无法下载它 每次发生断开连接时 fatal early EOF被打印出来 则repo sync停止 似乎在下次运行时
  • 幻影数据用例

    我试图理解 rust 中的 phantomData 我有一个 Foo 结构包裹着一个原始指针 我告诉编译器 Foo 不能比 a 更长寿 所以我试图防止属性 v 的值在 Foo 之前被删除 但是我发现当 String s 可以在 f 之前删除
  • 断开连接后保持 SSH 会话运行 - 过夜 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 这是对此的后续问题question https stackoverflow com questions 33041892 keep ssh
  • 使用 Word 互操作查找具有特定格式的一系列文本

    我有一个 MS Word 插件 需要仅根据其格式从一系列文本中提取文本 特别是在我的情况下 如果文本带有下划线或删除线 则带有下划线或删除线的字符 单词的范围通过需要找到 以便我可以跟踪它们 我的第一个想法是使用Range Find as
  • .Net File.GetLastAccessTime 更新文件的上次访问时间

    我们使用下面的行来获取文件的上次访问日期和时间 DateTime dtLastAccesstime File GetLastAccessTime sFilePath 但我们面临着奇怪的问题 上面的调用本身修改了最后访问时间 因此 我们有效地
  • Visual C++ 获取资源的路径

    我正在尝试将图像添加到 Visual C 项目并获取它的路径 基本上我想要的是向项目添加一些图像 以便它可以通过在项目内部而不是本地驱动器上获取必要的图像来在任何计算机上运行 我通过右键单击资源文件 在解决方案资源管理器菜单中 并添加 gt
  • 如何在特定时区(最好是我的应用程序的默认时区,而不是 UTC)创建新的 DateTime 对象?

    我已将时区设置为 config application rb 并且我希望默认情况下在我的应用程序中生成的所有时间都位于该时区 但是当我创建新的DateTime对象 使用 new 它创建它GMT 如何让它位于我的应用程序的时区 配置 应用程序
  • 如何将 NSString 从 CamelCase 转换为 TitleCase,将“playerName”转换为“Player Name”?

    我正在寻找将字符串从驼背格式转换为标题大小写格式的最简单方法 如何将 玩家姓名 更改为 玩家姓名 NSString str playerName NSMutableString str2 NSMutableString string for
  • 限制vb.net中列表框中的选择

    我正在 vb net 中创建一个包含列表框的 Web 控件 我知道我可以选择 单个 或 多个 选择模式 但我有兴趣将 多个 选择限制为预定大小 例如 阻止用户选择 3 个以上的项目 我尝试向列表框中添加一个验证器 这可能是一种前进的方法 但
  • 我无法刷新标准输入。如何在 C 中刷新标准输入?

    How to 刷新标准输入 为什么它在下面的代码片段中不起作用 include
  • Android:带有图标的选项菜单“更多列表”

    我喜欢 Android 在选项菜单中自动显示许多菜单项 当屏幕上的菜单项过多时 它会显示 更多 按钮 我想保持这种方式 但是当您按 更多 时弹出的菜单项中没有菜单图标 有什么办法可以让我否决这个吗 如果没有 当用户单击 更多 时如何显示我自
  • 如何在 C++ 中创建多个向量的组合而无需硬编码循环?

    我有几个数据看起来像这样 Vector1 elements T C A Vector2 elements C G A Vector3 elements C G T up to VectorK elements Note also that
  • 将rodata 与创建它的函数一起保存

    我试图使 rodata 部分位置与其关联的函数内存位置保持一致 我正在使用 GNU 编译器 链接器 裸机 plain jane c 和 STM32L4A6 微控制器 我有一个使用 STM32L4A6 控制器的定制板 其中 1Meg 闪存分为
  • 如何在 UITableView 中显示 NSSet?

    您将如何继续显示NSSet in a UITableView 如您所知 表视图将询问给定行的元素 但由于NSSet元素没有排序 这不能很好地混合 我当前的解决方案是迭代NSSet直到我到达给定索引处的元素 但这确实感觉不对 你可能会问为什么
  • 如何用 Java 从 XML 创建 PDF?

    目前 我正在 Java 中创建一个 XML 文件 并通过使用 XSL XSLT 对其进行转换来将其显示在 JSP 页面中 现在我需要获取该 XML 文件并在 PDF 中显示相同的信息 有没有办法通过使用某种 XSL 文件来做到这一点 我见过