- Вопрос или проблема
- Ответ или решение
- 1. Убедитесь, что все структурные элементы добавлены правильно
- 2. Правильное использование начальной иконки меток
- 3. Проверка указания языка и метаданных
- 4. Наличие и корректность используемых шрифтов
- 5. Проверьте правильность потоков и закрытие ресурсов
- 6. Сборка и тестирование
- Пример улучшенного кода
- Заключение
Вопрос или проблема
В настоящее время я работаю над созданием 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);
}
Ответ или решение
Для создания 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. Важно помнить, что создание доступного контента требует внимания к деталям и знания всех аспектов управления структурой документа. Удачи в ваших усилиях!