Проблема создания PDF с соблюдением PDF/UA – PAC Checker сообщает “Тестовый объект не размечен”

Вопрос или проблема

В настоящее время я работаю над созданием PDF-файла, соответствующего стандарту PDF/UA. Моя главная цель — гарантировать, что он отвечает стандартам доступности и проходит проверку с помощью инструмента PAC (PDF Accessibility Checker).

Проблема, с которой я сталкиваюсь, заключается в том, что проверка PAC постоянно указывает на ошибку, сообщая: “Тестовый объект не помечен.” Это указывает на то, что необходимая маркировка может отсутствовать или быть неправильно реализована, но я не уверен, что именно я упускаю, чтобы решить эту проблему.

Я убедился в том, что:

Определил элементы структуры документа
Использовал правильные теги в коде генерации содержимого PDF
Применил то, что, на мой взгляд, является правильными метаданными и настройками для доступности

Тем не менее, похоже, мне все еще не хватает чего-то основополагающего, чтобы маркировка была распознана. Какие шаги я мог бы пропустить, чтобы добиться правильной маркировки в PDF для соответствия PDF/UA?

Буду очень признателен за любые идеи о том, где я мог ошибиться, или советы по критическим элементам маркировки, которые стоит проверить.

Вот мой код.

public void newPdf() {
        int mcidCounter = 0; // Начать с 0
        int structParentCounter = 0; // Начать с 0
        PDDocument document = new PDDocument();
        PDPage page = new PDPage(PDRectangle.A4);
        document.addPage(page);

        // Установка записи StructParents на странице
        page.setStructParents(structParentCounter); // structParentCounter равен 0

        PDPageContentStream contentStream = new PDPageContentStream(document, page);
        PDType0Font font = loadFont(FontEnum.BUNDES_SANS_WEB_REGULAR, document);

        // Добавление шрифта в ресурсы страницы
        PDResources resources = page.getResources();
        if (resources == null) {
            resources = new PDResources();
            page.setResources(resources);
        }
        resources.add(font);

        PDDocumentCatalog catalog = document.getDocumentCatalog();
        PDStructureTreeRoot structureTreeRoot = new PDStructureTreeRoot();
        catalog.setStructureTreeRoot(structureTreeRoot);

        catalog.setLanguage("de-DE"); // Устанавливает язык документа на немецкий

        PDMarkInfo markInfo = new PDMarkInfo();
        markInfo.setMarked(true);
        catalog.setMarkInfo(markInfo);

        // Создание структурного элемента документа
        PDStructureElement documentElement = new PDStructureElement(StandardStructureTypes.DOCUMENT, structureTreeRoot);
        structureTreeRoot.appendKid(documentElement);

        // Создание структурного элемента абзаца
        PDStructureElement paragraphElement = new PDStructureElement(StandardStructureTypes.P, documentElement);
        paragraphElement.setPage(page);
        documentElement.appendKid(paragraphElement);

        // Подготовка содержимого с маркировкой с MCID
        COSDictionary markedContentDictionary = new COSDictionary();
        markedContentDictionary.setInt(COSName.MCID, mcidCounter);

        // Начало маркированного содержимого
        contentStream.beginMarkedContent(COSName.P, PDPropertyList.create(markedContentDictionary));
        contentStream.setFont(font, 12);
        contentStream.beginText();
        contentStream.newLineAtOffset(50, 700);
        contentStream.showText("Hallo Welt");
        contentStream.endText();
        contentStream.endMarkedContent();

        // Закрытие потока содержимого
        contentStream.close();

        // Создание родительского дерева и связывание с структурным элементом
        COSDictionary parentTreeRoot = new COSDictionary();
        PDNumberTreeNode parentTree = new PDNumberTreeNode(parentTreeRoot, COSBase.class);

        // Отображение StructParent на структурный элемент
        Map<Integer, COSObjectable> parentTreeMap = new HashMap<>();
        parentTreeMap.put(structParentCounter, paragraphElement);
        parentTree.setNumbers(parentTreeMap);
        structureTreeRoot.setParentTree(parentTree);

        // Сохранение документа
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        document.save(outputStream);
        byte[] pdfBytes = outputStream.toByteArray();
        document.close();


        Path actualPath = Path.of("src/test/resources/pdf/small_test.pdf");
        Files.write(actualPath, pdfBytes, StandardOpenOption.CREATE, StandardOpenOption.WRITE);
        

    }

А вот что показывает инструмент PAC

Ответ или решение

Для создания PDF-документа, соответствующего стандартам PDF/UA, необходимо обеспечить корректную реализацию структуры и разметки документов. Ошибка, с которой вы столкнулись при использовании инструмента проверки доступности PAC ("Test Object Not Tagged"), указывает на то, что в документе отсутствуют необходимые теги или они реализованы неправильно. Рассмотрим основные аспекты, которые могут помочь в решении проблемы.

1. Убедитесь, что все структурные элементы добавлены правильно

Согласно вашему коду, вы создали элементы структуры для документа и абзаца, однако необходимо удостовериться, что все элементы корректно связаны друг с другом. Важно правильно заполнять родительские и дочерние связи:

  • Проверьте, что вы указали правильные родительские элементы для каждого структурного объекта. Для элемента абзаца необходимо установить его родителем элемент документа, а также заполнить дерево родительских элементов.

2. Правильное использование начальной иконки меток

Использование начальной иконки меток (beginMarkedContent) в вашем коде корректно, но необходимо убедиться, что она действительно ассоциируется с нужным элементом структуры. Это значит, что при создании метки в содержимом страницы необходимо явным образом указать, к какому структурному элементу относится этот текст.

3. Проверка указания языка и метаданных

В вашем коде указано, что вы установили язык документа:

catalog.setLanguage("de-DE");

Убедитесь, что в документ также включены все необходимые метаданные, такие как заголовок, автор и другие важные поля. Это может включать следующее:

  • Создайте и добавьте информацию о метаданных в документ, используя класс PDDocumentInformation.

4. Наличие и корректность используемых шрифтов

Обратите внимание на то, что шрифты должны поддерживать соответствующую символику и форматирование текста, чтобы помочь в доступности документа. Убедитесь, что шрифты включены в документ правильно.

5. Проверьте правильность потоков и закрытие ресурсов

Ваш код выглядит корректным в плане создания контента, но важно также убедиться, что каждый поток данных (например, PDPageContentStream) закрывается после окончания работы. Это позволит избежать возможных утечек памяти и ошибок в структуре документа.

6. Сборка и тестирование

После внесения всех изменений, скомпилируйте документ и повторно протестируйте его с помощью PAC Checker. Особое внимание следует уделить следованию процессам создания структуры и добавления всех необходимых тегов и элементов.

Пример улучшенного кода

Вот как можно изменить ваш существующий код для более явного указания структурных связей:

PDStructureElement bodyElement = new PDStructureElement(StandardStructureTypes.BODY, documentElement);
documentElement.appendKid(bodyElement);

// Создание структурного элемента для абзаца
PDStructureElement paragraphElement = new PDStructureElement(StandardStructureTypes.P, bodyElement);
bodyElement.appendKid(paragraphElement);

Убедитесь, что для каждого элемента структуры создается связи, чтобы PAC Checker мог распознать их корректным образом.

Заключение

Следуйте приведенным рекомендациям, и у вас будет больше шансов устранить ошибку "Test Object Not Tagged". Соблюдайте все стандарты доступности, чтобы ваш PDF-документ соответствовал требованиям PDF/UA. Важно помнить, что создание доступного контента требует внимания к деталям и знания всех аспектов управления структурой документа. Удачи в ваших усилиях!

Оцените материал
Добавить комментарий

Капча загружается...