Validación PDF/A
PDF/A (ISO 19005) es el estándar internacional para el archivado a largo plazo de documentos electrónicos. PDF Oxide valida todos los niveles principales de PDF/A y puede convertir documentos no conformes hacia el cumplimiento.
Niveles soportados
| Level | Standard | Structure | Unicode | Transparency | Embedded Files |
|---|---|---|---|---|---|
| 1a | ISO 19005-1 | Required | Required | No | No |
| 1b | ISO 19005-1 | No | No | No | No |
| 2a | ISO 19005-2 | Required | Required | Yes | No |
| 2b | ISO 19005-2 | No | No | Yes | No |
| 2u | ISO 19005-2 | No | Required | Yes | No |
| 3a | ISO 19005-3 | Required | Required | Yes | Yes |
| 3b | ISO 19005-3 | No | No | Yes | Yes |
| 3u | ISO 19005-3 | No | Required | Yes | Yes |
Nivel “a” (accesible) requiere un árbol de estructura etiquetado y mapeo de caracteres Unicode. Nivel “b” (básico) requiere solo reproducibilidad visual. Nivel “u” (Unicode) requiere mapeo de texto Unicode sin el árbol de estructura completo.
Validación rápida
Use la función de conveniencia para una verificación en una sola llamada:
from pdf_oxide import PdfDocument
doc = PdfDocument("document.pdf")
result = doc.validate_pdf_a("2b")
print(f"Valid: {result.valid}")
print(f"Level: {result.level}")
for error in result.errors:
print(f" Error: {error}")
const doc = new WasmPdfDocument(bytes);
const result = doc.validatePdfA("2b");
console.log(`Valid: ${result.valid}`);
console.log(`Errors: ${result.errors.length}`);
doc.free();
use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::{validate_pdf_a, PdfALevel};
let mut doc = PdfDocument::open("archive.pdf")?;
let result = validate_pdf_a(&mut doc, PdfALevel::A1b)?;
if result.has_errors() {
println!("Not PDF/A-1b 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/A-1b compliant");
}
API del validador
El PdfAValidator proporciona un patrón builder para control detallado:
use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::{PdfAValidator, PdfALevel};
let mut doc = PdfDocument::open("report.pdf")?;
let result = PdfAValidator::new()
.stop_on_first_error(false)
.include_warnings(true)
.validate(&mut doc, PdfALevel::A2b)?;
println!("Errors: {}", result.errors.len());
println!("Warnings: {}", result.warnings.len());
Verificaciones específicas
Ejecute categorías de validación individuales en lugar de la suite completa:
use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::{PdfAValidator, PdfALevel};
let mut doc = PdfDocument::open("report.pdf")?;
let validator = PdfAValidator::new();
// Check only metadata
let result = validator.check_metadata(&mut doc, PdfALevel::A1b)?;
// Check only fonts
let result = validator.check_fonts(&mut doc, PdfALevel::A1b)?;
// Check only color spaces
let result = validator.check_colors(&mut doc, PdfALevel::A1b)?;
// Check only transparency
let result = validator.check_transparency(&mut doc, PdfALevel::A2b)?;
// Check only structure tags
let result = validator.check_structure(&mut doc, PdfALevel::A1a)?;
Validadores independientes
Cada categoría de validación también está disponible como una función independiente para máxima flexibilidad:
use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::validators::*;
use pdf_oxide::compliance::{PdfALevel, ValidationResult};
let mut doc = PdfDocument::open("document.pdf")?;
let mut result = ValidationResult::new(PdfALevel::A1b);
// Run each validator independently
validate_xmp_metadata(&mut doc, PdfALevel::A1b, &mut result)?;
validate_fonts(&mut doc, PdfALevel::A1b, &mut result)?;
validate_colors(&mut doc, PdfALevel::A1b, &mut result)?;
validate_encryption(&mut doc, PdfALevel::A1b, &mut result)?;
validate_transparency(&mut doc, PdfALevel::A1b, &mut result)?;
validate_structure(&mut doc, PdfALevel::A1b, &mut result)?;
validate_javascript(&mut doc, PdfALevel::A1b, &mut result)?;
validate_embedded_files(&mut doc, PdfALevel::A1b, &mut result)?;
validate_annotations(&mut doc, PdfALevel::A1b, &mut result)?;
println!("Total errors: {}", result.errors.len());
Resumen de validadores
| Function | What It Checks |
|---|---|
validate_xmp_metadata() |
XMP stream exists, pdfaid:part and pdfaid:conformance entries present, metadata consistency |
validate_fonts() |
All fonts embedded, glyph widths present, Unicode mapping available (for level “a” and “u”) |
validate_colors() |
No device-dependent color operators (rg, RG, k, K, g, G) without output intent |
validate_encryption() |
No encryption permitted in PDF/A documents |
validate_transparency() |
No transparency in PDF/A-1; allowed in PDF/A-2 and later |
validate_structure() |
Árbol de estructura etiquetado present with valid role mapping (required for level “a”) |
validate_javascript() |
No JavaScript actions or triggers present |
validate_embedded_files() |
Not allowed in PDF/A-1 or PDF/A-2; PDF/A-3 requires AFRelationship key on each file spec |
validate_annotations() |
Tipo de anotacións restricted per the relevant ISO 19005 part |
ValidationResult
La estructura ValidationResult contiene el resultado completo de una ejecución de validación:
pub struct ValidationResult {
pub level: PdfALevel,
pub errors: Vec<ComplianceError>,
pub warnings: Vec<ComplianceWarning>,
pub stats: ValidationStats,
}
| Campo | Tipo | Descripción |
|---|---|---|
level |
PdfALevel |
El nivel de cumplimiento objetivo |
errors |
Vec<ComplianceError> |
Violaciones bloqueantes que impiden el cumplimiento |
warnings |
Vec<ComplianceWarning> |
Problemas no bloqueantes que pueden afectar la calidad |
stats |
ValidationStats |
Conteos de páginas, fuentes y objetos verificados |
ComplianceError
pub struct ComplianceError {
pub code: ErrorCode,
pub message: String,
pub location: Option<String>,
pub clause: Option<String>,
}
El campo code usa el enum ErrorCode con categorías como MissingXmpMetadata, FontNotEmbedded, DeviceDependentColor, EncryptionPresent, TransparencyNotAllowed, MissingStructureTree, JavaScriptPresent e InvalidEmbeddedFile.
ComplianceWarning
pub struct ComplianceWarning {
pub code: WarningCode,
pub message: String,
pub location: Option<String>,
}
Conversión PDF/A
Convierta un documento no conforme hacia el cumplimiento PDF/A:
use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::{convert_to_pdf_a, PdfALevel};
let mut doc = PdfDocument::open("input.pdf")?;
let result = convert_to_pdf_a(&mut doc, PdfALevel::A1b)?;
println!("Conversion actions taken:");
for action in &result.actions {
println!(" - {}: {}", action.action_type, action.description);
}
if result.remaining_errors.is_empty() {
println!("Document is now PDF/A-1b compliant");
} else {
println!("{} issues could not be resolved automatically",
result.remaining_errors.len());
}
Configuración de conversión
Ajuste con precisión el proceso de conversión:
use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::{PdfAConverter, PdfALevel, ConversionConfig};
let mut doc = PdfDocument::open("input.pdf")?;
let config = ConversionConfig::new()
.embed_fonts(true)
.remove_javascript(true)
.flatten_transparency(true)
.add_structure(true);
let result = PdfAConverter::new(PdfALevel::A2b)
.with_config(config)
.convert(&mut doc)?;
El convertidor realiza estas acciones automáticamente:
- Inyección de metadatos XMP – agrega
pdfaid:partandpdfaid:conformanceentries - Incrustación de fuentes – incrusta cualquier fuente referenciada pero no incrustada
- Eliminación de JavaScript – elimina acciones y disparadores de JavaScript
- Aplanamiento de transparencia – renderiza elementos transparentes a opacos (solo PDF/A-1)
- Conversión de perfiles ICC – convierte colores dependientes del dispositivo a espacios de color basados en ICC
- Etiquetado de estructura – agrega etiquetas de estructura básicas (para objetivos de nivel “a”)
Flujo de trabajo: validar, corregir, re-validar
Un flujo de trabajo de archivado típico valida, intenta la conversión automática y luego re-valida:
use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::{validate_pdf_a, convert_to_pdf_a, PdfALevel};
let level = PdfALevel::A2b;
let mut doc = PdfDocument::open("input.pdf")?;
// Step 1: Initial validation
let result = validate_pdf_a(&mut doc, level)?;
if !result.has_errors() {
println!("Already compliant");
return Ok(());
}
println!("{} errors found, attempting conversion...", result.errors.len());
// Step 2: Automatic conversion
let conversion = convert_to_pdf_a(&mut doc, level)?;
println!("{} actions taken", conversion.actions.len());
// Step 3: Re-validate
let result = validate_pdf_a(&mut doc, level)?;
if result.has_errors() {
println!("{} errors remain after conversion:", result.errors.len());
for e in &result.errors {
println!(" {} -- {}", e.code, e.message);
}
} else {
println!("Document is now PDF/A-2b compliant");
}
Métodos de PdfALevel
El enum PdfALevel incluye métodos auxiliares para consultar las capacidades del nivel:
| Method | Return | Descripción |
|---|---|---|
part() |
PdfAPart |
ISO 19005 part (Part1, Part2, Part3) |
conformance() |
char |
Conformance letter (‘a’, ‘b’, or ‘u’) |
requires_structure() |
bool |
Si el árbol de estructura etiquetado es obligatorio |
requires_unicode() |
bool |
Si el mapeo Unicode es obligatorio |
allows_transparency() |
bool |
Si la transparencia está permitida |
allows_jpeg2000() |
bool |
Si las imágenes JPEG 2000 están permitidas |
allows_embedded_files() |
bool |
Si los adjuntos de archivo están permitidos |
xmp_part() |
&str |
XMP pdfaid:part value |
xmp_conformance() |
&str |
XMP pdfaid:conformance value |
from_xmp(part, conformance) |
Option<Self> |
Parse level from XMP metadata values |
Próximos pasos
- PDF/UA Accessibility – accessibility validation
- PDF/X Print Production – print production validation
- API Reference – complete Rust API