2014-01-22 36 views
5

我解析使用下面的代碼在我的WPF應用程序中使用iTextSharp的XMLWorker HTML字符串:iTextSharp的XMLWorker解析很慢

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

解析工作正常,但它真的很慢,大約需要2秒解析HTML。因此,對於50頁的PDF文件,大約需要2分鐘。我在我的HTML字符串中使用內聯樣式。這是自然行爲還是可以優化?

+4

您的HTML深度嵌套?例如,一切都包裹在一個巨大的DIV中?在這些情況下,解析器(甚至是普通的桌面瀏覽器)必須在它能夠呈現第一件事之前一直到文檔的末尾。你在用桌子嗎? PDFs沒有表格的概念,因此iText必須模擬它們,如果它們很長,可能在計算上很昂貴。你在使用圖像嗎?如果是這樣,iText必須加載/下載圖像(取決於它們的引用方式),這也需要時間。 –

+0

我還沒有答案,但我也看到這個圖書館的速度非常慢。大部分時間都是在ParseXHtml內部的以下方法中被使用的: iTextSharp.text.FontFactoryImp.RegisterDirectories –

+0

我發現只有在調試模式下運行我的應用程序時,XMLWorkerHelper實例超級慢。 –

回答

6

從這個意義上說,這個問題是錯誤的,它表明HTML解析會減慢一切。這不是真的。即使在解析HTML的第一個片段之前,也會出現瓶頸。

您正在使用的代碼行的最基本的少數如ParseHtml例子證明創建HTML您的PDF:

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

這段代碼很簡單,但解釋它執行了很多操作的內部在這個其他問題的意見:XMLWorkerHelper performance slow

註冊字體目錄的行爲消耗大量時間。您可以像ParseHtmlFonts示例中那樣使用您自己的FontProvider來避免這種情況。

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

在這種情況下,我們指導iText DONTLOOKFORFONTS,從而節省大量時間。我們沒有讓iText查找字體,而是告訴iText我們將在HTML中使用哪些字體。

+0

感謝您提供來自源代碼的明確答案 - 我將開始擴展我的代碼庫。 –