Skip to content

PDF/UA-Barrierefreiheit

PDF/UA (ISO 14289) definiert die Anforderungen an universell zugängliche PDF-Dokumente. PDF Oxide validiert Strukturbäume, Überschriftenabfolgen, Alternativtexte, Tabellenüberschriften, Sprachdeklarationen und mehr.

Abdeckung in den Bindings. Die PDF/UA-Validierung ist in Python (doc.validate_pdf_ua()), Rust (validate_pdf_ua + Builder PdfUaValidator) und Go (doc.ValidatePdfUa()) verfügbar. WASM stellt, sofern vorhanden, über validatePdfUa eine einfache Bestanden/Nicht-bestanden-Prüfung bereit. Ein öffentlicher C#-Wrapper ist noch nicht verfügbar — nutzen Sie die Rust-CLI (pdf-oxide validate --pdfua doc.pdf) oder rufen Sie die Prüfung über eines der unterstützten Bindings auf.

Unterstützte Stufen

Stufe Standard Beschreibung
PDF/UA-1 ISO 14289-1:2014 Grundlegende Anforderungen an die Barrierefreiheit
PDF/UA-2 ISO 14289-2:2024 Erweiterte Anforderungen, abgestimmt auf WCAG 2.1

Schnelle Validierung

from pdf_oxide import PdfDocument

doc = PdfDocument("document.pdf")
result = doc.validate_pdf_ua()
print(f"Valid: {result.valid}")
for error in result.errors:
    print(f"  {error}")
use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::{validate_pdf_ua, PdfUaLevel};

let mut doc = PdfDocument::open("accessible.pdf")?;
let result = validate_pdf_ua(&mut doc, PdfUaLevel::UA1)?;

if result.has_errors() {
    println!("Not PDF/UA-1 compliant:");
    for error in &result.errors {
        println!("  [{}] {} (clause {})",
            error.code, error.message,
            error.clause.as_deref().unwrap_or("n/a"));
    }
} else {
    println!("Document is PDF/UA-1 compliant");
}
doc, err := pdfoxide.Open("accessible.pdf")
if err != nil { log.Fatal(err) }
defer doc.Close()

valid, errs, err := doc.ValidatePdfUa()
if err != nil { log.Fatal(err) }

if valid {
    fmt.Println("Document is PDF/UA-1 compliant")
} else {
    fmt.Println("Not PDF/UA-1 compliant:")
    for _, e := range errs {
        fmt.Printf("  %s\n", e)
    }
}

Validator-API

Der Builder PdfUaValidator erlaubt das Konfigurieren bestimmter Prüfungen:

use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::{PdfUaValidator, PdfUaLevel};

let mut doc = PdfDocument::open("report.pdf")?;

let result = PdfUaValidator::new()
    .check_heading_sequence(true)
    .check_color_contrast(true)
    .allow_custom_types(vec!["Caption".into(), "Aside".into()])
    .validate(&mut doc, PdfUaLevel::UA1)?;

println!("Errors: {}", result.errors.len());
println!("Warnings: {}", result.warnings.len());
println!("Structure elements checked: {}",
    result.stats.structure_elements_checked);

Konfigurationsoptionen

Methode Standard Beschreibung
check_heading_sequence(bool) true Prüft, ob H1-H6 keine Ebenen überspringen
check_color_contrast(bool) true Markiert mögliche Kontrastprobleme
allow_custom_types(Vec<String>) [] Lässt nicht standardisierte Strukturtypen ohne Warnung zu

Untersuchung des Strukturbaums

Vor der Validierung können Sie den Strukturbaum und die Markierungsinformationen des Dokuments untersuchen:

use pdf_oxide::PdfDocument;

let mut doc = PdfDocument::open("tagged.pdf")?;

// Check if the document claims to be tagged
let mark_info = doc.mark_info()?;
println!("Marked: {}", mark_info.marked);
println!("Suspects: {}", mark_info.suspects);

// Access the structure tree
if let Some(tree) = doc.structure_tree()? {
    println!("Root tag: {}", tree.root_type);
    println!("Children: {}", tree.children.len());
}

Die Methode mark_info() gibt zurück:

Feld Typ Beschreibung
marked bool Ob sich das Dokument als getaggt deklariert
suspects bool Ob Tag-Zuordnungen möglicherweise fehlerhaft sind
user_properties bool Ob Benutzereigenschaften vorhanden sind

Wenn suspects true ist, greift PDF Oxide bei der Textextraktion automatisch auf die geometrische Anordnung zurück, anstatt sich auf den möglicherweise unzuverlässigen Strukturbaum zu verlassen.

Was geprüft wird

Der Validator deckt die folgenden PDF/UA-Anforderungen ab:

Dokumentebene

Prüfung Abschnitt Beschreibung
Sprache 7.2 Eintrag /Lang im Katalog vorhanden
Titel 7.1 Dokumenttitel gesetzt und in der Titelleiste angezeigt
Getaggt 7.1 Das MarkInfo-Dictionary deklariert Marked = true
XMP-Metadaten 7.1 pdfuaid:part im XMP-Stream deklariert

Struktur

Prüfung Abschnitt Beschreibung
Strukturbaum 7.1 Vollständiger Strukturbaum mit StructTreeRoot als Wurzel
Rollenzuordnung 7.5 Nicht standardisierte Typen auf Standard-Strukturelemente abgebildet
Überschriftenhierarchie 7.4.2 Überschriften (H1-H6) überspringen keine Ebenen
Artefaktmarkierung 7.3 Dekorative Inhalte als Artefakt markiert
Lesereihenfolge 7.2 Der Strukturbaum definiert eine logische Lesereihenfolge

Inhalt

Prüfung Abschnitt Beschreibung
Alternativtext für Bilder 7.3 /Alt oder /ActualText an Figure-Elementen
Tabellenüberschriften 7.5 TH-Elemente in Tabellenstrukturen vorhanden
Formularbeschriftungen 7.6.2 Formularfelder haben zugeordnete Beschriftungen oder Tooltips
Linktext 7.18 Link-Annotationen haben beschreibenden Inhalt
Listenstruktur 7.4.3 Listen verwenden die Struktur L, LI, Lbl, LBody

Schrift und Text

Prüfung Abschnitt Beschreibung
Unicode-Zuordnung 7.21.3 Sämtlicher Text hat eine Unicode-Repräsentation
Schrifteinbettung 7.21.4 Schriften eingebettet oder Standard-Base14-Schriften
ActualText 7.21.5 Ligaturen und Sonderglyphen haben /ActualText

UaValidationResult

pub struct UaValidationResult {
    pub level: PdfUaLevel,
    pub errors: Vec<UaComplianceError>,
    pub warnings: Vec<ComplianceWarning>,
    pub stats: UaValidationStats,
}

UaComplianceError

Jeder Fehler enthält einen optionalen WCAG-Abgleich:

pub struct UaComplianceError {
    pub code: UaErrorCode,
    pub message: String,
    pub location: Option<String>,
    pub wcag_ref: Option<String>,
    pub clause: Option<String>,
}

Das Feld wcag_ref ordnet den PDF/UA-Verstoß dem entsprechenden WCAG-Erfolgskriterium zu (z. B. "1.1.1" für Nicht-Text-Inhalte, "1.3.1" für Info und Beziehungen).

Kategorien von UaErrorCode

Das Enum UaErrorCode umfasst Fehlerkategorien wie:

  • MissingLanguage – kein /Lang-Eintrag im Dokumentkatalog
  • MissingStructureTree – Dokument ist nicht getaggt
  • MissingAltText – Figure-Element ohne Alternativtext
  • HeadingSkipped – Überschriftenebenen werden übersprungen (z. B. von H1 zu H3)
  • MissingTableHeaders – Tabelle ohne TH-Elemente
  • FormFieldNoLabel – Formularfeld ohne zugeordnete Beschriftung
  • InvalidRoleMapping – nicht standardisierter Typ nicht auf ein Standardelement abgebildet
  • ArtifactNotMarked – dekorativer Inhalt nicht als Artefakt markiert
  • MissingUnicode – Text ohne Unicode-Zuordnung

Praktisches Beispiel: Barrierefreiheitsbericht

Erzeugen Sie aus den Validierungsergebnissen einen menschenlesbaren Barrierefreiheitsbericht:

use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::{validate_pdf_ua, PdfUaLevel};

let mut doc = PdfDocument::open("document.pdf")?;
let result = validate_pdf_ua(&mut doc, PdfUaLevel::UA1)?;

println!("=== PDF/UA Accessibility Report ===");
println!("Level: PDF/UA-{}", result.level.xmp_part());
println!("Status: {}", if result.has_errors() { "FAIL" } else { "PASS" });
println!();

if result.has_errors() {
    println!("Errors ({}):", result.errors.len());
    for (i, error) in result.errors.iter().enumerate() {
        print!("  {}. [{}] {}", i + 1, error.code, error.message);
        if let Some(ref wcag) = error.wcag_ref {
            print!("  (WCAG {})", wcag);
        }
        println!();
    }
}

if result.has_warnings() {
    println!("\nWarnings ({}):", result.warnings.len());
    for warning in &result.warnings {
        println!("  - [{}] {}", warning.code, warning.message);
    }
}

println!("\nStats:");
println!("  Structure elements checked: {}",
    result.stats.structure_elements_checked);

Nächste Schritte