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

How to tag table header cells as TH instead of TD in iText7?

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

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

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

这里是生成 table:

的示例代码
//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(社区版)

编辑:最初的答案是在 pdfHTML 的上下文中错误给出的,而不是 iText7 本身。

被标记为 TD 的 TH 标签是当前实现的 side-effect,它以与 TD 相同的方式对待 TH。

对于 iText7

在将 header-cells 添加到 table 之前将 header-cells 的角色设置为 TH:

cell.setRole(PdfName.TH);

对于 pdfHTML

虽然可以在转换后和将它们添加到文档之前访问元素,但您需要遍历 iText 元素树以查找和识别 table 及其 header -细胞。使用 CustomTagWorker 覆盖标签的转换行为更容易。以下代码摘自the accessibility example. For a primer on custom tagworkers, have a look at the configuration blog-post.

首先创建一个继承自 TdTagWorker 的自定义 tagworker,但在返回 element-result 之前覆盖该角色:

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

请注意,iText 7.1 已经改变了这一点。您不能再直接调用 setRole() 函数,您必须通过辅助功能属性。此外,辅助功能属性中的 setRole() 函数仅接受字符串。所以现在,它将是:

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