iText 7 PDF可访问性:“表头单元没有关联的子单元” [英] iText 7 PDF accessibility: "Table header cell has no associated subcells"

查看:202
本文介绍了iText 7 PDF可访问性:“表头单元没有关联的子单元”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用iText 7将HTML转换为PDF。我需要PDF来访问(508符合适当的标签等),但是,无论我将哪个标记放在表格上,可访问性检查程序都会给出相同的错误: 表头单元格没有关联的子单元格。我已经尝试设置范围,标题等...似乎没有任何工作。这是一个表格的例子,但它们都有相同的问题:

 < table class =problems summary =患者诊断出的问题和相关的ICD代码。> 
< thead>
< tr>
问题
< / th>
代码
< / th>
< / tr>
< / thead>
< tbody>
< tr>
< td headers =问题标题>一些问题< / td>
< td headers =icd-code-header>某些ICD代码< / 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);
$ b $ public void createPdf(string html,string dest,PdfTypes type = PdfTypes.RefDoc)//字符串资源
{

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

WriterProperties writerProperties = new WriterProperties();

//添加元数据
writerProperties.AddXmpMetadata();

PdfWriter pdfWriter = new PdfWriter(outputStream,writerProperties);

PdfDocument pdfDoc = new PdfDocument(pdfWriter);
pdfDoc.GetCatalog()。SetLang(new PdfString(en-US));
//设置要标记的文档
pdfDoc.SetTagged();
pdfDoc.GetCatalog()。SetViewerPreferences(new PdfViewerPreferences()。SetDisplayDocTitle(true));

//设置元标记
PdfDocumentInfo pdfMetaData = pdfDoc.GetDocumentInfo();
pdfMetaData.SetAuthor(SOMER STRING);
pdfMetaData.AddCreationDate();
pdfMetaData.GetProducer();
pdfMetaData.SetCreator(有些字符串);


switch(type)
{
case PdfTypes.RefDoc:
pdfMetaData.SetKeywords(SOME STRING);
pdfMetaData.SetSubject(有些字符串);
休息;
case PdfTypes.PatientRoi:
pdfMetaData.SetKeywords(SOME STRING);
pdfMetaData.SetSubject(有些字符串);
休息;
case PdfTypes.RoiAdmin:
pdfMetaData.SetKeywords(SOME STRING);
pdfMetaData.SetSubject(有些字符串);
休息;
默认值:
break;
}
//标题来源于html

// pdf转换
ConverterProperties道具= new ConverterProperties();
FontProvider fp = new FontProvider();
fp.AddStandardPdfFonts();
foreach(FontPath中的var路径)
{
fp.AddFont(path);
}

props.SetFontProvider(fp);

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

HtmlConverter.ConvertToPdf(html,pdfDoc,道具);
pdfDoc.Close();


$ b $ / code>

编辑3:
这里是AccessibilityTagWorkerFactory(请记住,我想要像表一样操作的表没有标记类make-table-div,并​​且不应该受此类中的定制影响:

  public class AccessibilityTagWorkerFactory:DefaultTagWorkerFactory 
{
public override ITagWorker GetCustomTagWorker(IElementNode tag,ProcessorContext context)
{
bool hasClass = false;
foreach(tag.GetAttributes()中的var属性)
{
if(attribute.GetKey()==class)
(hasClass&& tag.GetAttribute(AttributeConstants.CLASS).Contains(make-h1))$ b {
hasClass = true;
}
}
$ b {
返回新的HRoleSpanTagWorker(tag,context,StandardRoles.H1);
}
if(hasClass&& tag.GetAttribute(AttributeConstants.CLASS).Contains(make-h2))
{
返回新的HRoleSpanTagWorker(tag,context,StandardRoles.H2);

if(hasClass&& tag.GetAttribute(AttributeConstants.CLASS).Contains(make-table-div))
{
return new DivRoleTableTagWorker(tag ,上下文);
}
返回base.GetCustomTagWorker(tag,context);


$ / code>


解决方案

After与iText团队的Jon Reilly一起工作,这是最终的解决方案,对我来说很有用(不需要列ID和相关联的头文件......只是范围)

  public class ThWithScopeTagWorker:ThTagWorker 
{
public ThWithScopeTagWorker(IElementNode元素,ProcessorContext上下文):base(元素,上下文)
{
}

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

//如果我们有第二个元素的范围不是col,可以在将来使用它
string htmlScope = element.GetAttribute(scope); //这是您的HTML

中的范围=XXXAccessibilityProperties属性=((IAccessibleElement)elementResult).GetAccessibilityProperties();
//如果需要,可以根据上面的htmlScope字符串添加行。
//为了我的目的,所有th元素都是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);
}
返回base.GetCustomTagWorker(tag,context);
}
}


I am converting HTML to a PDF using iText 7. I need the PDF to be accessible (508 compliant with appropriate tags, etc), but, no matter what markup I put on a table, accessibility checkers give the same error: "Table header cell has no associated subcells". I've tried setting scope, headers, etc... nothing seems to work. Here is an example of one of the tables but all of them have the same issue:

 <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>

Any help would be appreciated. Thank you so much.

EDIT: I forgot to mention, I am using the .NET version of iText 7.

EDIT 2: Here is the code that converts the HTML to 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();

    }
}

EDIT 3: Here is the AccessibilityTagWorkerFactory (keep in mind, the tables that I want to act like tables are not marked with the class, "make-table-div" and there shouldn't be affected by the customizations in this class:

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

解决方案

After working with Jon Reilly on the iText team, this was the final solution that worked for me (column IDs and associated headers aren't needed... just 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"));
        }
    }

}

and this:

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

这篇关于iText 7 PDF可访问性:“表头单元没有关联的子单元”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆