Emitir un árbol de estructura etiquetado para PDF/UA-2 a partir de contenido semántico
De un vistazo
Sección titulada «De un vistazo»Esta receta crea un PDF etiquetado orientado a ISO 14289-2 (PDF/UA-2). NextPDF emite un árbol de estructura lógica, secuencias de contenido marcado, el idioma del catálogo y los metadatos de identificación a nivel de documento. Esa estructura facilita la autoría accesible, pero la conformidad la decide un verificador independiente. La receta sigue examples/31-pdfua2-tagged.php.
Instalación
Sección titulada «Instalación»composer require nextpdf/core:^3El paso de verificación requiere que haya un verificador de PDF/UA-2 en PATH. Los ejemplos de esta receta usan veraPDF con el perfil ua2. No se necesita ningún paquete Pro ni Enterprise para emitir la estructura etiquetada.
Visión general conceptual
Sección titulada «Visión general conceptual»Un PDF etiquetado incluye un árbol de estructura lógica paralelo al flujo de contenido visual. Las tecnologías de asistencia leen el árbol, no la disposición de los píxeles, por lo que la estructura determina el orden de lectura expuesto. ISO 14289-2 establece cuatro requisitos sobre este punto. El contenido real (que no sea artefacto) debe ser alcanzable a través de ese árbol (§8.2.2). Los elementos de estructura deben anidarse en un orden definido (§8.2.3). Cada elemento debe resolverse a un espacio de nombres de estructura conocido, directamente o mediante asignación de roles (§8.2.4). Además, el idioma natural del contenido se declara a nivel de documento y se refina por elemento de estructura cuando difiere (§8.4.4).
NextPDF modela esto con un ConformanceMode tipado. enableTaggedPdf() establece ConformanceMode::PdfUa2, lo que (a) hace que la pipeline HTML conecte un TaggedContentEmitter al construir el analizador, (b) activa la marca MarkInfoMarked del catálogo que señala un PDF etiquetado (ISO 32000-2 §14.7), y (c) registra el idioma BCP-47 para la entrada Lang del catálogo. El escritor también emite la entrada Tabs por página para que el orden de tabulación siga el orden de la estructura (ISO 32000-2 §14.8).
Las invariantes estrictas de UA-2 solo se aplican a ConformanceMode::PdfUa2. Construir una ConformancePolicy estricta para cualquier otro modo lanza InvalidConfigException por diseño.
Superficie de la API
Sección titulada «Superficie de la API»La superficie de la API se genera a partir de PHPDoc. Los puntos de entrada principales:
\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(el modo que estableceenableTaggedPdf())Document::beginTag(string $type): static/Document::endTag(): static(etiquetado manual para contenido que no es HTML)
Ejemplo de código — Inicio rápido
Sección titulada «Ejemplo de código — Inicio rápido»<?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";Ejemplo de código — Producción
Sección titulada «Ejemplo de código — Producción»Este es el programa autónomo y ejecutable mediante el harness. En producción, el código llamador falla rápido ante una etiqueta de idioma mal formada, en lugar de descubrirla solo al ejecutar el verificador externo. Pasar ConformancePolicy::strictUa2() permite rechazar una etiqueta BCP-47 no válida en el límite de la API; después, la compilación queda condicionada al veredicto del verificador.
<?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 esperado en un host cuyo verapdf --flavour ua2 informa que el archivo es conforme:
veraPDF PASS — accessible.pdf carries a conforming UA-2 structureSi enableTaggedPdf() rechaza la etiqueta de idioma, el programa termina con código distinto de cero después de Tagged PDF/UA-2 setup rejected: … en STDERR. Si el verificador informa un problema, termina con código distinto de cero después de veraPDF FAILED — output is not PDF/UA-2 conforming. El veredicto corresponde al verificador: NextPDF emite la estructura, pero no afirma la conformidad.
Casos límite y trampas
Sección titulada «Casos límite y trampas»- Orden de las llamadas.
enableTaggedPdf()después dewriteHtml()no etiqueta retroactivamente el contenido ya escrito. Primero debe activarse el modo etiquetado. - Control estricto del idioma. Sin una política, una etiqueta BCP-47 no analizable se descarta de forma silenciosa y solo aparece al ejecutar el verificador. Con
ConformancePolicy::strictUa2()la misma etiqueta lanzaInvalidConfigExceptionen el límite deenableTaggedPdf()(ISO 14289-2 §8.4.4 ruta estricta). - Reactivación idempotente. Llamar a
enableTaggedPdf()dos veces actualiza el idioma sin reconstruir un árbol de estructura ya poblado. - Etiquetado manual. Para contenido que no es HTML, envuelve los elementos con
beginTag()/endTag(). Los roles de contenedor (Table,TR,L,LI) se convierten en elementos de agrupación sin contenido marcado. Los roles hoja (P,H1–H6,TD) obtienen MCID. - Exclusividad de modo. Una
ConformancePolicyestricta solo es válida conConformanceMode::PdfUa2. Combinar marcas estrictas de UA-2 con un modo PDF/A lanzaInvalidConfigException. Para componer un entregable PDF/A etiquetado, activar por separado el modo etiquetado y el perfil PDF/A.
Rendimiento
Sección titulada «Rendimiento»El árbol de estructura añade un árbol paralelo de diccionarios ligeros, más operadores BDC/EMC por tramo de texto. Para un informe típico, la sobrecarga representa un pequeño porcentaje del tamaño de salida y se mantiene cómodamente dentro del presupuesto de 2000 ms / 128 MB. El perfil de reproducibilidad semántica se aplica aquí porque un entregable orientado al verificador se compara por su árbol de sintaxis abstracta (AST) estructural y sus metadatos, no por los bytes en bruto. Ver la sección Conformidad.
Notas de seguridad
Sección titulada «Notas de seguridad»Residencia de datos y mitigaciones de PII
Sección titulada «Residencia de datos y mitigaciones de PII»El árbol de estructura contiene el mismo texto que el contenido visible. Si el HTML de origen contiene datos personales, esos datos también son alcanzables a través del árbol y de los atributos ActualText/Alt. Aplicar el mismo enmascaramiento y la misma minimización antes de generar el documento que se aplicarían al contenido visible. El etiquetado no añade ninguna nueva vía de exfiltración, pero sí hace que el texto sea extraíble programáticamente por diseño.
Telemetría segura y depuración de registros
Sección titulada «Telemetría segura y depuración de registros»La receta escribe en STDOUT solo una línea de progreso fija. Enrutar el PDF al canal lateral del harness (NEXTPDF_COOKBOOK_OUTPUT) o a una ruta del llamador. El texto del documento nunca se registra. Mantener la salida del verificador, que puede reproducir fragmentos de contenido, fuera de los registros compartidos.
Modelo de amenazas
Sección titulada «Modelo de amenazas»Un PDF etiquetado no es un límite de confianza. Un consumidor que confía en el árbol de estructura para el procesamiento automatizado aún debe validar el archivo, porque un productor hostil puede emitir un árbol estructuralmente bien formado pero engañoso. Tratar la estructura como una función de accesibilidad, no como una señal de integridad o autenticidad.
Comportamiento en modo FIPS
Sección titulada «Comportamiento en modo FIPS»Esta recipe no realiza ninguna operación criptográfica. El modo FIPS no cambia su comportamiento. No interviene ninguna firma ni cifrado.
Asignación de PDF/UA-2
Sección titulada «Asignación de PDF/UA-2»| Requisito de PDF/UA-2 | Lo que emite NextPDF | Cláusula |
|---|---|---|
| El contenido real está en el árbol de estructura | StructTreeRoot con StructElem por bloque y contenido marcado enlazado por MCID | ISO 14289-2 §8.2.2 |
| Anidamiento y orden de lectura definidos | Elementos de bloque asignados a roles de grouping/leaf en orden de documento | ISO 14289-2 §8.2.3 |
| Espacio de nombres de estructura conocido | Roles en el espacio de nombres de PDF 2.0; etiquetas HTML con asignación de roles donde es necesario | ISO 14289-2 §8.2.4 |
| Idioma del documento y del elemento | El Lang del catálogo a partir de la etiqueta BCP-47; el Lang por elemento cuando difiere | ISO 14289-2 §8.4.4 |
| El contenido que no es texto tiene una alternativa textual | Alt/ActualText en los elementos de estructura figure/non-text | ISO 14289-2 §8.5.1 |
| Relaciones de tabla | Table/TR/TH/TD roles con asociación de encabezados | ISO 14289-2 §8.2.5.26 |
| Metadatos de identificación de parte | Identificación a nivel de documento programada al guardar | ISO 14289-2 §Intro (pdfua2#p17) |
Referencia cruzada de etiqueta → ISO 32000-2 §14
Sección titulada «Referencia cruzada de etiqueta → ISO 32000-2 §14»PDF/UA-2 superpone requisitos de accesibilidad sobre los mecanismos de PDF etiquetado de ISO 32000-2. La asignación en la que se basa NextPDF:
| Emisión de NextPDF | Recurso de ISO 32000-2 §14 | Cláusula |
|---|---|---|
Árbol de estructura lógica (StructTreeRoot) | Estructura lógica de PDF etiquetado | §14.7 (iso32000_2_sec14#x1.x38.p13) |
Catálogo MarkInfo << /Marked true >> | Marcador de PDF etiquetado | §14.7 (iso32000_2_sec14#x1.x40.p3) |
Entrada Tabs por página que sigue el orden de la estructura | Navegación estructural / orden de tabulación | §14.8 (iso32000_2_sec14#x1.x50) |
Asignación de WCAG 2.2
Sección titulada «Asignación de WCAG 2.2»PDF/UA-2 es la expresión en formato PDF de requisitos de estructura que WCAG 2.2 enuncia de forma independiente del formato. La correspondencia relevante:
| Criterio de éxito de WCAG 2.2 | Mecanismo de PDF/UA-2 que produce esta recipe |
|---|---|
| 1.3.1 Información y relaciones (Nivel A) | El árbol de estructura hace que los encabezados, las listas y las relaciones de tabla sean programáticamente determinables (wcag_2_2#x2.x3.x3.x1.p3). |
| 1.3.2 Secuencia significativa (Nivel A) | El orden de la estructura define el orden de lectura con independencia de la disposición visual. |
| 3.1.1 Idioma de la página (Nivel A) | La entrada Lang del catálogo a partir de la etiqueta BCP-47. |
| 1.1.1 Contenido que no es texto (Nivel A) | Alt/ActualText en los elementos de estructura que no son texto (ISO 14289-2 §8.5.1). |
Esta asignación muestra dónde la estructura emitida facilita un criterio de WCAG 2.2. No es una declaración de conformidad con WCAG. La conformidad con WCAG cubre toda la experiencia de usuario y la determina una evaluación de accesibilidad, no el productor.
Conformidad
Sección titulada «Conformidad»| Declaración | Especificación | Cláusula | reference_id |
|---|---|---|---|
| El contenido real requiere una estructura lógica. | ISO 14289-2 | §8.2.2 | |
| Los elementos de estructura siguen un anidamiento y un orden de lectura definidos. | ISO 14289-2 | §8.2.3 | |
| Cada elemento de estructura se resuelve a un espacio de nombres conocido, directamente o mediante asignación de roles. | ISO 14289-2 | §8.2.4 | |
| El idioma natural se declara a nivel de documento y de elemento de estructura. | ISO 14289-2 | §8.4.4 | |
| El contenido que no es texto lleva una alternativa textual. | ISO 14289-2 | §8.5.1 | |
| Las celdas de tabla llevan relaciones de row/header/datos. | ISO 14289-2 | §8.2.5.26 | |
El marcador de PDF etiquetado es la marca MarkInfoMarked del catálogo. | ISO 32000-2 | §14.7 | |
| La conformidad se decide frente a la parte, no la afirma el productor. | ISO 14289-2 | §8.14.2 |
NextPDF emite la estructura etiquetada que facilita la autoría accesible. Facilitar no es conformidad. Esta receta no afirma la conformidad con PDF/UA-2. Un verificador independiente (por ejemplo, veraPDF) realiza esa determinación. Ejecutar el verificador antes de afirmar que un archivo es conforme.