iText 7 PDF可访问性:“表头单元没有关联的子单元” [英] iText 7 PDF accessibility: "Table header cell has no associated subcells"
问题描述
< 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屋!