PDF/UA 无障碍
PDF/UA(ISO 14289)定义了通用无障碍 PDF 文档的要求。PDF Oxide 验证结构树、标题序列、替代文本、表格表头、语言声明等。
支持的级别
| 级别 | 标准 | 描述 |
|---|---|---|
| PDF/UA-1 | ISO 14289-1:2014 | 基本辅助功能要求 |
| PDF/UA-2 | ISO 14289-2:2024 | 增强要求,与 WCAG 2.1 对齐 |
快速验证
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, PdfUa级别};
let mut doc = PdfDocument::open("accessible.pdf")?;
let result = validate_pdf_ua(&mut doc, PdfUa级别::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");
}
验证器 API
PdfUaValidator 构建器允许配置特定的检查项:
use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::{PdfUaValidator, PdfUa级别};
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, PdfUa级别::UA1)?;
println!("Errors: {}", result.errors.len());
println!("Warnings: {}", result.warnings.len());
println!("结构 elements checked: {}",
result.stats.structure_elements_checked);
配置选项
| Method | 默认值 | 描述 |
|---|---|---|
check_heading_sequence(bool) |
true |
Validate H1-H6 do not skip levels |
check_color_contrast(bool) |
true |
Flag potential contrast issues |
allow_custom_types(Vec<String>) |
[] |
Permit non-standard structure types without warning |
结构树检查
在运行验证之前,你可以检查文档的结构树和标记信息:
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());
}
mark_info() 方法返回:
| 字段 | 类型 | 描述 |
|---|---|---|
marked |
bool |
Whether the document declares itself as tagged |
suspects |
bool |
Whether tag assignments may be incorrect |
user_properties |
bool |
Whether user properties are present |
当 suspects 为 true 时,PDF Oxide 自动回退到基于几何位置的排序进行文本提取,而非依赖可能不可靠的结构树。
检查内容
验证器涵盖以下 PDF/UA 要求:
文档级
| 检查项 | 条款 | 描述 |
|---|---|---|
| 语言 | 7.2 | /Lang 条目存在于目录中 |
| Title | 7.1 | 文档标题已设置并显示在标题栏中 |
| Tagged | 7.1 | MarkInfo 字典声明 Marked = true |
| XMP metadata | 7.1 | pdfuaid:part 在 XMP 流中声明 |
结构
| 检查项 | 条款 | 描述 |
|---|---|---|
| 结构 tree | 7.1 | 以 StructTreeRoot 为根的完整结构树 |
| Role mapping | 7.5 | 非标准类型映射到标准结构元素 |
| Heading hierarchy | 7.4.2 | 标题(H1-H6)不跳过级别 |
| Artifact marking | 7.3 | 装饰性内容标记为 artifact |
| Reading order | 7.2 | 结构树定义逻辑阅读顺序 |
内容
| 检查项 | 条款 | 描述 |
|---|---|---|
| Alt text for images | 7.3 | /Alt or /ActualText 在 Figure 元素上 |
| Table headers | 7.5 | TH 元素存在于表格结构中 |
| Form labels | 7.6.2 | 表单字段 have associated labels or tooltips |
| Link text | 7.18 | 链接注释具有描述性内容 |
| List structure | 7.4.3 | 列表使用 L, LI, Lbl, LBody structure |
字体和文本
| 检查项 | 条款 | 描述 |
|---|---|---|
| Unicode mapping | 7.21.3 | 所有文本具有 Unicode 表示 |
| Font embedding | 7.21.4 | 字体已嵌入或为标准 Base14 字体 |
| ActualText | 7.21.5 | 连字和特殊字形具有 /ActualText |
UaValidationResult
pub struct UaValidationResult {
pub level: PdfUa级别,
pub errors: Vec<UaComplianceError>,
pub warnings: Vec<ComplianceWarning>,
pub stats: UaValidationStats,
}
UaComplianceError
每个错误包含可选的 WCAG 对应关系:
pub struct UaComplianceError {
pub code: UaErrorCode,
pub message: String,
pub location: Option<String>,
pub wcag_ref: Option<String>,
pub clause: Option<String>,
}
wcag_ref 字段将 PDF/UA 违规映射到对应的 WCAG 成功准则(例如 "1.1.1" 对应非文本内容,"1.3.1" 对应信息和关系)。
UaErrorCode Categories
UaErrorCode 枚举包含以下错误类别:
MissingLanguage– 文档目录中没有/Lang条目Missing结构Tree– 文档未标记MissingAltText– Figure 元素缺少替代文本HeadingSkipped– 标题级别跳跃(例如 H1 到 H3)MissingTableHeaders– 表格缺少TH元素FormFieldNoLabel– 表单字段 has no associated labelInvalidRoleMapping– 非标准类型未映射到标准元素ArtifactNotMarked– 装饰性内容未标记为 artifactMissingUnicode– 文本缺少 Unicode 映射
实际示例:无障碍报告
从验证结果生成人类可读的无障碍报告:
use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::{validate_pdf_ua, PdfUa级别};
let mut doc = PdfDocument::open("document.pdf")?;
let result = validate_pdf_ua(&mut doc, PdfUa级别::UA1)?;
println!("=== PDF/UA Accessibility Report ===");
println!("级别: 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!(" 结构 elements checked: {}",
result.stats.structure_elements_checked);
下一步
- PDF/A 验证 – 存档合规性
- PDF/X 印刷生产 – 印刷生产合规性
- API 参考 – 完整 Rust API