PDF/A 検証
PDF/A(ISO 19005)は、電子文書を長期保存するための国際標準です。PDF Oxide は主要な PDF/A レベルをすべて検証でき、非準拠の文書を準拠へと変換することもできます。
バインディング対応状況。 PDF/A 検証は Python(
doc.validate_pdf_a(level))、Rust(validate_pdf_a+PdfAValidatorビルダー)、WASM(doc.validatePdfA(level))、Go(doc.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() |
出力インテントを伴わないデバイス依存のカラー演算子(rg、RG、k、K、g、G)の不使用 |
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 フィールドは、MissingXmpMetadata、FontNotEmbedded、DeviceDependentColor、EncryptionPresent、TransparencyNotAllowed、MissingStructureTree、JavaScriptPresent、InvalidEmbeddedFile などのカテゴリを持つ 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)?;
コンバーターは次のアクションを自動的に実行します。
- XMP メタデータの挿入 –
pdfaid:partおよびpdfaid:conformanceエントリを追加する - フォントの埋め込み – 参照されているが埋め込まれていないフォントを埋め込む
- JavaScript の削除 – JavaScript アクションとトリガーを除去する
- 透過のフラット化 – 透過要素を不透明にレンダリングする(PDF/A-1 のみ)
- ICC プロファイルへの変換 – デバイス依存の色を ICC ベースのカラースペースに変換する
- 構造タグ付け – 基本的な構造タグを追加する(レベル「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 メタデータの値からレベルを解析する |
次のステップ
- PDF/UA アクセシビリティ – アクセシビリティ検証
- PDF/X 印刷制作 – 印刷制作の検証
- API リファレンス – 完全な Rust API