Émettre une arborescence de structure balisée PDF/UA-2 à partir d'un contenu sémantique
Cette page montre comment produire un PDF balisé visant la norme ISO 14289-2 (PDF/UA-2). NextPDF émet un arbre de structure logique, des séquences de contenu balisé, la langue du catalogue et les métadonnées d’identification au niveau du document. Cette structure facilite la création de documents accessibles, mais c’est un outil de vérification indépendant qui détermine la conformité. Elle s’appuie sur examples/31-pdfua2-tagged.php.
Installation
Section intitulée « Installation »composer require nextpdf/core:^3L’étape de vérification nécessite un outil de vérification PDF/UA-2 dans le PATH. Les exemples de cette page utilisent veraPDF avec la variante ua2. Tu n’as pas besoin d’un package Pro ou Enterprise pour émettre la structure balisée.
Aperçu conceptuel
Section intitulée « Aperçu conceptuel »Un PDF balisé porte un arbre de structure logique parallèle au flux de contenu visuel. Les technologies d’assistance lisent l’arbre, pas la disposition des pixels ; c’est donc la structure qui détermine l’ordre de lecture présenté. ISO 14289-2 pose ici quatre exigences. Le contenu réel (non-artefact) doit être accessible au travers de cet arbre (§8.2.2). Les éléments de structure doivent s’imbriquer dans un ordre défini (§8.2.3). Chaque élément doit se résoudre en un espace de noms de structure connu, directement ou par mappage de rôle (§8.2.4). Enfin, la langue naturelle du contenu est déclarée au niveau du document, puis affinée par élément de structure là où elle diffère (§8.4.4).
NextPDF modélise cela avec un ConformanceMode typé. enableTaggedPdf() définit ConformanceMode::PdfUa2, ce qui (a) conduit le pipeline HTML à câbler un TaggedContentEmitter au moment de la construction du parseur, (b) active l’indicateur de catalogue MarkInfoMarked qui signale un PDF balisé (ISO 32000-2 §14.7), et (c) enregistre la langue BCP-47 pour l’entrée de catalogue Lang. Le writer émet également l’entrée Tabs par page, afin que l’ordre de tabulation suive l’ordre de la structure (ISO 32000-2 §14.8).
Les invariants stricts UA-2 s’appliquent uniquement à ConformanceMode::PdfUa2. Construire une ConformancePolicy stricte pour tout autre mode lève InvalidConfigException, et c’est voulu.
Surface d’API
Section intitulée « Surface d’API »La surface d’API est générée à partir du PHPDoc. Les points d’entrée à retenir :
\NextPDF\Core\Document::createStandalone(): DocumentDocument::enableTaggedPdf(string $lang = 'en', ?ConformancePolicy $policy = null): staticDocument::setLanguage(string $lang): static\NextPDF\Conformance\ConformancePolicy::strictUa2(): self\NextPDF\Conformance\ConformanceMode::PdfUa2(le mode défini parenableTaggedPdf())Document::beginTag(string $type): static/Document::endTag(): static(balisage manuel pour le contenu non-HTML)
Exemple de code — Démarrage rapide
Section intitulée « Exemple de code — Démarrage rapide »<?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 exposea 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";Exemple de code — Production
Section intitulée « Exemple de code — Production »Voici le programme autonome, exécutable par le harnais. En production, l’appelant échoue tôt sur une balise de langue mal formée, au lieu de ne la découvrir qu’au moment d’exécuter l’outil de vérification externe. Passe ConformancePolicy::strictUa2() pour rejeter une balise BCP-47 invalide à la frontière de l’API, puis conditionne le build au verdict de l’outil de vérification.
<?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";STDOUT attendu, sur un hôte où verapdf --flavour ua2 signale le fichier comme conforme :
veraPDF PASS — accessible.pdf carries a conforming UA-2 structureSi enableTaggedPdf() rejette la balise de langue, le programme se termine avec un code non nul après avoir écrit Tagged PDF/UA-2 setup rejected: … sur STDERR. Si l’outil de vérification signale un problème, il se termine avec un code non nul après veraPDF FAILED — output is not PDF/UA-2 conforming. Le verdict revient à l’outil de vérification : NextPDF émet la structure, mais n’affirme pas la conformité.
Cas limites & pièges
Section intitulée « Cas limites & pièges »- Ordre des appels.
enableTaggedPdf()aprèswriteHtml()ne balise pas rétroactivement le contenu déjà écrit. Active d’abord le mode balisé. - Garde-fou strict sur la langue. Sans politique, une balise BCP-47 non analysable est ignorée silencieusement et n’apparaît qu’au moment de l’outil de vérification. Avec
ConformancePolicy::strictUa2(), la même balise lèveInvalidConfigExceptionà la frontière deenableTaggedPdf()(ISO 14289-2 §8.4.4, chemin strict). - Réactivation idempotente. Appeler
enableTaggedPdf()deux fois met à jour la langue sans reconstruire un arbre de structure déjà peuplé. - Balisage manuel. Pour le contenu non-HTML, encadre les éléments avec
beginTag()/endTag(). Les rôles de conteneur (Table,TR,L,LI) deviennent des éléments de regroupement sans contenu balisé. Les rôles feuilles (P,H1–H6,TD) reçoivent des MCID. - Exclusivité des modes. Une
ConformancePolicystricte n’est valide qu’avecConformanceMode::PdfUa2. Combiner des indicateurs stricts UA-2 avec un mode PDF/A lèveInvalidConfigException. Produis un livrable PDF/A balisé en activant le mode balisé et le profil PDF/A séparément.
Performance
Section intitulée « Performance »L’arbre de structure ajoute un arbre parallèle de dictionnaires légers, plus des opérateurs BDC/EMC pour chaque séquence de texte. Pour un rapport classique, le surcoût représente quelques pour cent de la taille de sortie et reste largement dans le budget de 2000 ms / 128 Mo. Le profil de reproductibilité sémantique s’applique ici, car un livrable destiné à un outil de vérification se compare par arbre de syntaxe abstraite (AST) structurel et métadonnées, plutôt que par octets bruts. Voir la section Conformité.
Notes de sécurité
Section intitulée « Notes de sécurité »Résidence des données & atténuations relatives aux PII
Section intitulée « Résidence des données & atténuations relatives aux PII »L’arbre de structure contient le même texte que le contenu visible. Si le HTML source contient des données personnelles, ces données sont aussi accessibles au travers de l’arbre et via les attributs ActualText/Alt. Applique la même expurgation et la même minimisation avant la production que celles que tu appliquerais au contenu visible. Le balisage n’ajoute aucun nouveau chemin d’exfiltration, mais il rend effectivement le texte extractible par programme, par conception.
Télémétrie sûre & nettoyage des journaux
Section intitulée « Télémétrie sûre & nettoyage des journaux »L’exemple n’écrit qu’une ligne de progression fixe sur STDOUT. Il envoie le PDF vers le canal auxiliaire du harnais (NEXTPDF_COOKBOOK_OUTPUT) ou vers un chemin fourni par l’appelant. Le texte du document n’est jamais journalisé. Garde la sortie de l’outil de vérification, qui peut contenir des fragments de contenu, hors des journaux partagés.
Modèle de menace
Section intitulée « Modèle de menace »Un PDF balisé n’est pas une frontière de confiance. Un consommateur qui s’appuie sur l’arbre de structure pour un traitement automatisé doit quand même valider le fichier, car un producteur hostile peut émettre un arbre structurellement bien formé mais trompeur. Traite la structure comme une aide à l’accessibilité, pas comme un signal d’intégrité ou d’authenticité.
Comportement en mode FIPS
Section intitulée « Comportement en mode FIPS »L’exemple n’effectue aucune opération cryptographique. Le mode FIPS ne change pas son comportement. Aucune signature ni aucun chiffrement n’est en jeu.
Mappage PDF/UA-2
Section intitulée « Mappage PDF/UA-2 »| Exigence PDF/UA-2 | Ce que NextPDF émet | Article |
|---|---|---|
| Le contenu réel se trouve dans l’arbre de structure | StructTreeRoot avec un StructElem par bloc et un contenu balisé lié par MCID | ISO 14289-2 §8.2.2 |
| Imbrication et ordre de lecture définis | Éléments de bloc mappés vers des rôles grouping/leaf dans l’ordre du document | ISO 14289-2 §8.2.3 |
| Espace de noms de structure connu | Rôles dans l’espace de noms PDF 2.0 ; balises HTML mappées par rôle là où c’est nécessaire | ISO 14289-2 §8.2.4 |
| Langue du document et de l’élément | Dans le catalogue, Lang issu de la balise BCP-47 ; Lang par élément quand elle diffère | ISO 14289-2 §8.4.4 |
| Le contenu non textuel a une alternative textuelle | Alt/ActualText portés sur les éléments de structure figure/non-text | ISO 14289-2 §8.5.1 |
| Relations de tableau | Table/TR/TH/TD, rôles avec associations d’en-tête | ISO 14289-2 §8.2.5.26 |
| Métadonnées d’identification de la partie | Identification au niveau du document, planifiée à l’enregistrement | ISO 14289-2 §Intro (pdfua2#p17) |
Renvoi croisé balise → ISO 32000-2 §14
Section intitulée « Renvoi croisé balise → ISO 32000-2 §14 »PDF/UA-2 superpose des exigences d’accessibilité aux mécanismes de PDF balisé d’ISO 32000-2. Le mappage sur lequel NextPDF s’appuie :
| Émission NextPDF | Dispositif ISO 32000-2 §14 | Article |
|---|---|---|
Arbre de structure logique (StructTreeRoot) | Structure logique du PDF balisé | §14.7 (iso32000_2_sec14#x1.x38.p13) |
Dans le catalogue, MarkInfo << /Marked true >> | Marqueur de PDF balisé | §14.7 (iso32000_2_sec14#x1.x40.p3) |
Entrée Tabs par page suivant l’ordre de la structure | Navigation structurelle / ordre de tabulation | §14.8 (iso32000_2_sec14#x1.x50) |
Mappage WCAG 2.2
Section intitulée « Mappage WCAG 2.2 »PDF/UA-2 est l’expression, en PDF, d’exigences de structure que WCAG 2.2 énonce de manière indépendante du format. L’alignement pertinent :
| Critère de succès WCAG 2.2 | Mécanisme PDF/UA-2 produit ici |
|---|---|
| 1.3.1 Information et relations (niveau A) | L’arbre de structure rend les titres, les listes et les relations de tableau déterminables par programme (wcag_2_2#x2.x3.x3.x1.p3). |
| 1.3.2 Séquence significative (niveau A) | L’ordre de la structure définit l’ordre de lecture, indépendamment de la disposition visuelle. |
| 3.1.1 Langue de la page (niveau A) | L’entrée Lang du catalogue à partir de la balise BCP-47. |
| 1.1.1 Contenu non textuel (niveau A) | Alt/ActualText sur les éléments de structure non textuels (ISO 14289-2 §8.5.1). |
Ce mappage montre où la structure émise prend en charge un critère WCAG 2.2. Il ne constitue pas une revendication de conformité WCAG. La conformité WCAG couvre toute l’expérience utilisateur et se détermine par une évaluation d’accessibilité, pas par le producteur.
Conformité
Section intitulée « Conformité »| Énoncé | Spécification | Article | reference_id |
|---|---|---|---|
| Le contenu réel exige une structure logique. | ISO 14289-2 | §8.2.2 | |
| Les éléments de structure suivent une imbrication et un ordre de lecture définis. | ISO 14289-2 | §8.2.3 | |
| Chaque élément de structure se résout en un espace de noms connu, directement ou par mappage de rôle. | ISO 14289-2 | §8.2.4 | |
| La langue naturelle est déclarée au niveau du document et de l’élément de structure. | ISO 14289-2 | §8.4.4 | |
| Le contenu non textuel porte une alternative textuelle. | ISO 14289-2 | §8.5.1 | |
| Les cellules de tableau portent des relations row/header/données. | ISO 14289-2 | §8.2.5.26 | |
Le marqueur de PDF balisé est l’indicateur de catalogue MarkInfoMarked. | ISO 32000-2 | §14.7 | |
| La conformité se décide par rapport à la partie, elle n’est pas affirmée par le producteur. | ISO 14289-2 | §8.14.2 |
NextPDF émet la structure balisée qui prend en charge une production accessible. La prise en charge ne vaut pas conformité. Cette page n’affirme pas la conformité PDF/UA-2. C’est un outil de vérification indépendant (par exemple veraPDF) qui établit ce verdict. Exécute l’outil de vérification avant d’affirmer qu’un fichier est conforme.