Skip to content

PDF/A 検証

PDF/A(ISO 19005)は、電子文書を長期保存するための国際標準です。PDF Oxide は主要な PDF/A レベルをすべて検証でき、非準拠の文書を準拠へと変換することもできます。

バインディング対応状況。 PDF/A 検証は Pythondoc.validate_pdf_a(level))、Rustvalidate_pdf_a + PdfAValidator ビルダー)、WASMdoc.validatePdfA(level))、Godoc.ValidatePdfA(level))で利用できます。公開されている C# ラッパーはまだ提供されていません。Rust の CLI(pdf-oxide validate --pdfa 2b doc.pdf)を使うか、対応バインディングのいずれかを経由して呼び出してください。PDF/A 変換PdfAConverter)は現在 Rust と Python でのみ公開されています。

対応レベル

レベル 標準 構造 Unicode 透過 埋め込みファイル
1a ISO 19005-1 必須 必須 不可 不可
1b ISO 19005-1 不要 不要 不可 不可
2a ISO 19005-2 必須 必須 不可
2b ISO 19005-2 不要 不要 不可
2u ISO 19005-2 不要 必須 不可
3a ISO 19005-3 必須 必須
3b ISO 19005-3 不要 不要
3u ISO 19005-3 不要 必須

レベル「a」(アクセシブル)はタグ付き構造ツリーと Unicode 文字マッピングを必要とします。レベル「b」(基本)は視覚的な再現性のみを必要とします。レベル「u」(Unicode)は完全な構造ツリーを伴わない Unicode テキストマッピングを必要とします。

クイック検証

ワンコールで確認するには便利関数を使います。

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");
}
package main

import (
    "fmt"
    "log"
    pdfoxide "github.com/yfedoseev/pdf_oxide/go"
)

func main() {
    doc, err := pdfoxide.Open("archive.pdf")
    if err != nil { log.Fatal(err) }
    defer doc.Close()

    // Level encoding: 0 = 1b, 1 = 1a, 2 = 2b, 3 = 2a, 4 = 2u, 5 = 3b, 6 = 3a, 7 = 3u
    result, err := doc.ValidatePdfA(0) // PDF/A-1b
    if err != nil { log.Fatal(err) }

    if result.Valid {
        fmt.Println("Document is PDF/A-1b compliant")
    } else {
        fmt.Println("Not PDF/A-1b compliant:")
        for _, e := range result.Errors {
            fmt.Printf("  %s\n", e)
        }
    }
}

バリデーター API

PdfAValidator は、きめ細かな制御のためのビルダーパターンを提供します。

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());

個別チェック

完全なスイートではなく、個々の検証カテゴリを実行します。

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)?;

スタンドアロンバリデーター

各検証カテゴリは、最大限の柔軟性を実現するためにスタンドアロン関数としても利用できます。

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());

バリデーター一覧

関数 チェック内容
validate_xmp_metadata() XMP ストリームの存在、pdfaid:part および pdfaid:conformance エントリの有無、メタデータの整合性
validate_fonts() すべてのフォントの埋め込み、グリフ幅の有無、Unicode マッピングの利用可否(レベル「a」と「u」向け)
validate_colors() 出力インテントを伴わないデバイス依存のカラー演算子(rgRGkKgG)の不使用
validate_encryption() PDF/A 文書では暗号化は許可されない
validate_transparency() PDF/A-1 では透過は不可。PDF/A-2 以降では許可
validate_structure() 有効なロールマッピングを伴うタグ付き構造ツリーの存在(レベル「a」で必須)
validate_javascript() JavaScript アクションやトリガーが存在しないこと
validate_embedded_files() PDF/A-1 および PDF/A-2 では不可。PDF/A-3 では各ファイル仕様に AFRelationship キーが必要
validate_annotations() 該当する ISO 19005 のパートに従って注釈タイプが制限される

ValidationResult

ValidationResult 構造体には、検証実行の完全な結果が含まれます。

pub struct ValidationResult {
    pub level: PdfALevel,
    pub errors: Vec<ComplianceError>,
    pub warnings: Vec<ComplianceWarning>,
    pub stats: ValidationStats,
}
フィールド 説明
level PdfALevel 対象の準拠レベル
errors Vec<ComplianceError> 準拠を妨げるブロッキング違反
warnings Vec<ComplianceWarning> 品質に影響する可能性のある非ブロッキングの問題
stats ValidationStats チェックしたページ、フォント、オブジェクトの数

ComplianceError

pub struct ComplianceError {
    pub code: ErrorCode,
    pub message: String,
    pub location: Option<String>,
    pub clause: Option<String>,
}

code フィールドは、MissingXmpMetadataFontNotEmbeddedDeviceDependentColorEncryptionPresentTransparencyNotAllowedMissingStructureTreeJavaScriptPresentInvalidEmbeddedFile などのカテゴリを持つ ErrorCode 列挙型を使用します。

ComplianceWarning

pub struct ComplianceWarning {
    pub code: WarningCode,
    pub message: String,
    pub location: Option<String>,
}

PDF/A 変換

非準拠の文書を 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());
}

変換構成

変換プロセスを細かく調整します。

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)?;

コンバーターは次のアクションを自動的に実行します。

  1. XMP メタデータの挿入pdfaid:part および pdfaid:conformance エントリを追加する
  2. フォントの埋め込み – 参照されているが埋め込まれていないフォントを埋め込む
  3. JavaScript の削除 – JavaScript アクションとトリガーを除去する
  4. 透過のフラット化 – 透過要素を不透明にレンダリングする(PDF/A-1 のみ)
  5. ICC プロファイルへの変換 – デバイス依存の色を ICC ベースのカラースペースに変換する
  6. 構造タグ付け – 基本的な構造タグを追加する(レベル「a」を対象とする場合)

ワークフロー: 検証、修正、再検証

典型的な保存ワークフローでは、検証を行い、自動変換を試みた後、再検証します。

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");
}

PdfALevel のメソッド

PdfALevel 列挙型には、レベルの機能を照会するためのヘルパーメソッドが含まれています。

メソッド 戻り値 説明
part() PdfAPart ISO 19005 のパート(Part1、Part2、Part3)
conformance() char 適合性を表す文字(‘a’、‘b’、‘u’)
requires_structure() bool タグ付き構造ツリーが必須かどうか
requires_unicode() bool Unicode マッピングが必須かどうか
allows_transparency() bool 透過が許可されるかどうか
allows_jpeg2000() bool JPEG 2000 画像が許可されるかどうか
allows_embedded_files() bool ファイル添付が許可されるかどうか
xmp_part() &str XMP の pdfaid:part の値
xmp_conformance() &str XMP の pdfaid:conformance の値
from_xmp(part, conformance) Option<Self> XMP メタデータの値からレベルを解析する

次のステップ