wake-up-neo.com

Verwenden Sie itextsharp xmlworker, um HTML in PDF zu konvertieren und Text vertikal zu schreiben

Gibt es in xmlworker die Möglichkeit, Textrichtung von unten nach oben zu schreiben? Ich möchte es gerne in der Tabelle verwenden. Mein Code lautet 

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

Aber es funktioniert nicht nach der Konvertierung von HTML in PDF. Text FIRST und SECOND stehen nicht in der Richtung von unten nach oben.

9
Daniel

Dies war ein ziemlich interessantes Problem, also +1 auf die Frage.

Der erste Schritt bestand darin, herauszufinden, ob iTextSharp XML Worker das Tag HTMLtd unterstützt. Die Zuordnungen finden Sie in der Quelle unter iTextSharp.tool.xml.html.Tags . Dort finden Sie, dass tdiTextSharp.tool.xml.html.table.TableData zugeordnet ist, was die Implementierung eines benutzerdefinierten Tag-Prozessors ein wenig erleichtert. Das heißt alles, was wir tun müssen, um von der Klasse zu erben und End() zu überschreiben:

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

Wie in den Inline-Kommentaren erwähnt, handelt es sich hierbei um eine sehr einfache Implementierung für Ihre spezifischen Anforderungen. Sie müssen zusätzliche Logik hinzufügen, um alle anderen Schreibmodi CSS -Eigenschaftswerte und zu unterstützen schließen Sie alle Vernunftsüberprüfungen ein.

AKTUALISIEREN

Basierend auf dem Kommentar von @ Daniel ist es nicht klar, wie benutzerdefinierte CSS hinzugefügt werden sollen, wenn HTML in PDF konvertiert wird. Zuerst das aktualisierte 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>";

Dann ein kleiner Ausschnitt aus einem benutzerdefinierten 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;}
";

Der etwas schwierige Teil ist das zusätzliche Setup - Sie können nicht das einfache, sofort einsatzbereite XMLWorkerHelper.GetInstance().ParseXHtml() verwenden, das hier bei SO üblich ist. Hier ist eine einfache Hilfsmethode, mit der Sie beginnen sollten:

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

Anstatt eine Erklärung des obigen Beispielcodes erneut aufzubereiten, siehe Dokumentation (Dokumentation mit entferntem iText, verbunden mit Wayback Machine), um eine bessere Vorstellung davon zu erhalten, warum Sie den Parser auf diese Weise einrichten müssen.

Beachten Sie auch:

  1. XML Worker unterstützt nicht alle CSS2/CSS3-Eigenschaften , daher müssen Sie may damit experimentieren, was funktioniert oder was nicht. ' Sie können nicht festlegen, wie genau das PDF) auf den im Browser angezeigten HTML-Code ausgerichtet sein soll.
  2. Das Snippet HTML hat das Tag p entfernt, da der Stil direkt auf das Tag td angewendet werden kann.
  3. Die Inline-Eigenschaft width. Wenn diese Option nicht angegeben wird, sind die Spalten variabel breit und stimmen überein, wenn der Text horizontal gerendert wurde.

Getestet mit iTextSharp und XML Worker Version 5.5.9 Hier ist das aktualisierte Ergebnis:

enter image description here

8
kuujinbo

wie kann ich die Bild-Tags in der Tabelle als PDF nach ihrer Tabellenposition darstellen? - @ kuujinbo

<table cellpadding="30" class="table table-striped" id="StudentInfoListTable">
                        <tr>
                            <td><img src="@Model.img" alt="" height="200" width="200" /></td>
                            <td class="middle"></td>
                            <td>LICENSE ID - @Html.DisplayFor(m => m.LicenseID)</td>
                        </tr>
                        <tr>
                            <td>NAME: </td>
                            <td class="middle"></td>
                            <td>@Html.DisplayFor(m => m.Name)</td>
                        </tr>
                        <tr>
                            <td>@Html.DisplayFor(m => m.Relo) </td>
                            <td class="middle"></td>
                            <td>@Html.DisplayFor(m => m.careOf)</td>
                        </tr>
                        <tr>
                            <td>GENDER: </td>
                            <td class="middle"></td>
                            <td>@Html.DisplayFor(m => m.gender)</td>
                        </tr>
                        <tr>
                            <td>BLOOD GROUP: </td>
                            <td class="middle"></td>
                            <td>@Html.DisplayFor(m => m.blood)</td>
                        </tr>
                        <tr>
                            <td>DATE OF BIRTH: </td>
                            <td class="middle"></td>
                            <td>@Html.DisplayFor(m => m.date)</td>
                        </tr>
                        <tr>
                            <td>CONTACT NO: </td>
                            <td class="middle"></td>
                            <td>@Html.DisplayFor(m => m.Mobile)</td>
                        </tr>
                        <tr>
                            <td>ADDRESS: </td>
                            <td class="middle"></td>
                            <td>@Html.DisplayFor(m => m.Address)</td>
                        </tr>
                        <tr>
                            <td>Signature </td>
                            <td class="middle"></td>
                            <td><img src="@Model.sign" alt="" style="background-color:white;"/></td>
                        </tr>
                    </table>
0
Siddarth Dutta
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);
}

Alternative mit utf8:

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