Skip to content

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:

  1. Inyección de metadatos XMP – agrega pdfaid:part and pdfaid:conformance entries
  2. Incrustación de fuentes – incrusta cualquier fuente referenciada pero no incrustada
  3. Eliminación de JavaScript – elimina acciones y disparadores de JavaScript
  4. Aplanamiento de transparencia – renderiza elementos transparentes a opacos (solo PDF/A-1)
  5. Conversión de perfiles ICC – convierte colores dependientes del dispositivo a espacios de color basados en ICC
  6. 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