Перейти к содержимому

Создание дерева структуры тегированного PDF/UA-2 на основе семантического содержимого

Этот рецепт создаёт тегированный файл Portable Document Format/Universal Accessibility 2 (PDF/UA-2) с учётом стандарта International Organization for Standardization (ISO) 14289-2. NextPDF создаёт дерево логической структуры, последовательности маркированного содержимого, язык каталога и идентификационные метаданные на уровне документа. Эта структура поддерживает доступное представление, но решение о соответствии выносит независимое средство проверки. Рецепт соответствует examples/31-pdfua2-tagged.php.

Окно терминала
composer require nextpdf/core:^3

Поместите средство проверки PDF/UA-2 в PATH для верификации. В этом рецепте используется veraPDF с профилем ua2. Для создания тегированной структуры пакет Pro или Enterprise не нужен.

Тегированный PDF содержит параллельное дерево логической структуры наряду с потоком визуального содержимого. Вспомогательные технологии читают это дерево, а не пиксельный макет, поэтому именно структура задаёт внешний порядок чтения. ISO 14289-2 устанавливает для этого четыре требования. Реальное (не артефактное) содержимое должно быть достижимо через это дерево (§8.2.2). Элементы структуры должны быть вложены в определённом порядке (§8.2.3). Каждый элемент должен разрешаться в известное пространство имён структуры — напрямую или через сопоставление ролей (§8.2.4). Естественный язык содержимого объявляется на уровне документа и уточняется для каждого элемента структуры, где он отличается (§8.4.4).

NextPDF моделирует это через типизированный ConformanceMode. enableTaggedPdf() задаёт ConformanceMode::PdfUa2, что (a) заставляет конвейер Hypertext Markup Language (HTML) подключить TaggedContentEmitter при создании парсера, (b) устанавливает в каталоге флаг MarkInfoMarked, сигнализирующий о тегированном PDF (ISO 32000-2 §14.7), и (c) записывает языковой тег Best Current Practice 47 (BCP-47) в запись каталога Lang. Кроме того, модуль записи создаёт для каждой страницы запись Tabs, чтобы порядок обхода по табуляции следовал порядку структуры (ISO 32000-2 §14.8).

Строгие инварианты UA-2 применяются только к ConformanceMode::PdfUa2. По замыслу создание строгой ConformancePolicy для любого другого режима выбрасывает InvalidConfigException.

Поверхность application programming interface (API) формируется по PHPDoc. Используйте следующие основные точки входа:

  • \NextPDF\Core\Document::createStandalone(): Document
  • Document::enableTaggedPdf(string $lang = 'en', ?ConformancePolicy $policy = null): static
  • Document::setLanguage(string $lang): static
  • \NextPDF\Conformance\ConformancePolicy::strictUa2(): self
  • \NextPDF\Conformance\ConformanceMode::PdfUa2 (режим, задаваемый enableTaggedPdf())
  • Document::beginTag(string $type): static / Document::endTag(): static (ручное тегирование для содержимого, отличного от HTML)
examples/31-pdfua2-tagged.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
// Enable tagged mode BEFORE writeHtml(). The HTML pipeline detects the
// mode at parser construction time and wires the tagged-content emitter.
$doc->enableTaggedPdf(lang: 'en');
$doc->setTitle('Quarterly Accessibility Report');
$doc->setLanguage('en');
$doc->addPage();
$doc->writeHtml(<<<'HTML'
<h1>Quarterly Accessibility Report</h1>
<p>This document opts into tagged PDF so assistive technology can expose
a meaningful reading order.</p>
<ul>
<li>Headings carry semantic roles.</li>
<li>Lists keep their item structure.</li>
</ul>
HTML);
$doc->save(__DIR__ . '/output/31-pdfua2-tagged.pdf');
echo "Created: output/31-pdfua2-tagged.pdf\n";

Эта самодостаточная программа может выполняться в тестовой среде. В продакшене лучше сразу завершаться с ошибкой при некорректном языковом теге, а не обнаруживать его только при запуске внешнего средства проверки. Передайте ConformancePolicy::strictUa2(), чтобы отклонить недопустимый тег BCP-47 на границе API, а затем поставьте сборку в зависимость от вердикта средства проверки.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Conformance\ConformancePolicy;
use NextPDF\Core\Document;
use NextPDF\Exception\InvalidConfigException;
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT') ?: (__DIR__ . '/accessible.pdf');
try {
$doc = Document::createStandalone();
// Strict UA-2: a malformed BCP 47 tag throws here, not silently at
// write time. strictUa2() also forces the §8.4.4 Lang validation.
$doc->enableTaggedPdf(lang: 'en-GB', policy: ConformancePolicy::strictUa2());
$doc->setTitle('Accessible Annual Report 2026');
$doc->setLanguage('en-GB');
$doc->addPage();
$doc->writeHtml(<<<'HTML'
<h1>Annual Report 2026</h1>
<p>Audited results for the financial year ending March 2026.</p>
<h2>Segment performance</h2>
<table>
<tr><th>Segment</th><th>Revenue</th></tr>
<tr><td>Cloud</td><td>42.1</td></tr>
<tr><td>Services</td><td>18.7</td></tr>
</table>
HTML);
$doc->save($out);
} catch (InvalidConfigException $e) {
fwrite(STDERR, "Tagged PDF/UA-2 setup rejected: {$e->getMessage()}\n");
exit(1);
}
// The gate is the checker, not the library.
$exitCode = 0;
$report = [];
exec('verapdf --flavour ua2 ' . escapeshellarg($out), $report, $exitCode);
if ($exitCode !== 0) {
fwrite(STDERR, "veraPDF FAILED — output is not PDF/UA-2 conforming\n");
fwrite(STDERR, implode("\n", $report) . "\n");
exit(1);
}
echo "veraPDF PASS — accessible.pdf carries a conforming UA-2 structure\n";

На хосте, где verapdf --flavour ua2 сообщает о соответствии файла, ожидаемый стандартный вывод (STDOUT) выглядит так:

veraPDF PASS — accessible.pdf carries a conforming UA-2 structure

Если enableTaggedPdf() отклоняет языковой тег, программа завершается с ненулевым кодом после Tagged PDF/UA-2 setup rejected: … в стандартном потоке ошибок (STDERR). Если средство проверки сообщает о проблеме, программа завершается с ненулевым кодом после veraPDF FAILED — output is not PDF/UA-2 conforming. Вердикт выносит средство проверки: NextPDF создаёт структуру, но не заявляет соответствие.

  • Порядок вызовов. enableTaggedPdf() после writeHtml() не тегирует задним числом уже записанное содержимое. Сначала включайте режим тегирования.
  • Строгий контроль языка. Без политики некорректный тег BCP-47 молча отбрасывается и проявляется только на этапе проверки. С ConformancePolicy::strictUa2() тот же тег выбрасывает InvalidConfigException на границе enableTaggedPdf() (ISO 14289-2 §8.4.4, строгий путь).
  • Идемпотентное повторное включение. Если вызвать enableTaggedPdf() дважды, NextPDF обновляет язык, не перестраивая уже заполненное дерево структуры.
  • Ручное тегирование. Для содержимого, отличного от HTML, оборачивайте элементы в beginTag() / endTag(). Роли-контейнеры (Table, TR, L, LI) становятся группирующими элементами без маркированного содержимого. Листовые роли (P, H1H6, TD) получают идентификаторы маркированного содержимого (MCID).
  • Взаимоисключение режимов. Строгая ConformancePolicy допустима только с ConformanceMode::PdfUa2. Сочетание строгих флагов UA-2 с режимом PDF/A выбрасывает InvalidConfigException. Чтобы создать тегированный результат PDF/A, включайте режим тегирования и профиль PDF/A по отдельности.

Дерево структуры добавляет одно параллельное дерево лёгких словарей и операторы BDC/EMC для каждого фрагмента текста. Для типичного отчёта эти накладные расходы составляют несколько процентов от размера вывода и остаются в пределах бюджета 2000 мс / 128 МБ. Применяется профиль семантической воспроизводимости, поскольку результат, ориентированный на средство проверки, сравнивается по структурному абстрактному синтаксическому дереву (AST) и метаданным, а не по сырым байтам. См. раздел “Соответствие”.

Размещение данных и меры по защите персональных данных

Заголовок раздела «Размещение данных и меры по защите персональных данных»

Дерево структуры содержит тот же текст, что и видимое содержимое. Если исходный HTML содержит персональные данные, включая персонально идентифицируемую информацию (PII), эти данные также доступны через дерево и через атрибуты ActualText/Alt. Применяйте то же редактирование и минимизацию перед оформлением, что и для видимого содержимого. Тегирование не добавляет нового канала утечки, но по замыслу делает текст программно извлекаемым.

Безопасная телеметрия и очистка журналов

Заголовок раздела «Безопасная телеметрия и очистка журналов»

Рецепт выводит в STDOUT только фиксированную строку состояния. Он направляет PDF во внешний путь тестовой среды (NEXTPDF_COOKBOOK_OUTPUT) или по пути, заданному вызывающей стороной. Текст документа никогда не записывается в журнал. Держите вывод средства проверки, который может содержать фрагменты содержимого, вне общих журналов.

Тегированный PDF не является границей доверия. Если ваш потребитель доверяет дереву структуры при автоматической обработке, он всё равно должен проверять файл, поскольку злоумышленный производитель может создать структурно корректное, но вводящее в заблуждение дерево. Рассматривайте структуру как средство обеспечения доступности, а не как сигнал целостности или подлинности.

Этот рецепт не выполняет криптографических операций. Режим Federal Information Processing Standards (FIPS) не меняет его поведение. Подписание и шифрование не задействованы.

Требование PDF/UA-2Что создаёт NextPDFРаздел
Реальное содержимое находится в дереве структурыStructTreeRoot с StructElem для каждого блока и маркированным содержимым, связанным через MCIDISO 14289-2 §8.2.2
Определённое вложение и порядок чтенияБлочные элементы сопоставлены с grouping/leaf-ролями в порядке документаISO 14289-2 §8.2.3
Известное пространство имён структурыРоли в пространстве имён PDF 2.0; теги HTML сопоставлены с ролями там, где это нужноISO 14289-2 §8.2.4
Язык документа и элементаКаталог Lang из тега BCP-47; Lang для каждого элемента, где он отличаетсяISO 14289-2 §8.4.4
Нетекстовое содержимое имеет текстовую альтернативуAlt/ActualText на элементах структуры figure/non-textISO 14289-2 §8.5.1
Связи таблицыTable/TR/TH/TD-роли со связью заголовковISO 14289-2 §8.2.5.26
Метаданные идентификации частиИдентификация на уровне документа, запланированная при сохраненииISO 14289-2 §Введение (pdfua2#p17)

PDF/UA-2 надстраивает требования доступности над механизмом тегированного PDF из ISO 32000-2. NextPDF опирается на это сопоставление:

Что эмитирует NextPDFМеханизм ISO 32000-2 §14Раздел
Дерево логической структуры (StructTreeRoot)Логическая структура тегированного PDF§14.7 (iso32000_2_sec14#x1.x38.p13)
Каталог MarkInfo << /Marked true >>Маркер тегированного PDF§14.7 (iso32000_2_sec14#x1.x40.p3)
Запись Tabs для каждой страницы, которая следует порядку структурыСтруктурная навигация / порядок табуляции§14.8 (iso32000_2_sec14#x1.x50)

PDF/UA-2 выражает в формате PDF требования к структуре, которые Web Content Accessibility Guidelines (WCAG) 2.2 формулирует независимо от формата. Соответствующее сопоставление:

Критерий успеха WCAG 2.2Механизм PDF/UA-2, который создаёт этот рецепт
1.3.1 Информация и взаимосвязи (уровень A)Дерево структуры делает заголовки, списки и связи таблиц программно определяемыми (wcag_2_2#x2.x3.x3.x1.p3).
1.3.2 Осмысленная последовательность (уровень A)Порядок структуры определяет порядок чтения независимо от визуального макета.
3.1.1 Язык страницы (уровень A)Запись каталога Lang из тега BCP-47.
1.1.1 Нетекстовое содержимое (уровень A)Alt/ActualText на нетекстовых элементах структуры (ISO 14289-2 §8.5.1).

Это сопоставление показывает, какие критерии WCAG 2.2 поддерживает созданная структура. Оно не является заявлением о соответствии WCAG. Соответствие WCAG охватывает весь пользовательский опыт, и его определяет оценка доступности, а не производитель.

УтверждениеСтандартРазделreference_id (идентификатор ссылки)
Реальное содержимое требует логической структуры.ISO 14289-2§8.2.2
Элементы структуры следуют определённому вложению и порядку чтения.ISO 14289-2§8.2.3
Каждый элемент структуры разрешается в известное пространство имён — напрямую или через сопоставление ролей.ISO 14289-2§8.2.4
Естественный язык объявляется на уровне документа и элемента структуры.ISO 14289-2§8.4.4
Нетекстовое содержимое несёт текстовую альтернативу.ISO 14289-2§8.5.1
Ячейки таблицы содержат связи row/header/data.ISO 14289-2§8.2.5.26
Маркером тегированного PDF является флаг каталога MarkInfoMarked.ISO 32000-2§14.7
Соответствие определяется по части стандарта, а не утверждается производителем.ISO 14289-2§8.14.2

NextPDF создаёт тегированную структуру, которая поддерживает доступное представление. Поддержка — это не соответствие. Этот рецепт не заявляет соответствие PDF/UA-2. Его определяет независимое средство проверки, например veraPDF. Запускайте средство проверки, прежде чем заявлять, что файл соответствует.