从动态发票和XSLT创建PDF文件

时间:2016-08-23 07:17:16

标签: java pdf itext apache-fop flying-saucer

我一直在尝试为客户发票生成PDF文件很长一段时间。发票保存为xml文件。客户可以拥有自己的xslt文件,以便拥有自己的发票视图(如果不是默认的,则用作xslt)。

我的问题是将XML /(X)HTML文件转换为pdf文件。我已经阅读了几乎所有的库来做这件事,并试图几乎改变所有库。

1)Apache FOP

http://www.javaworld.com/article/2071749/java-app-dev/convert-html-content-to-pdf-format.html

我使用默认的xslt和jtidy将发票xml转换为xhtml。然后我尝试使用Antenna House提供的XSL-FO将生成的xhtml转换为pdf.I设法生成一个只有标题的pdf文件。也没有成功。下面这样做的代码。

        TransformerFactory factory = TransformerFactory.newInstance();
        Source xslt = new StreamSource(getClass().getResourceAsStream("/xslts/general.xslt"));
//      xslt.setSystemId("/xslts/general.xslt");
        StringWriter writer = new StringWriter();
        StreamResult result = new StreamResult(writer);

        Transformer transformer = factory.newTransformer(xslt);
        DOMSource domSource = new DOMSource(document);
        transformer.transform(domSource, result);
        String strResult = writer.toString();


        Tidy tidy = new Tidy();
//        tidy.setDropEmptyParas(true);
//        tidy.setJoinStyles(true);
        tidy.setInputEncoding("UTF-8");
        tidy.setOutputEncoding("UTF-8");
        tidy.setXHTML(true);
        tidy.setMakeClean(true);
        tidy.setForceOutput(true);

        ByteArrayInputStream boas = new ByteArrayInputStream(strResult.getBytes("UTF-8"));
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        FileOutputStream baoOut = new FileOutputStream(new File("C:\\Users\\xxx\\out.pdf"));

        Document tiedDoc = tidy.parseDOM(boas, bos);

        DOMSource tiedDocDomSource = new DOMSource(tiedDoc);
        StringWriter writer2 = new StringWriter();
        StreamResult result2 = new StreamResult(writer2);
        Transformer xsl2foTrans = factory.newTransformer(new StreamSource(getClass().getResourceAsStream("/xslt/xhtml2fo.xsl")));

        xsl2foTrans.transform(tiedDocDomSource, result2);


//        // ab hier

        final FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());
        File userConfig = new File("C:\\Users\\xxx\\Desktop\\pdfWork\\fop.xconf");
        FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
        // configure foUserAgent as desired

        // Setup output stream.  Note: Using BufferedOutputStream
        // for performance reasons (helpful with FileOutputStreams).
        OutputStream out = baoOut;
        out = new BufferedOutputStream(out);

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

        // Setup JAXP using identity transformer
        transformer = factory.newTransformer(); // identity transformer

        // Setup input stream
        Source src = new StreamSource(new StringReader(writer2.toString()));

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

        // Start XSLT transformation and FOP processing
        transformer.transform(src, res);
        out.close();

2)IText

据我所知,我们应该为IText提供有效的xhtml来生成PDF文件。所以我使用default.xslt将invoice xml转换为html,然后使用带有setXhtml选项的jtidy将xhtml转换为xhtml。我设法从给定的xhtml生成pdf文件。但pdf渲染效果不佳。不知何故,样式标签中的css无法识别。没有成功。在下面执行此操作的代码

    StreamSource xslt = new StreamSource(getClass().getResourceAsStream("/xslt/general.xslt"));
//        StreamSource xslt =  new StreamSource(new FileInputStream(new File("C:\\Users\\XXX\\Desktop\\pdfWork\\firm.xslt")));


        TransformerFactory factory = TransformerFactory.newInstance();
//      Source xslt = new StreamSource(getClass().getResourceAsStream("/xslts/general.xslt"));
//      xslt.setSystemId("/xslts/general.xslt");
        StringWriter writer = new StringWriter();
        StreamResult result = new StreamResult(writer);

        Transformer transformer = factory.newTransformer(xslt);
        DOMSource domSource = new DOMSource(document);
        transformer.transform(domSource, result);
        String strResult = writer.toString();


        Tidy tidy = new Tidy();
//        tidy.setDropEmptyParas(true);
        tidy.setJoinStyles(true);
        tidy.setInputEncoding("UTF-8");
        tidy.setOutputEncoding("UTF-8");
        tidy.setXHTML(true);
        tidy.setMakeClean(true);
        tidy.setForceOutput(true);

        ByteArrayInputStream boas = new ByteArrayInputStream(strResult.getBytes("UTF-8"));
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        FileOutputStream baoOut = new FileOutputStream(new File("C:\\Users\\XXX\\Desktop\\pdfWork\\out.pdf"));

        tidy.parseDOM(boas, bos);


        com.itextpdf.text.Document documentText = new com.itextpdf.text.Document(PageSize.LETTER); // PageSize.A4, 10.0F, 10.0F, 10.0F, 0.0F
        PdfWriter pdfWriter = PdfWriter.getInstance(documentText, new FileOutputStream(new File("C:\\Users\\Onur\\Desktop\\pdfWork\\out.pdf")));
        documentText.open();

//        documentText.open();
//        HTMLWorker htmlWorker = new HTMLWorker(documentText);
//        htmlWorker.parse(new StringReader(IOUtils.toString(new ByteArrayInputStream(bos.toByteArray()), "UTF-8")));
//        documentText.close();

        XMLWorkerHelper worker = XMLWorkerHelper.getInstance();
        worker.parseXHtml(pdfWriter, documentText, new StringReader(IOUtils.toString(new ByteArrayInputStream(bos.toByteArray()))));
        documentText.close();

3)飞碟

我做了几乎与IText相同的步骤。我设法用公认的css样式标签生成PDF。我遇到的单个问题是表和一些元素溢出。它们不适合页面。我用

中建议的页面规则解决了这个问题

How can i make my html page to be fit in the pdf using Flying Saucer

Document document = // invoice as document
    StreamSource xslt = new StreamSource(getClass().getResourceAsStream("/xslt/general.xslt"));

        TransformerFactory factory = TransformerFactory.newInstance();
//      Source xslt = new StreamSource(getClass().getResourceAsStream("/xslts/general.xslt"));
//      xslt.setSystemId("/xslts/general.xslt");
        StringWriter writer = new StringWriter();
        StreamResult result = new StreamResult(writer);

        Transformer transformer = factory.newTransformer(xslt);
        DOMSource domSource = new DOMSource(document);
        transformer.transform(domSource, result);
        String strResult = writer.toString();


        Tidy tidy = new Tidy();
        tidy.setInputEncoding("UTF-8");
        tidy.setOutputEncoding("UTF-8");
        tidy.setXHTML(true);
        tidy.setMakeClean(true);
        tidy.setForceOutput(true);

        ByteArrayInputStream boas = new ByteArrayInputStream(strResult.getBytes("UTF-8"));
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        FileOutputStream baoOut = new FileOutputStream(new File("C:\\Users\\XXX\\Desktop\\pdfWork\\out2.pdf"));

        tidy.parseDOM(boas, bos);
        System.out.println(bos.toString("UTF-8"));


        ITextRenderer renderer = new ITextRenderer();
        renderer.getFontResolver().addFont("/unicode/ARIALUNI.TTF", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);

//        renderer.setDocument();
        renderer.setDocumentFromString(IOUtils.toString(new ByteArrayInputStream(bos.toByteArray())));
//                renderer.setPDFVersion('');
        renderer.layout();
        renderer.createPDF(baoOut);
        renderer.finishPDF();
        baoOut.flush();
        baoOut.close();

正如我所说,我设法使用飞碟从xhtml生成PDF文件。但是我必须在general.xslt中添加页面规则和一些内联样式来执行此操作。但问题是每个客户都可以拥有自己的xslt用于发票视图。所以我不想触摸和更改xslt。 general.xslt可以从下面的链接下载。我怎样才能实现这一目标?可能吗 ?或者我做错了什么?在此先感谢!

http://www.efatura.gov.tr/dosyalar/kilavuzlar/UBL-TR1.2_Paketi.zip

0 个答案:

没有答案