2016-11-25 54 views
8

我正在使用Android的Itext庫將html轉換爲pdf,它工作正常,但在某些情況下它不能正確解析。我想創建一個紅色的虛線分隔符,但它總是給我一個深灰色的實線分隔符。使用iText庫將html轉換爲pdf時不適用hr的Inline CSS

我的HTML標籤是

<hr noshade style="border: 0; width:100%;border-bottom-width: 1px; border-bottom-style: dotted; border-bottom-color: red"> 

我轉換代碼

 Document document = new Document(PageSize.A4); 

     //this sets the margin to the created pdf 
     document.setMargins(35, 35, 150, 100); 

     PdfWriter writer = PdfWriter.getInstance(document, 
       new FileOutputStream(fileWithinMyDir)); 
     if (isPrescription) { 
      HeaderFooterPageEvent event = new HeaderFooterPageEvent(); 
      writer.setPageEvent(event); 
     } else { 
      CertificateFooterPageEvent event = new CertificateFooterPageEvent(); 
      writer.setPageEvent(event); 
     } 
     document.open(); 
     HtmlPipelineContext htmlContext = new HtmlPipelineContext(null); 
     htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory()); 
     htmlContext.setImageProvider(new AbstractImageProvider() { 
      public String getImageRootPath() { 

       Uri uri = Uri.parse("file:///android_asset/"); 

       return uri.toString(); 
      } 
     }); 


     CSSResolver cssResolver = 
       XMLWorkerHelper.getInstance().getDefaultCssResolver(false); 

     // Pipelines 
     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); 
     InputStream is = new ByteArrayInputStream(htmlString.getBytes()); 
     XMLWorkerHelper.getInstance().parseXHtml(writer, document, is); 
     p.parse(is); 

     document.close(); 
+0

未使用iText,所以我只能提供一個建議。嘗試爲'hr's樣式添加'background-color:transparent;'並刪除'noshade':


'。 –

+0

@HiddenHobbes仍然是一樣的,問題出在圖書館,我正在尋找解決辦法。 –

回答

4

我是一個.NET開發人員,所以該代碼是在C#。但是你應該可以輕鬆地翻譯以下內容。

iText是一個PDF優先庫,而[X]HTML解析相當複雜,所以它在這方面不是全功能。每當解析[X]HTML,事情不會你期望的特定標籤的方式,你應該遵循的基本步驟是:

  1. 驗證XML Worker支持標籤:Tags class
  2. 如果標籤支持,在這種情況下,這是真實的,看看默認的實現。這是由the HorizontalRule class處理的。但是,我們發現不支持您的用例,因此一種方法是使用該代碼作爲藍圖。 (如下所示)您也可以繼承特定的標記類並覆蓋End()方法as done here。無論哪種方式,你所做的只是實現一個自定義標籤處理器。
  3. 如果標籤爲而不是支持,則需要從AbstractTagProcessor繼承自定義標籤處理器。

無論如何,下面是一個簡單的例子,讓你開始。首先,自定義標籤處理器:

public class CustomHorizontalRule : AbstractTagProcessor 
{ 
    public override IList<IElement> Start(IWorkerContext ctx, Tag tag) 
    { 
     IList<IElement> result; 
     LineSeparator lineSeparator; 
     var cssUtil = CssUtils.GetInstance(); 

     try 
     { 
      IList<IElement> list = new List<IElement>(); 
      HtmlPipelineContext htmlPipelineContext = this.GetHtmlPipelineContext(ctx); 

      Paragraph paragraph = new Paragraph(); 
      IDictionary<string, string> css = tag.CSS; 
      float baseValue = 12f; 
      if (css.ContainsKey("font-size")) 
      { 
       baseValue = cssUtil.ParsePxInCmMmPcToPt(css["font-size"]); 
      } 
      string text; 
      css.TryGetValue("margin-top", out text); 
      if (text == null) text = "0.5em"; 

      string text2; 
      css.TryGetValue("margin-bottom", out text2); 
      if (text2 == null) text2 = "0.5em"; 

      string border; 
      css.TryGetValue(CSS.Property.BORDER_BOTTOM_STYLE, out border); 
      lineSeparator = border != null && border == "dotted" 
       ? new DottedLineSeparator() 
       : new LineSeparator(); 

      var element = (LineSeparator)this.GetCssAppliers().Apply(
       lineSeparator, tag, htmlPipelineContext 
      ); 

      string color; 
      css.TryGetValue(CSS.Property.BORDER_BOTTOM_COLOR, out color); 
      if (color != null) 
      { 
       // WebColors deprecated, but docs don't state replacement 
       element.LineColor = WebColors.GetRGBColor(color); 
      } 

      paragraph.SpacingBefore += cssUtil.ParseValueToPt(text, baseValue); 
      paragraph.SpacingAfter += cssUtil.ParseValueToPt(text2, baseValue); 
      paragraph.Leading = 0f; 
      paragraph.Add(element); 
      list.Add(paragraph); 
      result = list; 
     } 
     catch (NoCustomContextException cause) 
     { 
      throw new RuntimeWorkerException(
       LocaleMessages.GetInstance().GetMessage("customcontext.404"), 
       cause 
      ); 
     } 
     return result; 
    } 
} 

大部分代碼是直接設置邊框樣式和顏色取自現有的源,隨着檢查的除外CSS.Property.BORDER_BOTTOM_STYLECSS.Property.BORDER_BOTTOM_COLOR,如果他們在<hr>會內聯style屬性。

然後添加自定義標籤處理器上面的XML工人TagProcessorFactory

using (var stream = new FileStream(OUTPUT_FILE, FileMode.Create)) 
{ 
    using (var document = new Document()) 
    { 
     var writer = PdfWriter.GetInstance(document, stream); 
     document.Open(); 

     var tagProcessorFactory = Tags.GetHtmlTagProcessorFactory(); 
     // custom tag processor above 
     tagProcessorFactory.AddProcessor(
      new CustomHorizontalRule(), 
      new string[] { HTML.Tag.HR } 
     ); 
     var htmlPipelineContext = new HtmlPipelineContext(null); 
     htmlPipelineContext.SetTagFactory(tagProcessorFactory); 

     var pdfWriterPipeline = new PdfWriterPipeline(document, writer); 
     var htmlPipeline = new HtmlPipeline(htmlPipelineContext, pdfWriterPipeline); 
     var cssResolver = XMLWorkerHelper.GetInstance().GetDefaultCssResolver(true); 
     var cssResolverPipeline = new CssResolverPipeline(
      cssResolver, htmlPipeline 
     ); 

     var worker = new XMLWorker(cssResolverPipeline, true); 
     var parser = new XMLParser(worker); 
     var xHtml = "<hr style='border:1px dotted red' />"; 
     using (var stringReader = new StringReader(xHtml)) 
     { 
      parser.Parse(stringReader); 
     } 
    } 
} 

有一點要注意的是,即使我們使用速記border內嵌樣式,iText的的CSS解析器似乎設置全部內部樣式。也就是說,您可以使用四種手形中的任何一種來檢查 - 我只是碰巧使用了CSS.Property.BORDER_BOTTOM_STYLECSS.Property.BORDER_BOTTOM_COLOR

所生成的PDF:

enter image description here

0

你可以使用一個div沒有任何或任何內容,您想要的,而不是一個小時,給邊框樣式該div,我相信它會在你的工作案件。