【问题标题】:Java Render XML Document as PDFJava 将 XML 文档呈现为 PDF
【发布时间】:2013-01-16 13:42:30
【问题描述】:

我有一个当前存储为内存中字符串的 XML 文档,并希望将其呈现为 PDF。换言之,PDF 内容将是一个 XML 文档。该方法呈现的 XML 是通用的——可能会发送多种类型的 XML 文档。

我很难弄清楚如何使用各种基于 Java 的框架来完成。

Apache FOP

这个框架似乎需要将文档中的 XML 元素特定转换为 FOP 实体。由于有问题的方法必须接受通用 XML,我认为这个框架不符合我的要求。

iText

我尝试使用 iText/Flying Saucer (org.xhtmlrenderer) 的组合呈现文档,虽然它确实呈现 PDF,但内容仅包含空格分隔的数据值,没有 xml 元素或属性。使用下面的代码和测试数据:

文件

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <elem1>value1</elem1>
  <elem2>value2</elem2>
</root>

代码

File inputFile = new File(PdfGenerator.class.getResource("test.xml").getFile());
OutputStream os = new FileOutputStream("c:\\temp\\Sample.pdf");
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(inputFile);
renderer.layout();
renderer.createPDF(os);
os.close();  

生成的 PDF 包含内容值 value1 value2,但没有标签。

我的问题是 有人可以提供代码 sn-p 用于使用上述框架之一渲染包含 XML 内容的 PDF,还是有其他框架更适合我的需求?

编辑: 我意识到here 提出了同样的问题,但似乎提出的解决方案需要深入了解 css 文件中传入 XML 文档的结构。

【问题讨论】:

  • 您是否考虑过带有 XML 输入源的 JasperReports?
  • 如果 XML 是通用的添加,你让它听起来,你希望它如何呈现?作为表示 XML 内容的结构化树?

标签: java xml pdf itext apache-fop


【解决方案1】:

只是为了给出一个使用 fop 的例子 - 在这里你有它。为了让每个人都能遵循这一点,我使用了 fop 命令行工具。

同样可以在 Java 代码中轻松执行,然后您无需随时将 xml 作为文件。

生成 PDF 的 XSLT

<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="/">
<fo:root>
  <fo:layout-master-set>
    <fo:simple-page-master master-name="content"
        page-width="210mm" page-height="297mm" margin="20mm 20mm 20mm 20mm">
      <fo:region-body/>
    </fo:simple-page-master>
  </fo:layout-master-set>
  <fo:page-sequence master-reference="content">
    <fo:flow flow-name="xsl-region-body">
      <fo:block>
        <xsl:apply-templates />
    </fo:block>
    </fo:flow>
  </fo:page-sequence>
</fo:root>
</xsl:template>

<xsl:template match="@*">
  <xsl:text> </xsl:text>
  <xsl:value-of select="name()" />
  <xsl:text>="</xsl:text>
    <xsl:value-of select="." />
  <xsl:text>"</xsl:text>
</xsl:template>

<xsl:template match="*">
  <xsl:param name="indent">0</xsl:param>
  <fo:block margin-left="{$indent}">
    <xsl:text>&lt;</xsl:text>
    <xsl:value-of select="name()" />
    <xsl:apply-templates select="@*" />
    <xsl:text>&gt;</xsl:text>
    <xsl:apply-templates>
      <xsl:with-param name="indent" select="$indent+10" />
    </xsl:apply-templates>
    <xsl:text>&lt;/</xsl:text>
    <xsl:value-of select="name()" />
    <xsl:text>&gt;</xsl:text>
  </fo:block>
</xsl:template>

</xsl:stylesheet>

我们称这个文件为 xml2pdf.xsl

代码简述

  • 模板 match="/" 主要构建 pdf,除了调用其他模板匹配方法或更准确的模板 match="*" 的行。

  • 模板 match="" 写入元素 start 和 end 并调用,而后者又为元素中的每个属性(如果有)调用模板 match="@"。最后它调用了

  • 使用 with-param 语句中的 select="$indent+10" 属性,模板每达到一个级别,缩进参数就会增加 10。

使用代码

# fop -xsl xml2pdf.xsl -xml sample.xml -pdf result.pdf

【讨论】:

    【解决方案2】:

    这是使用 itext 的解决方案。您的 html 内容在请求中。而且itext不是免费的。看看它的许可要求,因为它近年来发生了变化,虽然它不是很贵。

    public class MyPDFGeneratorService {
    
        public byte[] generatePdf(final XhtmlPDFGenerationRequest request) {
            try {
    
                ITextRenderer renderer = new ITextRenderer();
                renderer.setDocument(this.getDocument(request.getContent()), null);
                renderer.layout();
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                renderer.createPDF(baos);
                return this.toByteArray(baos);
    
            }
            catch (Exception e) {
                throw new PDFGenerationException(
                        "Unable to generate  PDF.", e);
            }
        }
    
        private Document getDocument(final String content) {
            InputSource is = new InputSource(new BufferedReader(new StringReader(
                    content)));
            return XMLResource.load(is).getDocument();
        }
    
    
        private byte[] toByteArray(final ByteArrayOutputStream baos)
            throws IOException {
        byte[] bytes = baos.toByteArray();
        baos.close();
        return bytes;
    
     }
    
    }
    

    【讨论】:

      【解决方案3】:

      尝试谷歌搜索,有许多代码sn-ps。例如:http://www.vogella.com/articles/JavaPDF/article.html

      我推荐 iText 而不是 FOP,它更快,内存占用更少,并且您可以更好地控制结果。

      【讨论】:

      • 问题的症结在于如何使用这样的框架来渲染any xml 文档作为包含原始XML 的PDF。我了解如何根据已知的数据格式手动构建 PDF 文档。我正在寻找与我提供的代码 sn-p 一样简单的东西,它将呈现原始 XML(如果存在这样的东西)。
      • 抱歉有点密集...您能解释一下预格式化块的意思吗?您是指应用于传入 XML 字符串的某种格式,还是向 PDF 文档添加一些预先格式化的数据类型?
      • 使用等宽字体,例如“Courier”。
      • 由于第 5 版 itext 在 AGPL 下,所以我们中的许多人不能再使用它了!
      猜你喜欢
      • 2012-04-04
      • 1970-01-01
      • 2010-10-27
      • 1970-01-01
      • 1970-01-01
      • 2017-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多