I am parsing HTML string using iTextSharp XMLWorker in my WPF application using the below code:
var css = "";
using (var htmlMS = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(html)))
{
//Create a stream to read our CSS
using (var cssMS = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(css)))
{
//Get an instance of the generic XMLWorker
var xmlWorker = XMLWorkerHelper.GetInstance();
//Parse our HTML using everything setup above
xmlWorker.ParseXHtml(writer, doc, htmlMS, cssMS, System.Text.Encoding.UTF8, fontProv);
}
}
The parsing works fine but it is really slow, it takes around 2 seconds to parse the HTML. So for a 50 page pdf, it takes around 2 minutes. I am using inline styling to in my HTML string. Is this the natural behaviour or it can be optimized?
The question is wrong in the sense that it suggests that the HTML parsing is slowing everything down. That's not true. The bottleneck occurs even before the first snippet of HTML is parsed.
You are using the most basic handful of lines of code to create your PDF from HTML as demonstrated in the ParseHtml example:
public void createPdf(String file) throws IOException, DocumentException {
// step 1
Document document = new Document();
// step 2
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
// step 3
document.open();
// step 4
XMLWorkerHelper.getInstance().parseXHtml(writer, document,
new FileInputStream(HTML));
// step 5
document.close();
}
This code is simple, but it performs a lot of operations internally as explained in the comments of this other question: XMLWorkerHelper performance slow.
The act of registering font directories consumes plenty of time. You can avoid this, by using your own FontProvider
as is done in the ParseHtmlFonts example.
public void createPdf(String file) throws IOException, DocumentException {
// step 1
Document document = new Document();
// step 2
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
writer.setInitialLeading(12.5f);
// step 3
document.open();
// step 4
// CSS
CSSResolver cssResolver = new StyleAttrCSSResolver();
CssFile cssFile = XMLWorkerHelper.getCSS(new FileInputStream(CSS));
cssResolver.addCss(cssFile);
// HTML
XMLWorkerFontProvider fontProvider = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
fontProvider.register("resources/fonts/Cardo-Regular.ttf");
fontProvider.register("resources/fonts/Cardo-Bold.ttf");
fontProvider.register("resources/fonts/Cardo-Italic.ttf");
fontProvider.addFontSubstitute("lowagie", "cardo");
CssAppliers cssAppliers = new CssAppliersImpl(fontProvider);
HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
// Pipelines
PdfWriterPipeline pdf = new PdfWriterPipeline(document, writer);
HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);
// XML Worker
XMLWorker worker = new XMLWorker(css, true);
XMLParser p = new XMLParser(worker);
p.parse(new FileInputStream(HTML));
// step 5
document.close();
}
In this case, we instruct iText DONTLOOKFORFONTS, thus saving an enormous amount of time. Instead of having iText looking for fonts, we tell iText which fonts we're going to use in the HTML.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With