Преобразование искаженного HTML в PDF с помощью Flying Saucer PDF Rendering - PullRequest
0 голосов
/ 30 августа 2018

В проекте GitHub Я пытаюсь преобразовать любую произвольную строку HTML в PDF-версию. Под преобразованием я понимаю синтаксический анализ HTML-кода и его преобразование в файл PDF.

Чтобы добиться этого, я использую Flying Saucer PDF Rendering , например:

Main.java

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();
        }
    }
}

В приведенном выше коде, если я использую html-строку, хранящуюся в переменной ok (это «действительный» html), он правильно создает PDF-файл (если вы запустите проект GitHub с помощью переменной ok, он будет создайте файл 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.

Важные примечания:

  • Значения, присвоенные переменным ok и html, являются только заполнителями для вопроса. Реальные из них здесь .
  • В реальном проекте строка html является вводом, полученным от пользователя. Да, он / она должен знать, что туда поместить, но, конечно, он / она может делать некоторые ошибки в конформации html, поэтому я должен с этим справиться.

Вопрос (ы)

  • Есть ли способ, которым я могу "сказать" Flying Saucer PDF Rendering в игнорировать / автозаполнение / очистить себя / или любые другие , эти "недействительные" детали и переходите к созданию файла PDF (предпочтительно) .
  • Есть ли лучший подход, который я могу использовать, чтобы преодолеть это?

Ответы [ 2 ]

0 голосов
/ 30 августа 2018

Я сделал то же самое совсем недавно. Использовал Flying Saucer для создания PDF из HTML. Поскольку у меня была та же проблема, я использовал библиотеку HtmlCleaner для очистки кода HTML перед анализом в библиотеке Flying Saucer.

// 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);
// ....

https://mvnrepository.com/artifact/net.sourceforge.htmlcleaner/htmlcleaner http://htmlcleaner.sourceforge.net/javause.php

0 голосов
/ 30 августа 2018

Первоначальной мыслью было бы проанализировать ваш ввод через другую библиотеку, которая могла бы лучше обрабатывать html, а затем toString () результаты этой библиотеки в PDF Renderer.

https://jsoup.org/

Пять минут поиска в Google показали, что это довольно разумная библиотека для использования. Есть даже тестовая утилита, в которую вы можете попытаться добавить неверный результат:

https://try.jsoup.org/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...