2016-03-23 19 views
8

xmlworkerにテキストの方向をボトムアップで書き込むことは可能ですか?私はテーブルでそれを使用したいと思います。 私のコードはitextsharp xmlworkerを使用してhtmlからpdfに変換し、テキストを垂直方向に書き込む

 <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> 

ですが、それはそれは、HTMLからPDFへの変換後に動作しません。テキストFIRSTとSECONDはボトムアップ方向にありません。

+0

あなたがこれを行うには、カスタムコードを記述する必要が9は、ここで更新結果です。あなたが期待するものの 'HTML'サンプルを追加すると、誰かが手助けすることができます... – kuujinbo

答えて

6

これはかなり面白い問題だったので、質問に+1してください。

最初のステップは、iTextSharp XML WorkerがHTMLtdタグをサポートしているかどうかを調べることでした。このマッピングは、ソースのiTextSharp.tool.xml.html.Tagsにあります。そこではtdiTextSharp.tool.xml.html.table.TableDataにマッピングされているので、カスタムタグプロセッサを実装する作業が簡単になります。私。私たちはクラスから継承し、End()を上書きする必要があるすべて:

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

インラインコメントで述べたように、これはあなたの特定のニーズのための非常に単純な実装です。 writing-modeCSS property valueをサポートする追加のロジックを追加し、サニティチェックを含める必要があります。 @Danielが残したコメントに基づいて

UPDATE

、それはPDFHTMLを変換するときにカスタムCSSを追加する方法は明らかではありません。まず、更新されたHTML:

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>"; 

次にカスタムCSSの小さなスニペット:

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

少し難しい部分は余分なセットアップです - あなたは、一般的に見ボックスXMLWorkerHelper.GetInstance().ParseXHtml()のうち、簡単なを使用することはできませんここにある。ここであなたが始める必要があり、単純なヘルパーメソッドです:

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

の代わりに上記のコード例、see the documentationの説明を焼き直し、あなたがする必要がある理由のより良いアイデアを得るために(iTextのは、ウェイバックマシンにリンクされ、ドキュメントを削除しました)そのようにパーサーをセットアップしてください。

にも注意してください:

  1. XMLワーカーが働くかあなたが欲しいどれだけ近いかに関しては動作しません何を試して必要があるかもしれませんあなたはので、ないサポートにすべてのCSS2/CSS3のプロパティを行いますPDFをブラウザーに表示されたHTMLを見てください。
  2. HTMLスニペットはタグを削除しました。このスタイルはtdタグに直接適用できるためです。
  3. インラインwidthプロパティ。省略すると、テキストが水平方向にレンダリングされた場合に一致する可変幅になります。

iTextSharpおよびXML Workerバージョン5.5でテスト済みです。UTF8と

enter image description here

+0

ありがとうございます。非常に役に立ちます。私の場合はhtmlファイルが大きいです。テーブルがたくさんありますが、2つのテーブルだけが縦書きのテキストを必要とします。自分のコードの残りの部分にどのように実装するのだろうか。私は前にこれをしました: 'using(var myCss = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(example_css))) { using(var msHtml = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(example_html) ))))) {iTextSharp.tool.xml.XMLWorkerHelper.GetInstance()。ParseXHtml(writer、doc、msHtml、myCss); } } ' – Daniel

+0

@ダニエル - あなたが 'HTML'文字列と' CSS'文字列を渡すことを許可するヘルパーメソッドを含むように答えを更新しました。 – kuujinbo

+0

もう一度、ありがとうございました。 – 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); 
} 

オルタナティブ:

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; 
} 
関連する問題