Доступность iText 7 PDF: ячейка заголовка таблицы не имеет связанных подячеек

Я конвертирую HTML в PDF с помощью iText 7. Мне нужно, чтобы 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);
    }
}

person Tamer Rifai    schedule 13.02.2018    source источник
comment
Является ли AcessibilityTagWorkerFactory из в этом примере? Я не уверен, какое средство проверки соответствия вы используете, чтобы увидеть ошибку, но simplay средства проверки соответствия Acrobat заявляет, что заголовки завершаются ошибкой, если используется TableHeaderTagWorker (ссылка в классе, использованном выше), а не ThTagWorker по умолчанию.   -  person Jon Reilly    schedule 14.02.2018
comment
Привет @JonReilly, спасибо за ваш ответ. Я отредактировал вопрос с помощью AccessibilityTagWorkerFactory. Краткий ответ заключается в том, что он смоделирован на основе этого примера, но не выполняет никакой специальной работы с тегами TH. Если ThTagWorker будет использоваться по умолчанию, то у меня не должно возникнуть проблем, верно? Я использую PAC 3 для проверки доступности: access-for-all.ch/en/pdf-lab/pdf-accessibility-checker-pac.html, но использовал другие тесты с теми же результатами, включая проверку тегов самостоятельно в Acrobat Pro. Теги TH не имеют идентификаторов, а теги TD не связаны с идентификаторами TH.   -  person Tamer Rifai    schedule 15.02.2018


Ответы (1)


После работы с Джоном Рейли в команде iText это было окончательное решение, которое сработало для меня (идентификаторы столбцов и связанные заголовки не нужны... просто 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);
    }
}
person Tamer Rifai    schedule 01.03.2018
comment
Как указано в автономном режиме, следующая версия pdfHtml (2.0.2) будет поддерживать атрибут области для тегов ‹TH›, как того требуют стандарты PDF/UA. Если кто-то увидит это до официального выпуска версии 2.0.2, у нас есть сборка SNAPSHOT, доступная здесь: repo.itextsupport.com/webapp/#/artifacts/browse/simple/General/ - person Jon Reilly; 06.03.2018