2016-03-23 10 views
8

xmlworker'da aşağıya yazı yazma yönü elde etmek mümkün mü? Bunu masada kullanmak istiyorum. Kodumhtml dosyasını pdf'ye dönüştürmek ve dikey olarak metin yazmak için itextsharp xmlworker öğesini kullanma

 <table border=1> 
    <tr> 
    <td style="padding-right:18px"> 
      <p style="writing-mode:sideways-lr;text-align:center">First</p</td> 
    <td style="padding-right:18px"> 
      <p style="writing-mode:sideways-lr;text-align:center">Second</p></td></tr> 
    <tr><td><p style="text-align:center">1</p> </td> 
     <td><p style="text-align:center">2</p></td> 
    </tr> 
     </table> 

olduğunu Ama buna pdf html dönüşüm sonra çalışmaz. İLK ve İKİNCİ metinler aşağıdan yukarıya yönde değildir.

+0

Bunu yapmak için özel kod yazmak gerekir 9 İşte updated sonucu. Ne bekliyorsanız bir 'HTML' örnek eklerseniz, birisi _might_ yardımcı olabilir ... – kuujinbo

cevap

6

Bu oldukça ilginç bir sorundu, bu yüzden soruya +1.

İlk adım, iTextSharp XML Worker'ın HTMLtd etiketini destekleyip desteklemediğine bakmaktı. Eşleştirmeler kaynağında iTextSharp.tool.xml.html.Tags'da bulunabilir. td'un iTextSharp.tool.xml.html.table.TableData ile eşleştiğini görüyorsunuz, bu da özel bir etiket işlemcisinin işini biraz daha kolay hale getiriyor. Yani Biz sınıfından miras ve End() geçersiz do için gereken tüm:

public class TableDataProcessor : TableData 
{ 
    /* 
    * a **very** simple implementation of the CSS writing-mode property: 
    * https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode 
    */ 
    bool HasWritingMode(IDictionary<string, string> attributeMap) 
    { 
     bool hasStyle = attributeMap.ContainsKey("style"); 
     return hasStyle 
       && attributeMap["style"].Split(new char[] { ';' }) 
       .Where(x => x.StartsWith("writing-mode:")) 
       .Count() > 0 
      ? true : false; 
    } 

    public override IList<IElement> End(
     IWorkerContext ctx, 
     Tag tag, 
     IList<IElement> currentContent) 
    { 
     var cells = base.End(ctx, tag, currentContent); 
     var attributeMap = tag.Attributes; 
     if (HasWritingMode(attributeMap)) 
     { 
      var pdfPCell = (PdfPCell) cells[0]; 
      // **always** 'sideways-lr' 
      pdfPCell.Rotation = 90; 
     } 
     return cells; 
    } 
} 

satır içi açıklamalarda belirtildiği gibi, bu özel ihtiyaçları için bir çok basit bir uygulamasıdır. Diğer writing-modeCSS property value'u desteklemek için ek mantık eklemeniz ve herhangi bir akıl kontrolünü eklemeniz gerekir.

GÜNCELLEME

@Daniel bıraktığı yorumun dayanarak, PDF için HTML dönüştürürken özel CSS nasıl ekleneceği değil açık. İlk güncelleştirilmiş HTML: Sonra

string XHTML = @" 
<h1>Table with Vertical Text</h1> 
<table><tr> 
<td style='writing-mode:sideways-lr;text-align:center;width:40px;'>First</td> 
<td style='writing-mode:sideways-lr;text-align:center;width:40px;'>Second</td></tr> 
<tr><td style='text-align:center'>1</td> 
<td style='text-align:center'>2</td></tr></table> 

<h1>Table <u>without</u> Vertical Text</h1> 
<table width='50%'> 
<tr><td class='light-yellow'>0</td></tr> 
<tr><td>1</td></tr> 
<tr><td class='light-yellow'>2</td></tr> 
<tr><td>3</td></tr> 
</table>"; 

özel CSS küçük bir pasajı:

string CSS = @" 
    body {font-size: 12px;} 
    table {border-collapse:collapse; margin:8px;} 
    .light-yellow {background-color:#ffff99;} 
    td {border:1px solid #ccc;padding:4px;} 
"; 

hafifçe zor kısmı ekstra kurulum - eğer sık ​​görülen kutu XMLWorkerHelper.GetInstance().ParseXHtml() üzerinden basit kullanamazsınız burada SO. İşte size başlamış basit bir yardımcı bir yöntem vardır:

public void ConvertHtmlToPdf(string xHtml, string css) 
{ 
    using (var stream = new FileStream(OUTPUT_FILE, FileMode.Create)) 
    { 
     using (var document = new Document()) 
     { 
      var writer = PdfWriter.GetInstance(document, stream); 
      document.Open(); 

      // instantiate custom tag processor and add to `HtmlPipelineContext`. 
      var tagProcessorFactory = Tags.GetHtmlTagProcessorFactory(); 
      tagProcessorFactory.AddProcessor(
       new TableDataProcessor(), 
       new string[] { HTML.Tag.TD } 
      ); 
      var htmlPipelineContext = new HtmlPipelineContext(null); 
      htmlPipelineContext.SetTagFactory(tagProcessorFactory); 

      var pdfWriterPipeline = new PdfWriterPipeline(document, writer); 
      var htmlPipeline = new HtmlPipeline(htmlPipelineContext, pdfWriterPipeline); 

      // get an ICssResolver and add the custom CSS 
      var cssResolver = XMLWorkerHelper.GetInstance().GetDefaultCssResolver(true); 
      cssResolver.AddCss(css, "utf-8", true); 
      var cssResolverPipeline = new CssResolverPipeline(
       cssResolver, htmlPipeline 
      ); 

      var worker = new XMLWorker(cssResolverPipeline, true); 
      var parser = new XMLParser(worker); 
      using (var stringReader = new StringReader(xHtml)) 
      { 
       parser.Parse(stringReader); 
      } 
     } 
    } 
} 

Yukarıdaki örnek kod bir açıklama rehashing, see the documentation Gerekirse neden daha iyi bir fikir edinmek için (iText Wayback Machine ile bağlantılı belgeleri, kaldırıldı) yerine ayrıştırıcıyı bu şekilde ayarlayın.

Ayrıca Not:

  1. XML İşçi değil desteği tüm BB2/CSS3 özellikleri; bu nedenle may çalışır veya istediğiniz kadar yakın açısından işe yaramazsa ne deneme ihtiyacı Tarayıcıda görüntülenen HTML'ye bakmak için PDF.
  2. HTML snippet'i, stil td etiketine doğrudan uygulanabileceğinden, p etiketini kaldırmıştır.
  3. Satır içi width özelliği. Gerekmiyorsa, sütunlar yatay olarak oluşturulmuşsa, eşleşen genişliklerde genişlikler olacaktır.

iTextSharp ve XML Worker sürüm 5.5 ile test edilmiştir.utf8 ile

enter image description here

+0

Çok teşekkürler. Çok yardımcı oluyor. Benim durumumda html dosyası büyük. Çok fazla tablo var ama sadece iki tablo dikey metne ihtiyaç duyuyor. Kendi css kodunuzun geri kalanına nasıl uygulanacağını merak ediyorum. Bunu daha önce yaptım: 'kullanarak (var myCss = yeni MemoryStream (System.Text.Encoding.UTF8.GetBytes (örnek_css))) { kullanarak (var msHtml = new MemoryStream (System.Text.Encoding.UTF8.GetBytes (example_html)))) {iTextSharp.tool.xml.XMLWorkerHelper.GetInstance() ParseXHtml (yazar, doc, msHtml, myCss); } } ' – Daniel

+0

@Daniel - yanıtı, bir 'HTML' dizesi ve bir 'CSS' dizesini iletmenize izin veren bir yardımcı yöntem içerecek şekilde güncelleştirildi. – kuujinbo

+0

Bir kez daha, çok teşekkürler. – Daniel

0
public void addHtmlToPdf(Document document, PdfWriter writer, String html) { 
    PdfPTable table = new PdfPTable(1); 
    PdfPCell cell = new PdfPCell(); 
    ElementList list = XMLWorkerHelper.ParseToElementList(html, null); 
    foreach(IElement element in list) { 
     cell.AddElement(element); 
    } 
    table.AddCell(cell); 
    document.Add(table); 
} 

Alternatif::

public void addHtmlToPdf_Utf8(Document document, PdfWriter writer, String html) 
{ 
    XMLWorkerHelper xml = XMLWorkerHelper.GetInstance(); 
    xml.ParseXHtml(writer, document, stringToStream(html), System.Text.Encoding.UTF8); 
} 
public Stream stringToStream(string txt) { 
    var stream = new MemoryStream(); 
    var w = new StreamWriter(stream); 
    w.Write(txt); 
    w.Flush(); 
    stream.Position = 0; 
    return stream; 
} 
İlgili konular