iText7 / iText7.pdf html - создание доступного тегированного PDF из HTML приводит к неправильному порядку вкладок - PullRequest
1 голос
/ 10 января 2020

Вот фрагмент HTML:

    <html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <style type="text/css">
        body {
            font-family: Calibri,Arial,Tahoma,Helvetica,sans-serif;
            color: black;
            font-size: 12pt;
            width: 595pt;
        }

        h1 {
            color: #553c74;
            font-size: 18pt;
            font-weight: bold;
        }

            h1.title {
                display: inline;
                font-size: 28pt;
                font-weight: bold;
                color: #553c74;
            }

        h2 {
            color: #553c74;
            font-size: 16pt;
            font-weight: bold;
        }

        h3 {
            color: #00759b;
            font-size: 12pt;
            font-weight: bold;
        }

            h3.requiredAction {
                color: black;
                font-weight: bold;
                margin-top: 21px;
            }

        .headingLeft {
            float: left;
        }

        .contentRight {
            float: left;
            margin-left: 10px;
            margin-top: 17px;
        }

        .topSection {
            margin-top: 22px;
        }

        .clearBoth {
            clear: both;
        }

        .symbolstandardmet {
            color: #009639;
            font-family: webdings;
            font-size: 18pt;
        }

        .standardmet {
            color: #009639;
        }

        .standard {
            font-size: 16pt;
            font-weight: bold;
            margin-top: 0;
        }

        .pageBreakBefore {
            margin-top: 0px;
        }

        .premisesAddress {
            font-size: 18pt;
            color: #553c74;
            line-height: 0px;
        }

        .pageBreakBefore {
            page-break-before: always;
        }

        #contentWrapperBody {
            padding-left: 8pt;
            padding-right: 45pt;
        }

        h1 {
            display: inline-block;
        }

        @page:first {
            margin-top: 170pt;
        }
    </style>

    <title>Report</title>

</head>
<body id="contentWrapperBody">
    <h1>Name:</h1>
    <span id="lblAddress" class="premisesAddress">Address Line 1, Address line 2, City, Postcode</span>

    <div class="clearBoth"></div>

    <h2 class="headingLeft">Reference:</h2>
    <div class="contentRight topSection">123456789</div>

    <div class="clearBoth"></div>

    <h2 class="headingLeft">Type:</h2>
    <div class="contentRight topSection">The type</div>

    <div class="clearBoth"></div>

    <h2 class="headingLeft">Date:</h2>
    <div class="contentRight topSection">12/04/2019</div>

    <div class="clearBoth"></div>

    <h2>Context</h2>
    <div>
        <p>A paragraph of context info here.</p>
    </div>


    <h2>Overall outcome</h2>
    <h3>
        <span id="lblOverallStandardsMet" class="standardmet"><span class="symbolstandardmet">a</span>Standards met</span>
    </h3>


    <h3 class="headingLeft requiredAction">Required Action:</h3>
    <div class="contentRight topSection"><span id="lblRequiredAction">None</span></div>
    <div class="clearBoth"></div>
    <p>Follow this link to <a href="#tbldefinitions">find out what the possible outcomes mean</a></p>

</body>
</html>

Вот код:

 public static class DocConverter
{
    private const string fontWebdings = "~/content/fonts/webdings.ttf";
    private const string fontCalibri = "~/content/fonts/calibrib.ttf";

    [Flags]
    public enum DocOptions
    {
        None = 0,
        DisplayTitle = 1,
        AddHeaderPageOne = 2,
        AddHeaderAllPages = 4,
        AddLineBottomEachPage = 8
    }

    public static byte[] ConvertToPdfWithTags(string html, string title, string docOptions)
    {
        DocOptions documentOptions = DocOptions.None;
        if (!string.IsNullOrEmpty(docOptions))
        {
            int options;
            if (int.TryParse(docOptions, out options))
                documentOptions = (DocOptions)options;
        }

        PdfFontFactory.RegisterDirectory(System.Web.Hosting.HostingEnvironment.MapPath("~/content/fonts/"));
        ConverterProperties props = new ConverterProperties();


        FontProvider fp = new FontProvider();

        fp.AddDirectory(System.Web.Hosting.HostingEnvironment.MapPath("~/content/fonts/"));

        props.SetFontProvider(fp);
        props.SetTagWorkerFactory(new DefaultTagWorkerFactory());

        using (var workStream = new MemoryStream())
        {
            using (var pdfWriter = new PdfWriter(workStream, new WriterProperties().AddUAXmpMetadata().SetPdfVersion
                (PdfVersion.PDF_2_0).SetFullCompressionMode(true)))
            {

                PdfDocument pdfDoc = new PdfDocument(pdfWriter);
                pdfDoc.GetCatalog().SetLang(new PdfString("en-GB"));


                pdfDoc.GetCatalog().SetViewerPreferences(new PdfViewerPreferences().SetDisplayDocTitle(true));
        //This event handler used for adding background images.  Also where I've tried setting the tab order on pdfPage
                //if (documentOptions > 0)
                //    pdfDoc.AddEventHandler(PdfDocumentEvent.END_PAGE, new PublicReportHeaderFooter(documentOptions, title));
                //Set meta tags
                var pdfMetaData = pdfDoc.GetDocumentInfo();
                pdfMetaData.AddCreationDate();
                pdfMetaData.GetProducer();
                pdfMetaData.SetCreator("iText Software");
                //Set the document to be tagged
                pdfDoc.SetTagged();

                using (var document = HtmlConverter.ConvertToDocument(html, pdfDoc, props))
                {
                    //Can do more with document here if necessary


                }

                //Returns the written-to MemoryStream containing the PDF.   
                return workStream.ToArray();
            }
        }
    }



}

Если я открою полученный PDF-файл в Acrobat Pro и сделаю отчет о доступности и проверим в порядке чтения он переходит от имени в первой строке к контексту гораздо дальше вниз, а не в верхнем-нижнем, лево-правом порядке: screenshot from acrobat

Похоже, что из-за " стиль float: left на некоторых элементах, но я не уверен, как его обойти. Я пытался поиграть с page.Put (PdfName.Tag, PdfName.S) и page.SetTabOrder (PdfName.S), указав разные параметры (например, C или R), но, похоже, это не имеет значения , Я использую C# iText7 версии 7.1.9 и iText7.pdf html версии 2.1.6. Любая помощь приветствуется.

1 Ответ

0 голосов
/ 15 января 2020

Чем больше я смотрю на документацию, тем больше я думаю, что это просто ошибка. Порядок чтения в доступном PDF-файле должен соответствовать структурному порядку документа HTML по умолчанию, но стили float: left , кажется, отбрасывают вещи. Я не могу найти способ вызвать ошибку в GitHub для этого проекта, но я нашел обходной путь для любого другого с этой проблемой, который заключается в простом добавлении «float: left» ко всем другим элементам по мере необходимости вместе с

<div style="clear: both;"></div>

между элементами, которые на самом деле не нуждаются в поплавке. Таким образом, доступный помеченный ордер получается правильно. Однако это породило еще одну проблему, заключающуюся в том, что элементы с «float: left» больше не появлялись на новой странице, где также был установлен «page-break-before: всегда». Мне пришлось добавить еще один пустой элемент div перед этими элементами со стилем page-break-before, чтобы исправить это. Надеюсь, что люди из iText увидят это и либо исправят эти проблемы, если они будут ошибками, либо ответят лучшим ответом, если я просто что-то не так понял.

...