【问题标题】:iText 7 need to skip reading page header elementsiText 7 需要跳过阅读页眉元素
【发布时间】:2020-01-03 17:27:52
【问题描述】:

我正在使用 EventHandler 为我的 pdf 创建页眉。标题的内容在添加到 Canvas 之前添加到表中。作为 508 合规性的一部分,我需要排除标头内容被大声读出。我该如何帮凶?

public class TEirHeaderEventHandler : IEventHandler 
{
    public void HandleEvent(Event e)
    {
        PdfDocumentEvent docEvent = (PdfDocumentEvent)e;
        PdfDocument pdf = docEvent.GetDocument();
        PdfPage page = docEvent.GetPage();

        PdfCanvas headerPdfCanvas = new PdfCanvas(page.NewContentStreamBefore(), page.GetResources(), pdf);
        Rectangle headerRect = new Rectangle(60, 725, 495, 96);
        Canvas headerCanvas = new Canvas(headerPdfCanvas, pdf, headerRect);

        //creating content for header
        CreateHeaderContent(headerCanvas);
        headerCanvas.Close();
    }

    private void CreateHeaderContent(Canvas canvas)
    {
        //Create header content
        Table table = new Table(UnitValue.CreatePercentArray(new float[] { 60, 25, 15 } ));
        table.SetWidth(UnitValue.CreatePercentValue(100));

        Cell cell1 = new Cell().Add(new Paragraph("Establishment Inspection Report").SetBold().SetTextAlignment(TextAlignment.LEFT));
        cell1.SetBorder(Border.NO_BORDER);
        table.AddCell(cell1);

        Cell cell2 = new Cell().Add(new Paragraph("FEI Number:").SetBold().SetTextAlignment(TextAlignment.RIGHT));
        cell2.SetBorder(Border.NO_BORDER);
        table.AddCell(cell2);

        Cell cell3 = new Cell().Add(new Paragraph(_feiNum).SetBold().SetTextAlignment(TextAlignment.RIGHT));
        cell3.SetBorder(Border.NO_BORDER);
        table.AddCell(cell3);

        canvas.Add(table);
    }
}

public static void CreatePdf()
{
    using (MemoryStream writeStream = new MemoryStream())
    using (FileStream inputHtmlStream = File.OpenRead(inputHtmlFile))
    {
        PdfDocument pdf = new PdfDocument(new PdfWriter(writeStream));
        pdf.SetTagged();

        iTextDocument document = new iTextDocument(pdf);           

        TEirHeaderEventHandler teirEvent = new TEirHeaderEventHandler();
        pdf.AddEventHandler(PdfDocumentEvent.START_PAGE, teirEvent);


        //Convert html to pdf
        HtmlConverter.ConvertToDocument(inputHtmlStream, pdf, properties);

        document.Close();

        byte[] bytes = TEirReorderingPages(writeStream, numOfPages);

        File.WriteAllBytes(outputPdfFile, bytes);
    }
}

请注意,我已设置要标记的文档。但是当我打开文件时,我仍然会看到“正在阅读未标记的文档”屏幕。但是,当我激活“朗读”功能时,会读取所有内容,包括标题。任何意见或建议将不胜感激。提前感谢您的帮助。

【问题讨论】:

    标签: pdf header itext7 screen-readers section508


    【解决方案1】:

    一般

    Alexey Subach 建议的方法通常是正确的。您将内容标记为人工制品以将其与真实内容区分开来。

    element.getAccessibilityProperties().setRole(StandardRoles.ARTIFACT);
    

    这会标记内容流中的内容,并将元素从结构树中排除。

    你的情况

    但是,您的具体情况更为细微。

    对于一个标记良好的 PDF 文档,正确的朗读方法是处理结构树,它是一种数据结构,表示文档的(语义)元素的逻辑阅读顺序,例如段落,表格和列表。

    由于您创建标题内容的方式,它不会自动标记:从PdfCanvas 实例创建的Canvas 实例默认禁用autotagging。所以标题中的表格没有在内容流中标记,也不包含在结构树中。使用上述常规中描述的方法将其明确标记为工件应该不会产生显着差异,因为它一开始不在结构树中。

    如果您通过添加headerCanvas.enableAutoTagging(page) 启用autotagging,您会注意到该表确实出现在结构树中。

    如果您随后添加table.getAccessibilityProperties().setRole(StandardRoles.ARTIFACT),则该表会再次从结构树中排除。

    总结:看结构树,你原来的代码和General的做法没有区别。

    Adobe 阅读顺序/辅助功能设置

    根据您的描述,我认为您正在使用 Adob​​e Acrobat 或 Reader 来实现大声朗读功能。在Preferences > Reading > Reading Order Options 下,您可以配置如何处理内容以实现朗读功能:

    来自https://helpx.adobe.com/reader/using/accessibility-features.html

    • Infer Reading Order From Document(推荐):通过使用结构推理布局分析的高级方法来解释未标记文档的阅读顺序。
    • 从左到右,从上到下的阅读顺序:根据文本在页面上的位置传递文本,从左到右,然后从上到下阅读。此方法比 Infer Reading Order From Document 更快。此方法仅分析文本;表单字段被忽略,表格也无法被识别。
    • 覆盖标记文档中的阅读顺序:使用阅读首选项中指定的阅读顺序,而不是文档的标记结构指定的阅读顺序。仅当您在标记不佳的 PDF 中遇到问题时才使用此首选项。

    在我的测试中,让 Adob​​e Reader 大声读出使用原始代码创建的标题内容的唯一方法是选择从左到右,从上到下阅读顺序 并启用覆盖标记文档中的阅读顺序。在这种情况下,它基本上忽略了标记,只处理页面上每个位置的内容。

    如果禁用覆盖标记文档中的阅读顺序,则不会读取您的原​​始代码和显式工件的标题内容。

    结论

    虽然总是这样标记工件是个好主意,这样它们可以与真实内容正确区分,但在这种情况下,我相信您遇到的行为与应用程序配置有关,而不是与文件结构有关。

    【讨论】:

      【解决方案2】:

      页眉和页脚通常是分页工件,应按以下方式标记:

      table.getAccessibilityProperties().setRole(StandardRoles.ARTIFACT);
      

      这将使该表不被读取。请注意,您可以将任何实现IAccessibleElement 接口的元素标记为工件。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-25
        • 2023-03-12
        • 1970-01-01
        • 1970-01-01
        • 2015-06-22
        相关资源
        最近更新 更多