Как создать PDF-файл из XML на Java?

На данный момент я создаю XML-файл на Java и отображаю его на странице JSP, преобразовывая его с помощью XSL / XSLT. Теперь мне нужно взять этот XML-файл и отобразить ту же информацию в PDF-файле. Есть ли способ сделать это, используя какой-нибудь файл XSL?

Я видел библиотеку Java-PDF iText, но не могу найти способ использовать ее с XML и таблицей стилей.

Любая помощь будет принята с благодарностью. Заранее спасибо!

Теперь есть iText® XMLWorker, реализация по умолчанию - HTML / CSS в pdf.

Redlab 28.05.2011 12:23

Лучше рассмотреть возможность использования фреймворка Apache-FOP. Я добавил ответ ниже, используя apache-fop.

Levent Divilioglu 09.12.2016 00:52
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
31
2
82 804
11
Перейти к ответу Данный вопрос помечен как решенный

Ответы 11

Возможно, вы захотите взглянуть на существующие библиотеки XSL-FO, которые могут создавать PDF-файлы в качестве преобразования. Попробую найти ссылку.

ты нашел что-нибудь?

Sanjay Sahani 20.02.2020 08:53
Ответ принят как подходящий

Вы можете использовать объекты форматирования XSL. Вот несколько хороших статей о том, как это сделать:

BIRT имеет графический интерфейс для Eclipse, который позволяет вам определять PDF из XML, DB, CSV и т. д.

Вы также можете проверить проект Apache FOP здесь

Используйте JasperReports. Вы можете извлечь данные из базы данных или XML. Вы можете экспортировать во многие форматы: pdf, excel, html и т. д.

Попробуйте проект xhtmlrenderer. См. Статью «Создание PDF-файлов для развлечения и прибыли с помощью Flying Saucer и iText».

Это хорошо для развлечения, но если вы планируете использовать itext, обязательно ознакомьтесь с лицензией.

vsingh 05.11.2013 19:07

Если вы опоздали, вы можете создать статический PDF-файл с редактируемыми полями в дизайнере Adobe, а затем создать соответствующий XML-документ XDP.

Есть два способа сделать это.

  • Во-первых, вы можете создать обычный PDF-файл, который при обратном чтении не даст вам иерархии исходного XML-файла. Это очень подробно объясняется в 'Section 9.4.2 Parsing XML''iText in Action : Edition 2'.

  • Во-вторых, вы можете создать PDF-файл с тегами, который содержит как иерархию XML, так и данные. Это позволяет вам прочитать PDF-файл и создать из него XML-файл (который точно соответствует исходному XML-файлу). Эта концепция также подробно рассматривается в '15.2.3 Adding structure''iText in Action : Edition 2'.

В зависимости от ваших требований вы можете использовать любой из упомянутых выше подходов.

Вы можете применить XSL-Fo к вашему XML и преобразовать его с помощью преобразователя Java:

File xmlfile = new File(baseDir, xml);
File xsltfile = new File(baseDir, xsl);
File pdffile = new File(outDir, "ResultXMLPDF.pdf");

FopFactory fopFactory = FopFactory.newInstance();
FOUserAgent foUserAgent = fopFactory.newFOUserAgent();

OutputStream out = new java.io.FileOutputStream(pdffile);
out = new java.io.BufferedOutputStream(out);

try
{
    Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);
    // Setup XSLT
    TransformerFactory factory = TransformerFactory.newInstance();
    Transformer transformer = factory.newTransformer(new StreamSource(xsltfile));

    transformer.setParameter("versionParam", "1.0");

    Source src = new StreamSource(xmlfile);

    Result res = new SAXResult(fop.getDefaultHandler());

    transformer.transform(src, res);

} finally {
    out.close();
}

System.out.println("Success!");

XML, CSS, XHTML и т. д. Представляют собой «живую экосистему» ​​открытых стандартов, в то время как XSL-FO является изолированным стандартом.

... Исторически XSL-FO и XSLT создавались как братья-близнецы, но только XSLT остается «живым стандартом», XSL-FO концентрирует много ДНК в проприетарных (Adobe) стандартах ... теперь устарело.

Строго говоря, XSL-FO является частью «заброшенного пути», который не будет развиваться, он игнорирует CSS, «новый способ» выражения макета в «живой экосистеме».

Это не проблема Java

Смотрите этот ответ об использовании CSS-страница с XML или XHTML.

Как XSL-FO не является частью экосистемы XML?

Tony Graham 25.08.2015 12:40

@TonyGraham Спасибо, я согласен и отредактировал ... лучше (извините, мой английский)? Вы можете редактировать, теперь это Wiki!

Peter Krauss 25.08.2015 16:21

A - Объяснение

Вы должны использовать структуру Apache FOP для генерации вывода pdf. Просто вы предоставляете данные в формате xml и визуализируете страницу с файлом xsl-fo и указываете такие параметры, как допуск, макет страницы в этом файле xsl-fo.

Я предоставлю простую демонстрацию, я использую инструмент сборки знаток для сбора необходимых файлов jar. Обратите внимание, что в конце страницы есть графика svg, встроенная в pdf. Я также хочу продемонстрировать, что вы можете встраивать SVG-графику в PDF-файл.

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

Интересно! Но для правильной работы мне нужно добавить compile group: 'xml-apis', name: 'xml-apis', version: '1.4.01' в свою зависимость.

Stefano Scarpanti 18.09.2017 17:47

Спасибо за подробный ответ. Я запустил приведенный выше код с теми же файлами, и он возвращает ошибку: «Не удалось скомпилировать таблицу стилей. Обнаружена 1 ошибка. At net.sf.saxon.PreparedStylesheet.prepare (PreparedStylesheet.j‌ ava: 176)». Любая помощь, пожалуйста!

Afifa Rih 03.07.2018 18:41

Другие вопросы по теме