iText 7 PDF 可访问性:“表格标题单元格没有关联的子单元格”

Posted

技术标签:

【中文标题】iText 7 PDF 可访问性:“表格标题单元格没有关联的子单元格”【英文标题】:iText 7 PDF accessibility: "Table header cell has no associated subcells" 【发布时间】:2018-07-24 02:17:40 【问题描述】:

我正在使用 iText 7 将 html 转换为 PDF。我需要 PDF 可访问(508 符合适当的标签等),但是,无论我在表格上放置什么标记,可访问性检查器都会给出相同的错误: “表格标题单元格没有关联的子单元格”。我试过设置范围、标题等......似乎没有任何效果。这是其中一个表的示例,但它们都有相同的问题:

 <table class="problems" summary="Patient's diagnosed problems and associated ICD codes.">
        <thead>
            <tr>
                <th scope="col" id="problem-header">
                    Problem
                </th>
                <th scope="col" id="icd-code-header">
                    Code
                </th>
            </tr>
        </thead>
        <tbody>
            <tr>
              <td headers="problem-header">Some Problem</td>
              <td headers="icd-code-header">Some ICD Code</td>
            </tr>
        </tbody>
    </table>

任何帮助将不胜感激。非常感谢。

编辑:我忘了提,我使用的是 .NET 版本的 iText 7。

编辑 2:这是将 HTML 转换为 PDF 的代码:

public class AccessiblePdfService : IAccessiblePdfService

    private static readonly string[] FontPaths = ConfigurationManager.AppSettings["FontPaths"].Split(new char[]  ';' , StringSplitOptions.RemoveEmptyEntries);

    public void createPdf(string html, string dest, PdfTypes type = PdfTypes.RefDoc) //string resources
    

        FileStream outputStream = new FileStream(dest, FileMode.Create, FileAccess.Write);

        WriterProperties writerProperties = new WriterProperties();

        //Add metadata
        writerProperties.AddXmpMetadata();

        PdfWriter pdfWriter = new PdfWriter(outputStream, writerProperties);

        PdfDocument pdfDoc = new PdfDocument(pdfWriter);
        pdfDoc.GetCatalog().SetLang(new PdfString("en-US"));
        //Set the document to be tagged
        pdfDoc.SetTagged();
        pdfDoc.GetCatalog().SetViewerPreferences(new PdfViewerPreferences().SetDisplayDocTitle(true));

        //Set meta tags
        PdfDocumentInfo pdfMetaData = pdfDoc.GetDocumentInfo();
        pdfMetaData.SetAuthor("SOME STRING");
        pdfMetaData.AddCreationDate();
        pdfMetaData.GetProducer();
        pdfMetaData.SetCreator("SOME STRING");


        switch (type)
        
            case PdfTypes.RefDoc:
                pdfMetaData.SetKeywords("SOME STRING");
                pdfMetaData.SetSubject("SOME STRING");
                break;
            case PdfTypes.PatientRoi:
                pdfMetaData.SetKeywords("SOME STRING");
                pdfMetaData.SetSubject("SOME STRING");
                break;
            case PdfTypes.RoiAdmin:
                pdfMetaData.SetKeywords("SOME STRING");
                pdfMetaData.SetSubject("SOME STRING");
                break;
            default:
                break;
        
        //Title is derived from html

        // pdf conversion
        ConverterProperties props = new ConverterProperties();
        FontProvider fp = new FontProvider();
        fp.AddStandardPdfFonts();
        foreach (var path in FontPaths)
        
            fp.AddFont(path);
                    

        props.SetFontProvider(fp);

        DefaultTagWorkerFactory tagWorkerFactory = new AccessibilityTagWorkerFactory();
        props.SetTagWorkerFactory(tagWorkerFactory);

        HtmlConverter.ConvertToPdf(html, pdfDoc, props);
        pdfDoc.Close();

    

编辑 3: 这是 AccessibilityTagWorkerFactory (请记住,我想像表一样工作的表没有用“make-table-div”类标记,并且不应该受到此类自定义的影响:

public class AccessibilityTagWorkerFactory : DefaultTagWorkerFactory

public override ITagWorker GetCustomTagWorker(IElementNode tag, ProcessorContext context)
    
        bool hasClass = false;
        foreach (var attribute in tag.GetAttributes())
        
            if (attribute.GetKey() == "class")
            
                hasClass = true;
            
        
        if (hasClass && tag.GetAttribute(AttributeConstants.CLASS).Contains("make-h1"))
        
            return new HRoleSpanTagWorker(tag, context, StandardRoles.H1);
        
        if (hasClass && tag.GetAttribute(AttributeConstants.CLASS).Contains("make-h2"))
        
            return new HRoleSpanTagWorker(tag, context, StandardRoles.H2);
        
        if (hasClass && tag.GetAttribute(AttributeConstants.CLASS).Contains("make-table-div"))
        
            return new DivRoleTableTagWorker(tag, context);
        
        return base.GetCustomTagWorker(tag, context);
    

【问题讨论】:

AcessibilityTagWorkerFactory 是否来自this example?我不确定您使用哪个合规检查器来查看错误,但如果使用 TableHeaderTagWorker(上面使用的类中的链接)而不是默认的 ThTagWorker,Acrobat 的合规检查器 simplay 会显示“标题”失败。跨度> 嗨@JonReilly,感谢您的回复。我用 AccessibilityTagWorkerFactory 编辑了这个问题。简短的回答是它是根据该示例建模的,但它没有使用 TH 标签进行任何自定义工作。如果默认使用 ThTagWorker,那么我应该没有问题,对吧?我正在使用 PAC 3 来检查可访问性:access-for-all.ch/en/pdf-lab/pdf-accessibility-checker-pac.html,但我使用了具有相同结果的其他测试,包括我自己在 Acrobat Pro 中检查标签。 TH 标签没有 ID,TD 标签不与 TH ID 关联。 【参考方案1】:

在与 iText 团队的 Jon Reilly 合作后,这是对我有用的最终解决方案(不需要列 ID 和关联的标题......只需 Scope)

public class ThWithScopeTagWorker : ThTagWorker

    public ThWithScopeTagWorker(IElementNode element, ProcessorContext context) : base(element, context)
    
    

    public override void ProcessEnd(IElementNode element, ProcessorContext context)
    
        base.ProcessEnd(element, context);
        IPropertyContainer elementResult = base.GetElementResult();
        if (elementResult is IAccessibleElement)
        
            ((IAccessibleElement)elementResult).GetAccessibilityProperties().SetRole(StandardRoles.TH);

            //Can use this in the future in case we have th elements with different scope than "col"
            string htmlScope = element.GetAttribute("scope"); //This is the scope="XXX" in your HTML

            AccessibilityProperties properties = ((IAccessibleElement)elementResult).GetAccessibilityProperties();
            //Could add "Row" if needed based on htmlScope string above. 
            //For my purposes, all th elements were scope="col"
            properties.AddAttributes(new PdfStructureAttributes("Table").AddEnumAttribute("Scope", "Column"));
        
    


还有这个:

public class AccessibilityTagWorkerFactory : DefaultTagWorkerFactory

    public override ITagWorker GetCustomTagWorker(IElementNode tag, ProcessorContext context)
        
         //...        
        if (tag.Name() == "th")
        
            return new ThWithScopeTagWorker(tag, context);
        
        return base.GetCustomTagWorker(tag, context);
    

【讨论】:

如脱机所述,pdfHtml (2.0.2) 的下一版本将支持 PDF/UA 标准要求的 标签的范围属性。如果有人在 2.0.2 正式发布之前看到这个,我们在这里提供了一个 SNAPSHOT 版本:repo.itextsupport.com/webapp/#/artifacts/browse/simple/General/…

以上是关于iText 7 PDF 可访问性:“表格标题单元格没有关联的子单元格”的主要内容,如果未能解决你的问题,请参考以下文章

使用 iText 7 和 C# 在可访问的 pdf 中将标题添加为 H1

使用 iTextSharp 添加水印文本时,PAC 工具中出现 iText 7 警告

如何从iText 7中的PDF格式的轮廓/书签访问矩形,拟合类型,缩放,页码

有用过itext 7生成PDF的大佬吗

如何在 iText 7 中设置 Tab 键顺序?

使用 iText 提取文本不起作用:编码或加密文本?