如何在iText7中将表头单元格标记为TH而不是TD?

时间:2017-09-01 07:55:17

标签: itext7

我需要在iText7中创建符合PDF / UA标准的文档。最重要的要求是标记所有内容。启用标记时(通过调用PdfDocument.SetTagged()方法),添加到文档中的大多数元素都会获得正确的标记。

问题在于标记表头单元格。根据ISO 32000-1:2008,表格标题单元格必须标记为TH,表格数据单元格必须标记为TD( 14.8.4.2.4。表格元素,表337)。

iText允许使用Table.AddHeaderCell()Table.AddCell()方法区分标题单元格和常规单元格。此机制为行组正确创建THead和TBody标记。不幸的是,细胞本身总是标记为TD。

以下是生成表格的示例代码:

//var pdfDoc = new PdfDocument(...)

pdfDoc.SetTagged();

var doc = new Document(pdfDoc);

var table = new Table(2);
table.AddHeaderCell("Header 0");
table.AddHeaderCell("Header 1");
table.AddCell("Data 0");
table.AddCell("Data 1");

doc.Add(table);
doc.Close();

以下是我们获得的标记结构示例:

<Table>
    <THead>
        <TR>
            <TD>              //must be TH!
                <P>
                    "Header 0"
            <TD>
                <P>
                    "Header 1"
    <TBody>
        <TR>
            <TD>              //TD is correct here
                <P>
                    "Data 0"
            <TD>
                <P>
                    "Data 1"

使用AddHeaderCell()方法时,是否可以让iText生成TH标签?

我正在使用iText 7.0.0 for .NET(社区版)

2 个答案:

答案 0 :(得分:4)

编辑:在pdfHTML的背景下错误地给出了初步答案,而不是正确的iText7。

被标记为TD的TH标签是当前实现的副作用,其以与TD相同的方式处理TH。

适用于iText7

在将标题单元格添加到表格之前,将标题单元格的角色设置为TH:

cell.setRole(PdfName.TH);

对于pdfHTML

虽然可以在转换后访问元素并将其添加到文档之前,但您需要遍历iText元素的树以查找和识别表及其标题 - 单元格。使用CustomTagWorker覆盖标记的转换行为更容易。以下代码取自the accessibility example。有关自定义标记工作者的入门读物,请查看configuration blog-post

首先创建一个继承自TdTagWorker的自定义标记工具,但在返回元素结果之前覆盖该角色:

public class TableHeaderTagWorker extends TdTagWorker {
    public TableHeaderTagWorker(IElementNode element, ProcessorContext context) {
        super(element, context);
    }

    @Override
    public IPropertyContainer getElementResult() {
        Cell cell =(Cell) super.getElementResult();
        cell.setRole(PdfName.TH);
        return super.getElementResult();
    }
}

创建CustomTagWorkerFactory,将此TagWorker映射到TH - 代码

public class AccessibilityTagWorkerFactory extends DefaultTagWorkerFactory {

    @Override
    public ITagWorker getCustomTagWorker(IElementNode tag, ProcessorContext context) {
        //This can probably replaced with a regex or string pattern
        if(tag.name().equals("h1")){
            return new HeaderTagWorker(tag, context,1);
        }
        if(tag.name().equals("h2")){
            return new HeaderTagWorker(tag, context,2);
        }
        if(tag.name().equals("h3")){
            return new HeaderTagWorker(tag, context,3);
        }
        if(tag.name().equals("h4")){
            return new HeaderTagWorker(tag, context,4);
        }
        if(tag.name().equals("h5")){
            return new HeaderTagWorker(tag, context,5);
        }
        if(tag.name().equals("h6")){
            return new HeaderTagWorker(tag, context,6);
        }

        if(tag.name().equals("th")){
            return new TableHeaderTagWorker(tag,context);
        }

        return null;
    }
}

并将ConvertorProperties设置为使用此自定义工厂:

ConverterProperties props = new ConverterProperties();
DefaultTagWorkerFactory tagWorkerFactory = new AccessibilityTagWorkerFactory();
props.setTagWorkerFactory(tagWorkerFactory);
HtmlConverter.convertToPdf(new FileInputStream(src), pdfDoc, props);
pdfDoc.close();

答案 1 :(得分:1)

请注意,iText 7.1对此进行了更改。您不再可以直接调用setRole()函数,而必须通过Accessibility Properties。此外,可访问性属性中的setRole()函数仅接受一个字符串。所以现在是:

cell.getAccessibilityProperties().setRole(PdfName.TH.toString());