Convertendo HTML para PDF usando o iText

Estou postando esta pergunta porque muitos desenvolvedores fazem mais ou menos a mesma pergunta de formas diferentes. Eu mesmo responderei a essa pergunta (sou o Fundador / CTO do iText Group), para que possa ser uma "resposta da Wiki". Se o recurso "documentação" do estouro de pilha ainda existisse, esse seria um bom candidato para um tópico de documentação.

O arquivo de origem:

Estou tentando converter o seguinte arquivo HTML em PDF:

<html>
    <head>
        <title>Colossal (movie)</title>
        <style>
            .poster { width: 120px;float: right; }
            .director { font-style: italic; }
            .description { font-family: serif; }
            .imdb { font-size: 0.8em; }
            a { color: red; }
        </style>
    </head>
    <body>
        <img src="img/colossal.jpg" class="poster" />
        <h1>Colossal (2016)</h1>
        <div class="director">Directed by Nacho Vigalondo</div>
        <div class="description">Gloria is an out-of-work party girl
            forced to leave her life in New York City, and move back home.
            When reports surface that a giant creature is destroying Seoul,
            she gradually comes to the realization that she is somehow connected
            to this phenomenon.
        </div>
        <div class="imdb">Read more about this movie on
            <a href="www.imdb.com/title/tt4680182">IMDB</a>
        </div>
    </body>
</html>

Em um navegador, esse HTML se parece com o seguinte:

Os problemas que encontrei:

O HTMLWorker não leva em consideração o CSS

Quando eu useiHTMLWorker, Preciso criar umImageProvider para evitar um erro que me informa que a imagem não pode ser encontrada. Eu também preciso criar umStyleSheet instância para alterar alguns dos estilos:

public static class MyImageFactory implements ImageProvider {
    public Image getImage(String src, Map<String, String> h,
            ChainedProperties cprops, DocListener doc) {
        try {
            return Image.getInstance(
                String.format("resources/html/img/%s",
                    src.substring(src.lastIndexOf("/") + 1)));
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }    
}

public static void main(String[] args) throws IOException, DocumentException {
    Document document = new Document();
    PdfWriter.getInstance(document, new FileOutputStream("results/htmlworker.pdf"));
    document.open();
    StyleSheet styles = new StyleSheet();   
    styles.loadStyle("imdb", "size", "-3");
    HTMLWorker htmlWorker = new HTMLWorker(document, null, styles);
    HashMap<String,Object> providers = new HashMap<String, Object>();
    providers.put(HTMLWorker.IMG_PROVIDER, new MyImageFactory());
    htmlWorker.setProviders(providers);
    htmlWorker.parse(new FileReader("resources/html/sample.html"));
    document.close();   
}

O resultado fica assim:

Por algum motivo,HTMLWorker também mostra o conteúdo do<title> etiqueta, rótulo, palavra-chave. Não sei como evitar isso. O CSS no cabeçalho não é analisado, tenho que definir todos os estilos no meu código, usando oStyleSheet objeto.

Quando olho para o meu código, vejo que muitos objetos e métodos que estou usando estão obsoletos:

Então, decidi atualizar para o XML Worker.

Imagens não são encontradas ao usar o XML Worker

Eu tentei o seguinte código:

public static final String DEST = "results/xmlworker1.pdf";
public static final String HTML = "resources/html/sample.html";
public void createPdf(String file) throws IOException, DocumentException {
    Document document = new Document();
    PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
    document.open();
    XMLWorkerHelper.getInstance().parseXHtml(writer, document,
            new FileInputStream(HTML));
    document.close();
}

Isso resultou no seguinte PDF:

Em vez de Times-Roman, a fonte padrão Helvetica é usada; isso é típico para o iText (eu deveria ter definido uma fonte explicitamente no meu HTML). Caso contrário, o CSS parece ser respeitado, mas a imagem está faltando e eu não recebi uma mensagem de erro.

ComHTMLWorker, uma exceção foi lançada e eu pude corrigir o problema introduzindo umImageProvider. Vamos ver se isso funciona para o XML Worker.

Nem todos os estilos CSS são suportados no XML Worker

Eu adaptei meu código assim:

public static final String DEST = "results/xmlworker2.pdf";
public static final String HTML = "resources/html/sample.html";
public static final String IMG_PATH = "resources/html/";
public void createPdf(String file) throws IOException, DocumentException {
    Document document = new Document();
    PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
    document.open();

    CSSResolver cssResolver =
            XMLWorkerHelper.getInstance().getDefaultCssResolver(true);
    HtmlPipelineContext htmlContext = new HtmlPipelineContext(null);
    htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
    htmlContext.setImageProvider(new AbstractImageProvider() {
        public String getImageRootPath() {
            return IMG_PATH;
        }
    });

    PdfWriterPipeline pdf = new PdfWriterPipeline(document, writer);
    HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
    CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);

    XMLWorker worker = new XMLWorker(css, true);
    XMLParser p = new XMLParser(worker);
    p.parse(new FileInputStream(HTML));

    document.close();
}

Meu código é muito mais longo, mas agora a imagem é renderizada:

A imagem é maior do que quando a renderizei usandoHTMLWorker o que me diz que o atributo CSSwidth para oposter classe é levada em consideração, mas ofloat O atributo é ignorado. Como faço para corrigir isso?

A questão restante:

Então a questão se resume a isso: eu tenho umespecífico Arquivo HTML que tento converter em PDF. Passei por muito trabalho, corrigindo um problema após o outro, mas há umespecífico problema que não consigo resolver: como faço para o iText respeitar o CSS que define a posição de um elemento, comofloat: right?

Pergunta adicional:

Quando meu HTML contém elementos de formulário (como<input>), esses elementos do formulário são ignorados.

questionAnswers(1)

yourAnswerToTheQuestion