Een getagde PDF/UA-2-structuurboom genereren uit semantische inhoud
In het kort
Sectie met titel “In het kort”Met dit recipe maak je een getagd Portable Document Format/Universal Accessibility 2 (PDF/UA-2)-bestand. Het is gericht op International Organization for Standardization (ISO) 14289-2. NextPDF genereert een logische structuurboom, marked-content-reeksen, de catalogustaal en identificatiemetadata op documentniveau. Die structuur ondersteunt toegankelijk auteurschap, maar een onafhankelijke checker bepaalt de conformiteit. Het recipe volgt examples/31-pdfua2-tagged.php.
Installatie
Sectie met titel “Installatie”composer require nextpdf/core:^3Zet een PDF/UA-2-checker op PATH voor de verificatie. Dit recipe gebruikt veraPDF met de ua2-variant. Je hebt geen Pro- of Enterprise-pakket nodig om de getagde structuur te genereren.
Conceptueel overzicht
Sectie met titel “Conceptueel overzicht”Een getagde PDF bevat naast de visuele content-stream een parallelle logische structuurboom. Hulptechnologie leest de boom in plaats van de pixel-lay-out, dus de structuur bepaalt de leesvolgorde die wordt aangeboden. ISO 14289-2 stelt hier vier eisen. Echte (niet-artefact) inhoud moet via die boom bereikbaar zijn (§8.2.2). Structuurelementen moeten volgens een gedefinieerde volgorde genest zijn (§8.2.3). Elk element moet, rechtstreeks of via role mapping, herleidbaar zijn tot een bekende structuurnaamruimte (§8.2.4). De natuurlijke taal van de inhoud wordt op documentniveau gedeclareerd en per structuurelement verfijnd waar deze afwijkt (§8.4.4).
NextPDF modelleert dit met een getypeerde ConformanceMode. enableTaggedPdf() stelt ConformanceMode::PdfUa2 in. Daardoor (a) koppelt de Hypertext Markup Language (HTML)-pijplijn een TaggedContentEmitter aan op het moment dat de parser wordt geconstrueerd, (b) stelt de catalogus-MarkInfoMarked-vlag in die een getagde PDF signaleert (ISO 32000-2 §14.7), en (c) legt de Best Current Practice 47 (BCP 47)-taal vast voor de catalogus-Lang-vermelding. De writer genereert ook de Tabs-vermelding per pagina, zodat de tabvolgorde de structuurvolgorde volgt (ISO 32000-2 §14.8).
De strikte UA-2-invarianten gelden alleen voor ConformanceMode::PdfUa2. Als je een strikte ConformancePolicy tegen een andere modus construeert, werpt dat bewust InvalidConfigException.
API-oppervlak
Sectie met titel “API-oppervlak”Het API-oppervlak (application programming interface) is afgeleid uit PHPDoc. Gebruik deze belangrijkste ingangspunten:
\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(de modus die wordt ingesteld doorenableTaggedPdf())Document::beginTag(string $type): static/Document::endTag(): static(handmatige tagging voor niet-HTML-inhoud)
Codevoorbeeld — Snelstart
Sectie met titel “Codevoorbeeld — Snelstart”<?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";Codevoorbeeld — Productie
Sectie met titel “Codevoorbeeld — Productie”Dit op zichzelf staande programma kan in de harness draaien. Laat de productieflow bij een misvormde taaltag snel falen, in plaats van dit pas te ontdekken wanneer de externe checker draait. Geef ConformancePolicy::strictUa2() mee om een ongeldige BCP 47-tag bij de API-grens af te wijzen, en koppel de build vervolgens aan het oordeel van de checker.
<?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";Op een host waar verapdf --flavour ua2 een conform bestand meldt, is de verwachte standaarduitvoer (STDOUT):
veraPDF PASS — accessible.pdf carries a conforming UA-2 structureAls enableTaggedPdf() de taaltag afwijst, eindigt het programma met een niet-nul-status na Tagged PDF/UA-2 setup rejected: … op de standaardfoutuitvoer (STDERR). Als de checker een probleem meldt, eindigt het programma met een niet-nul-status na veraPDF FAILED — output is not PDF/UA-2 conforming. De checker geeft het oordeel: NextPDF genereert de structuur, maar stelt geen conformiteit vast.
Randgevallen en valkuilen
Sectie met titel “Randgevallen en valkuilen”- Aanroepvolgorde.
enableTaggedPdf()nawriteHtml()tagt al geschreven inhoud niet met terugwerkende kracht. Schakel de getagde modus eerst in. - Strikte taalpoort. Zonder een policy wordt een niet-parseerbare BCP 47-tag stilzwijgend verwijderd en komt die pas bij de checker aan het licht. Met
ConformancePolicy::strictUa2()werpt dezelfde tagInvalidConfigExceptionbij deenableTaggedPdf()-grens (ISO 14289-2 §8.4.4 strikt pad). - Idempotent opnieuw inschakelen. Als je
enableTaggedPdf()tweemaal aanroept, werkt NextPDF de taal bij zonder een gevulde structuurboom opnieuw op te bouwen. - Handmatige tagging. Omhul items voor niet-HTML-inhoud met
beginTag()/endTag(). Container-rollen (Table,TR,L,LI) worden groeperende elementen zonder marked content. Blad-rollen (P,H1–H6,TD) krijgen marked-content-identifiers (MCID’s). - Modusexclusiviteit. Een strikte
ConformancePolicyis alleen geldig metConformanceMode::PdfUa2. Het combineren van strikte UA-2-vlaggen met een PDF/A-modus werptInvalidConfigException. Maak een getagd PDF/A-product door de getagde modus en het PDF/A-profiel afzonderlijk in te schakelen.
Prestaties
Sectie met titel “Prestaties”De structuurboom voegt één parallelle boom van lichtgewicht woordenboeken toe en BDC/EMC-operatoren per tekstrun. Voor een typisch rapport bedraagt de overhead enkele procenten van de uitvoergrootte en blijft deze ruim binnen het budget van 2000 ms / 128 MB. Het semantische reproduceerbaarheidsprofiel is van toepassing, omdat een checkergericht product wordt vergeleken op basis van de structurele abstract syntax tree (AST) plus metadata, niet op basis van ruwe bytes. Zie de sectie Conformiteit.
Beveiligingsnotities
Sectie met titel “Beveiligingsnotities”Gegevenslocatie en PII-mitigaties
Sectie met titel “Gegevenslocatie en PII-mitigaties”De structuurboom bevat dezelfde tekst als de zichtbare inhoud. Als de bron-HTML persoonsgegevens bevat, waaronder persoonlijk identificeerbare informatie (PII), zijn die gegevens ook bereikbaar via de boom en via de ActualText/Alt-attributen. Pas vóór het auteurschap dezelfde redactie en minimalisatie toe als je voor de zichtbare inhoud zou doen. Tagging voegt geen nieuw exfiltratiepad toe, maar maakt de tekst bewust programmatisch extraheerbaar.
Veilige telemetrie en log-scrubbing
Sectie met titel “Veilige telemetrie en log-scrubbing”Het recipe schrijft alleen een vaste voortgangsregel naar STDOUT. Het routeert de PDF naar het zijkanaal van de harness (NEXTPDF_COOKBOOK_OUTPUT) of naar een pad dat de aanroeper opgeeft. Documenttekst wordt nooit gelogd. Houd checker-uitvoer, die inhoudsfragmenten kan weergeven, uit gedeelde logs.
Dreigingsmodel
Sectie met titel “Dreigingsmodel”Een getagde PDF is geen vertrouwensgrens. Als je afnemer de structuurboom voor geautomatiseerde verwerking vertrouwt, moet die het bestand nog steeds valideren, omdat een vijandige producent een structureel welgevormde maar misleidende boom kan genereren. Behandel de structuur als een toegankelijkheidsvoorziening, niet als een integriteits- of authenticiteitssignaal.
Gedrag in FIPS-modus
Sectie met titel “Gedrag in FIPS-modus”Dit recipe voert geen cryptografische bewerking uit. De Federal Information Processing Standards (FIPS)-modus verandert het gedrag ervan niet. Er is geen ondertekening of versleuteling bij betrokken.
PDF/UA-2-mapping
Sectie met titel “PDF/UA-2-mapping”| PDF/UA-2-eis | Wat NextPDF genereert | Clausule |
|---|---|---|
| Echte inhoud bevindt zich in de structuurboom | StructTreeRoot met StructElem per blok en MCID-gekoppelde marked content | ISO 14289-2 §8.2.2 |
| Gedefinieerde nesting en leesvolgorde | Blokelementen toegewezen aan grouping/leaf-rollen in documentvolgorde | ISO 14289-2 §8.2.3 |
| Bekende structuurnaamruimte | Rollen in de PDF 2.0-naamruimte; HTML-tags worden waar nodig via role mapping toegewezen | ISO 14289-2 §8.2.4 |
| Document- en elementtaal | Catalogus-Lang uit de BCP 47-tag; per-element-Lang wanneer deze afwijkt | ISO 14289-2 §8.4.4 |
| Niet-tekstuele inhoud heeft een tekstalternatief | Alt/ActualText op figure/non-text-structuurelementen | ISO 14289-2 §8.5.1 |
| Tabelrelaties | Table/TR/TH/TD-rollen met header-associatie | ISO 14289-2 §8.2.5.26 |
| Identificatiemetadata van het onderdeel | Identificatie op documentniveau ingepland bij het opslaan | ISO 14289-2 §Intro (pdfua2#p17) |
Tag → ISO 32000-2 §14-kruisverwijzing
Sectie met titel “Tag → ISO 32000-2 §14-kruisverwijzing”PDF/UA-2 legt toegankelijkheidseisen boven op de getagde-PDF-mechanismen van ISO 32000-2. NextPDF steunt op deze mapping:
| NextPDF-emissie | ISO 32000-2 §14-voorziening | Clausule |
|---|---|---|
Logische structuurboom (StructTreeRoot) | Getagde-PDF logische structuur | §14.7 (iso32000_2_sec14#x1.x38.p13) |
Catalogus-MarkInfo << /Marked true >> | Getagde-PDF-markering | §14.7 (iso32000_2_sec14#x1.x40.p3) |
Tabs-vermelding per pagina die de structuurvolgorde volgt | Structurele navigatie / tabvolgorde | §14.8 (iso32000_2_sec14#x1.x50) |
WCAG 2.2-mapping
Sectie met titel “WCAG 2.2-mapping”PDF/UA-2 is de PDF-formaatspecifieke uitwerking van structuureisen die Web Content Accessibility Guidelines (WCAG) 2.2 formaatonafhankelijk verwoordt. De relevante afstemming:
| WCAG 2.2-succescriterium | PDF/UA-2-mechanisme dat dit recipe produceert |
|---|---|
| 1.3.1 Info en relaties (niveau A) | De structuurboom maakt koppen, lijsten en tabelrelaties programmatisch bepaalbaar (wcag_2_2#x2.x3.x3.x1.p3). |
| 1.3.2 Betekenisvolle volgorde (niveau A) | De structuurvolgorde bepaalt de leesvolgorde onafhankelijk van de visuele lay-out. |
| 3.1.1 Taal van de pagina (niveau A) | De catalogus-Lang-vermelding uit de BCP 47-tag. |
| 1.1.1 Niet-tekstuele inhoud (niveau A) | Alt/ActualText op niet-tekstuele structuurelementen (ISO 14289-2 §8.5.1). |
Deze mapping laat zien waar de gegenereerde structuur een WCAG 2.2-criterium ondersteunt. Dit is geen WCAG-conformiteitsclaim. WCAG-conformiteit omvat de volledige gebruikerservaring, en een toegankelijkheidsevaluatie bepaalt die, niet de producent.
Conformiteit
Sectie met titel “Conformiteit”| Bewering | Specificatie | Clausule | reference_id |
|---|---|---|---|
| Echte inhoud vereist een logische structuur. | ISO 14289-2 | §8.2.2 | |
| Structuurelementen volgen een gedefinieerde nesting en leesvolgorde. | ISO 14289-2 | §8.2.3 | |
| Elk structuurelement is, rechtstreeks of via role mapping, herleidbaar tot een bekende naamruimte. | ISO 14289-2 | §8.2.4 | |
| Natuurlijke taal wordt op document- en structuurelementniveau gedeclareerd. | ISO 14289-2 | §8.4.4 | |
| Niet-tekstuele inhoud draagt een tekstalternatief. | ISO 14289-2 | §8.5.1 | |
| Tabelcellen dragen row/header/data-relaties. | ISO 14289-2 | §8.2.5.26 | |
De getagde-PDF-markering is de catalogus-MarkInfoMarked-vlag. | ISO 32000-2 | §14.7 | |
| Conformiteit wordt bepaald ten opzichte van het onderdeel, niet beweerd door de producent. | ISO 14289-2 | §8.14.2 |
NextPDF genereert de getagde structuur die toegankelijk auteurschap ondersteunt. Ondersteuning is geen conformiteit. Dit recipe beweert geen PDF/UA-2-conformiteit. Een onafhankelijke checker, zoals veraPDF, doet die bepaling. Draai de checker voordat je stelt dat een bestand conform is.