iText:从现有PDF导入样式文本和信息

时间:2015-08-13 06:29:07

标签: java html pdf itext

我使用iText生成PDF并且工作正常。但是我需要一种方法来从现有的PDF中导入html样式的信息。 我知道我可以使用XMLWorker类直接从我自己的文档中的html生成文本。但是因为我不确定它是否真的支持我想要解决的所有html功能。 因此,使用XSLT从html生成PDF。然后应将此PDF的内容复制到我的文档中。 书中有两种方式(“iText in Action”)。 一个解析PDF并使用PdfReaderContentParser和TextExtractionStrategy从文档中获取文本(或其他信息)。 它看起来像这样:

PdfReader reader = new PdfReader(pdf);
PdfReaderContentParser parser = new PdfReaderContentParser(reader);
TextExtractionStrategy strategy;
for(int i=1;i<=reader.getNumberOfPages();i++){
strategy = parser.processContent(i, new LocationTextExtractionStrategy());
document.add(new Chunk(strategy.getResultantText()));
}

但这只会将纯文本打印到文档中。显然有更多的ExtractionStrategys,也许其中一个完全符合我的要求,但我还没有找到它。

第二种方法是将PDF每一面的itextpdf.text.Image复制到您的文档中。这显然不是一个好主意,因为即使现有PDF中只有一行文本,它也会将整个页面添加到您的文档中。它是这样做的:

PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
PdfReader reader = new PdfReader(pdf);
PdfImportedPage page;
for(int i=1;i<=reader.getNumberOfPages();i++){
page = writer.getImportedPage(reader,i);
document.add(Image.getInstance(page));
}

就像我说的那样,复制PDF末尾的所有空行,但我需要在最后一行文本后立即继续我的文本。 如果我可以将这个itext.text.Image转换为java.awt.BufferedImage,我可以使用getSubImage();我可以从PDF中提取信息以删除所有空行。但我无法找到解决这个问题的方法。

这是我发现的两种方式。但是因为它们都不适合我的目的,因为它们是我的问题是: 有没有办法导入除最后的空行以外的所有内容,但包括文本样式的信息,表格以及使用iText从PDF到我的文档的所有其他内容?

1 个答案:

答案 0 :(得分:0)

您可以删除XSLT生成的PDF的空白区域,然后像在代码中一样导入修剪后的页面。

示例代码

以下代码借鉴了我对Using iTextPDF to trim a page's whitespace的回答中的代码。与那里的代码相反,我们必须操纵媒体框,而不是裁剪框,因为这是PdfWriter.getImportedPage所尊重的唯一框。

在从给定PdfReader导入页面之前,请使用以下方法裁剪:

static void cropPdf(PdfReader reader) throws IOException
{
    int n = reader.getNumberOfPages();
    for (int i = 1; i <= n; i++)
    {
        PdfReaderContentParser parser = new PdfReaderContentParser(reader);
        MarginFinder finder = parser.processContent(i, new MarginFinder());
        Rectangle rect = new Rectangle(finder.getLlx(), finder.getLly(), finder.getUrx(), finder.getUry());

        PdfDictionary page = reader.getPageN(i);
        page.put(PdfName.MEDIABOX, new PdfArray(new float[]{rect.getLeft(), rect.getBottom(), rect.getRight(), rect.getTop()}));
    }
}

(摘自ImportPageWithoutFreeSpace.java

扩展渲染侦听器MarginFinder将从上面链接的问题中获取。你可以在这里找到一份副本:MarginFinder.java

运行示例

使用此代码

PdfReader readerText = new PdfReader(docText);
cropPdf(readerText);
PdfReader readerGraphics = new PdfReader(docGraphics);
cropPdf(readerGraphics);
try (   FileOutputStream fos = new FileOutputStream(new File(RESULT_FOLDER, "importPages.pdf")))
{
    Document document = new Document();
    PdfWriter writer = PdfWriter.getInstance(document, fos);
    document.open();
    document.add(new Paragraph("Let's import 'textOnly.pdf'", new Font(FontFamily.HELVETICA, 12, Font.BOLD)));
    document.add(Image.getInstance(writer.getImportedPage(readerText, 1)));
    document.add(new Paragraph("and now 'graphicsOnly.pdf'", new Font(FontFamily.HELVETICA, 12, Font.BOLD)));
    document.add(Image.getInstance(writer.getImportedPage(readerGraphics, 1)));
    document.add(new Paragraph("That's all, folks!", new Font(FontFamily.HELVETICA, 12, Font.BOLD)));

    document.close();
}
finally
{
    readerText.close();
    readerGraphics.close();
}

(摘自ImportPageWithoutFreeSpace.java中的单元测试方法testImportPages

我从docText文档中导入了两个页面

<code>docText</code> document

以及docGraphics文档

中的页面

<code>docGraphics</code> document

进入一个包含之前,之间和之后的一些文本的新文档。结果:

result of the import

如您所见,源样式被保留,但周围的自由空间被丢弃。