iText 7 PDF可访问性:"表头单元格没有关联的子单元"

时间:2018-02-13 16:33:13

标签: html pdf-generation accessibility itext7 section508

我正在使用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>

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

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

编辑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(请记住,我想表格的表格没有标记为类,&#34; make-table-div&#34;并且不应该受到自定义的影响这堂课:

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

1 个答案:

答案 0 :(得分:2)

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

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