簡體   English   中英

使用 Flying Saucer PDF Rendering 將格式錯誤的 HTML 轉換為 PDF

[英]Convert malformed HTML to PDF using Flying Saucer PDF Rendering

GitHub項目中,我試圖將任意 HTML 字符串轉換為 PDF 版本。 通過轉換,我的意思是解析 HTML,並將其呈現為 PDF 文件。

為了實現這一點,我正在使用飛碟 PDF 渲染,如下所示:

主程序

public class Main {

    public static void main(String [] args) {
        final String ok = "<valid html here>: see github rep for real html markup here";
        final String html = "<invalid html here>: see github rep for real html markup here";
        try {
            // final byte[] bytes = generatePDFFrom(ok); // works!
            final byte[] bytes = generatePDFFrom(html); // does NOT work :(
            try(FileOutputStream fos = new FileOutputStream("sample-file.pdf")) {
                fos.write(bytes);
            }

        } catch (IOException | DocumentException e) {
            e.printStackTrace();
        }
    }

    private static byte[] generatePDFFrom(String html) throws IOException, DocumentException {
        final ITextRenderer renderer = new ITextRenderer();
        renderer.setDocumentFromString(html);
        renderer.layout();
        try (ByteArrayOutputStream fos = new ByteArrayOutputStream(html.length())) {
            renderer.createPDF(fos);
            return fos.toByteArray();
        }
    }
}

在上面的代碼中,如果我使用存儲在ok變量中的 html 字符串(這是一個“有效”的 html),它會正確創建 PDF(如果您使用ok變量運行 GitHub 項目,它將創建一個文件sample-file.pdf在項目文件夾中,並帶有一些呈現的 html)。

現在,如果我使用html變量中的值(帶有無效標簽的 html,標簽可能未正確關閉等),它會引發以下錯誤(錯誤可能因不正確的值而異):

ERROR:  'The markup in the document following the root element must be well-formed.'
Exception in thread "main" org.xhtmlrenderer.util.XRRuntimeException: Can't load the XML resource (using TrAX transformer). org.xml.sax.SAXParseException; lineNumber: 22; columnNumber: 9; The markup in the document following the root element must be well-formed.
    at org.xhtmlrenderer.resource.XMLResource$XMLResourceBuilder.transform(XMLResource.java:222)
    at org.xhtmlrenderer.resource.XMLResource$XMLResourceBuilder.createXMLResource(XMLResource.java:181)
    at org.xhtmlrenderer.resource.XMLResource.load(XMLResource.java:84)
    at org.xhtmlrenderer.pdf.ITextRenderer.setDocumentFromString(ITextRenderer.java:171)
    at org.xhtmlrenderer.pdf.ITextRenderer.setDocumentFromString(ITextRenderer.java:166)
    at Main.generatePDFFrom(Main.java:84)
    at Main.main(Main.java:72)
Caused by: javax.xml.transform.TransformerException: org.xml.sax.SAXParseException; lineNumber: 22; columnNumber: 9; The markup in the document following the root element must be well-formed.
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:740)
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:343)
    at org.xhtmlrenderer.resource.XMLResource$XMLResourceBuilder.transform(XMLResource.java:220)
    ... 6 more
Caused by: org.xml.sax.SAXParseException; lineNumber: 22; columnNumber: 9; The markup in the document following the root element must be well-formed.
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1239)
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:659)
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:728)
    ... 8 more

現在,據我所知,這是因為 html 字符串的“無效”部分。

重要筆記:

  • 這里分配給變量okhtml的值只是問題的占位符。 真正的在這里
  • 在實際項目中,html 字符串是來自用戶的輸入。 是的,他/她必須知道在那里放什么,但是,當然,他/她可以在 html 構造中犯一些錯誤,所以我必須處理這個。

問題)

  • 有什么方法可以“告訴”飛碟 PDF 渲染忽略/自動完成/清理自身/或任何其他“無效”部分,然后繼續創建 PDF 文件(首選)
  • 有沒有更好的方法可以用來克服這個問題。

由於我在使用 Flying Saucer 從 HTML 生成 PDF 時遇到了同樣的問題,因此在解析到 Flying Saucer 庫之前,我使用了HtmlCleaner庫(請參閱maven 鏈接)來清理 HTML 代碼。

// Clean the html to use in the flying saucer converting tool
// get the element you want to serialize
HtmlCleaner cleaner = new HtmlCleaner();
TagNode rootTagNode = cleaner.clean(html);
// set up properties for the serializer (optional, see online docs)
CleanerProperties cleanerProperties = cleaner.getProperties();
// use the getAsString method on an XmlSerializer class
XmlSerializer xmlSerializer = new PrettyXmlSerializer(cleanerProperties);
String cleanedHtml = xmlSerializer.getAsString(rootTagNode);

// use the https://github.com/flyingsaucerproject/flyingsaucer to convert cleaned HTML to PDF
ITextRenderer renderer = new ITextRenderer();
renderer.setDocumentFromString(cleanedHtml);
// ....

最初的想法是通過另一個能夠更好地處理 html 的庫來解析您的輸入,然后將該庫的結果toString()解析到 PDF 渲染器中。

https://jsoup.org/

五分鍾的谷歌搜索發現這是一個非常合理的庫使用。 甚至還有一個測試實用程序,您可以嘗試將格式錯誤的輸入放入:

https://try.jsoup.org/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM