Boluc Papuccuoglu
Boluc Papuccuoglu

Reputation: 2346

iText using XMLWorker to keep the whole of a table in one page

Basically, what I am trying to do is achieve what the OP of this question wants:

iText avoid to cut tables on page jump

However, at the moment I am generating a XHTML document and using XMLWorker (the iTextSharp version) to parse that document to generate my content. How can I set the KeepRowsTogether flag of the table object being produced by the XmlWorker.Parse method?

Upvotes: 2

Views: 2469

Answers (1)

Boluc Papuccuoglu
Boluc Papuccuoglu

Reputation: 2346

OK, figured it out. Basically I derived a TagProcessor from the iTextSharp.tool.xml.html.table.Table and overrode the End method so that it checks whether the tag has a keeprowstogether attribute and if it does, iterates through the base class's output and invokes the KeepRowsTogether method of the PdfPTable object:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using iTextSharp.tool.xml.html;
using iTextSharp.tool.xml.html.table;
using iTextSharp.text.pdf;

namespace MySolution
{
    public class TableHtmlTagProcessor : Table
    {
        public override IList<iTextSharp.text.IElement> End(iTextSharp.tool.xml.IWorkerContext ctx, iTextSharp.tool.xml.Tag tag, IList<iTextSharp.text.IElement> currentContent)
        {
            string keeprowstogetherattr = "keeprowstogether";
            var retval = base.End(ctx, tag, currentContent);
            if (tag.Attributes.ContainsKey(keeprowstogetherattr) && tag.Attributes[keeprowstogetherattr] == "true")
            {
                foreach (PdfPTable table in retval.OfType<PdfPTable>())
                {
                    table.KeepRowsTogether(0);
                }
            }
            return retval;
        }
    }
}

then, before parsing I add this processor to the TagProcessorFactory so that it processes table tags instead of the default implementation:

HtmlPipelineContext htmlContext = new HtmlPipelineContext(null);
var tagProcessorFactory = Tags.GetHtmlTagProcessorFactory();
tagProcessorFactory.AddProcessor(new TableHtmlTagProcessor(), new[] { "table" });
htmlContext.SetTagFactory(tagProcessorFactory);

and voila! all the table elements in the source XHTML which have keeprowstogether attribute set to "true" are not broken across pages!

Is this overkill? Is there a simpler method to achieve that effect?

Upvotes: 4

Related Questions