コンテンツにスキップ

セマンティックコンテンツからタグ付き PDF/UA-2 の構造ツリーを出力する

このレシピでは、ISO 14289-2(PDF/UA-2)を対象とするタグ付き PDF を作成します。NextPDF は、論理構造ツリー、マーク付きコンテンツシーケンス、カタログ言語、およびドキュメントレベルの識別メタデータを出力します。この構造はアクセシブルなオーサリングをサポートしますが、適合性は独立したチェッカーが判定します。このレシピは examples/31-pdfua2-tagged.php に沿っています。

Terminal window
composer require nextpdf/core:^3

検証ステップには、PATH 上に PDF/UA-2 チェッカーが必要です。このレシピの例では、ua2 フレーバーの veraPDF を使用します。タグ付き構造を出力するために Pro または Enterprise のパッケージは必要ありません。

タグ付き PDF は、視覚的なコンテンツストリームと並行して 論理構造ツリー を保持します。支援技術はピクセルレイアウトではなくこのツリーを読み取るため、支援技術に提示される読み上げ順序は構造によって決まります。ISO 14289-2 は、この点について 4 つの要件を定めています。実体(非アーティファクト)コンテンツは、そのツリーを通じて到達可能でなければなりません(§8.2.2)。構造要素は、定義された順序でネストしなければなりません(§8.2.3)。すべての要素は、直接または役割マッピングによって、既知の構造名前空間に resolve(解決)されなければなりません(§8.2.4)。そして、コンテンツの自然言語はドキュメントレベルで宣言され、異なる場合は構造要素ごとに指定されます(§8.4.4)。

NextPDF は、これを型付きの ConformanceMode でモデル化します。enableTaggedPdf()ConformanceMode::PdfUa2 を設定します。これにより、(a) HTML パイプラインがパーサー構築時に TaggedContentEmitter を接続し、(b) タグ付き PDF を示すカタログの MarkInfoMarked フラグを設定し(ISO 32000-2 §14.7)、(c) カタログの Lang エントリ用に BCP-47 言語を記録します。ライターは、タブ順序が構造順序に従うように、ページごとの Tabs エントリも出力します(ISO 32000-2 §14.8)。

厳格な UA-2 の不変条件は、ConformanceMode::PdfUa2 にのみ適用されます。他のモードに対して厳格な ConformancePolicy を構築すると、設計上 InvalidConfigException がスローされます。

API サーフェスは PHPDoc から生成されます。主要なエントリポイントは次のとおりです。

  • \NextPDF\Core\Document::createStandalone(): Document
  • Document::enableTaggedPdf(string $lang = 'en', ?ConformancePolicy $policy = null): static
  • Document::setLanguage(string $lang): static
  • \NextPDF\Conformance\ConformancePolicy::strictUa2(): self
  • \NextPDF\Conformance\ConformanceMode::PdfUa2enableTaggedPdf() によって設定されるモード)
  • Document::beginTag(string $type): static / Document::endTag(): static(非 HTML コンテンツの手動タグ付け)
examples/31-pdfua2-tagged.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
// Enable tagged mode BEFORE writeHtml(). The HTML pipeline detects the
// mode at parser construction time and wires the tagged-content emitter.
$doc->enableTaggedPdf(lang: 'en');
$doc->setTitle('Quarterly Accessibility Report');
$doc->setLanguage('en');
$doc->addPage();
$doc->writeHtml(<<<'HTML'
<h1>Quarterly Accessibility Report</h1>
<p>This document opts into tagged PDF so assistive technology can expose
a meaningful reading order.</p>
<ul>
<li>Headings carry semantic roles.</li>
<li>Lists keep their item structure.</li>
</ul>
HTML);
$doc->save(__DIR__ . '/output/31-pdfua2-tagged.pdf');
echo "Created: output/31-pdfua2-tagged.pdf\n";

これは、ハーネスで実行できる自己完結型のプログラムです。本番の呼び出し側では、不正な形式の言語タグを外部チェッカー実行時まで待って検出するのではなく、早期に失敗させます。API 境界で無効な BCP-47 タグを拒否するには ConformancePolicy::strictUa2() を渡し、その後はチェッカーの判定でビルドをゲートします。

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Conformance\ConformancePolicy;
use NextPDF\Core\Document;
use NextPDF\Exception\InvalidConfigException;
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT') ?: (__DIR__ . '/accessible.pdf');
try {
$doc = Document::createStandalone();
// Strict UA-2: a malformed BCP 47 tag throws here, not silently at
// write time. strictUa2() also forces the §8.4.4 Lang validation.
$doc->enableTaggedPdf(lang: 'en-GB', policy: ConformancePolicy::strictUa2());
$doc->setTitle('Accessible Annual Report 2026');
$doc->setLanguage('en-GB');
$doc->addPage();
$doc->writeHtml(<<<'HTML'
<h1>Annual Report 2026</h1>
<p>Audited results for the financial year ending March 2026.</p>
<h2>Segment performance</h2>
<table>
<tr><th>Segment</th><th>Revenue</th></tr>
<tr><td>Cloud</td><td>42.1</td></tr>
<tr><td>Services</td><td>18.7</td></tr>
</table>
HTML);
$doc->save($out);
} catch (InvalidConfigException $e) {
fwrite(STDERR, "Tagged PDF/UA-2 setup rejected: {$e->getMessage()}\n");
exit(1);
}
// The gate is the checker, not the library.
$exitCode = 0;
$report = [];
exec('verapdf --flavour ua2 ' . escapeshellarg($out), $report, $exitCode);
if ($exitCode !== 0) {
fwrite(STDERR, "veraPDF FAILED — output is not PDF/UA-2 conforming\n");
fwrite(STDERR, implode("\n", $report) . "\n");
exit(1);
}
echo "veraPDF PASS — accessible.pdf carries a conforming UA-2 structure\n";

予想される STDOUT は、verapdf --flavour ua2 がファイルを適合していると報告するホストでは、次のとおりです。

veraPDF PASS — accessible.pdf carries a conforming UA-2 structure

enableTaggedPdf() が言語タグを拒否した場合、プログラムは STDERR に Tagged PDF/UA-2 setup rejected: … を出力した後、非ゼロで終了します。チェッカーが問題を報告した場合は、veraPDF FAILED — output is not PDF/UA-2 conforming の後、非ゼロで終了します。判定はチェッカーが下すものです。NextPDF は構造を出力しますが、適合性を主張するわけではありません。

  • 呼び出し順序。 enableTaggedPdf()writeHtml() の後に呼び出しても、すでに書き込まれたコンテンツに遡ってタグを付けることはできません。まずタグ付きモードを有効にしてください。
  • 厳格な言語ゲート。 ポリシーを指定しない場合、解析不能な BCP-47 タグは黙って破棄され、チェッカーの実行時にのみ表面化します。ConformancePolicy::strictUa2() を使用すると、同じタグは enableTaggedPdf() の境界で InvalidConfigException をスローします(ISO 14289-2 §8.4.4 の厳格パス)。
  • 冪等な再有効化。 enableTaggedPdf() を 2 回呼び出しても、構築済みの構造ツリーを再構築することなく言語が更新されます。
  • 手動タグ付け。 非 HTML コンテンツの場合は、対象を beginTag() / endTag() で囲みます。コンテナの役割(TableTRLLI)は、マーク付きコンテンツを持たないグループ化要素になります。リーフの役割(PH1H6TD)には MCID が付与されます。
  • モードの排他性。 厳格な ConformancePolicyConformanceMode::PdfUa2 でのみ有効です。厳格な UA-2 フラグを PDF/A モードと組み合わせると、InvalidConfigException がスローされます。タグ付きモードと PDF/A プロファイルを別々に有効にすることで、タグ付き PDF/A の成果物を構成できます。

構造ツリーは、軽量な辞書からなる並行ツリーを 1 つと、テキストラン単位の BDC/EMC 演算子を追加します。典型的なレポートでは、オーバーヘッドは出力サイズの数パーセントであり、2000 ms / 128 MB の予算に十分に収まります。ここでは意味論的な再現性プロファイルが適用されます。チェッカー指向の成果物は、生のバイト列ではなく、構造的な抽象構文木(AST)とメタデータによって比較されるためです。「適合性」セクションを参照してください。

構造ツリーは、可視コンテンツと同じテキストを保持します。ソース HTML に個人データが含まれる場合、そのデータはツリーを通じて、また ActualText/Alt 属性を通じても到達可能になります。可視コンテンツに対して行うのと同じ墨消しと最小化を、オーサリング前に適用してください。タグ付けによって新たな流出経路が増えることはありませんが、設計上、テキストがプログラムから抽出可能になります。

このレシピは、固定された進捗行のみを STDOUT に書き込みます。PDF は、ハーネスのサイドチャネル(NEXTPDF_COOKBOOK_OUTPUT)または呼び出し側のパスにルーティングされます。ドキュメントのテキストがログに記録されることはありません。コンテンツの断片を反映しうるチェッカーの出力は、共有ログに残さないでください。

タグ付き PDF は信頼境界ではありません。敵対的なプロデューサーは、構造的には整形式だが誤解を招くツリーを出力できるため、自動処理のために構造ツリーを信頼する利用者は、依然としてファイルを検証する必要があります。構造は、完全性や真正性の信号ではなく、アクセシビリティのためのアフォーダンスとして扱ってください。

このレシピは暗号操作を一切行いません。FIPS モードによってその動作が変わることはありません。署名も暗号化も関与しません。

PDF/UA-2 要件NextPDF が出力するもの条項
実体コンテンツの構造ツリー内配置StructTreeRoot(ブロックごとの StructElem と MCID でリンクされたマーク付きコンテンツを持つ)ISO 14289-2 §8.2.2
定義されたネストと読み上げ順序ドキュメント順序で grouping/leaf の役割にマッピングされたブロック要素ISO 14289-2 §8.2.3
既知の構造名前空間PDF 2.0 名前空間内の役割、必要に応じた HTML タグの役割マッピングISO 14289-2 §8.2.4
ドキュメントおよび要素の言語BCP-47 タグ由来のカタログ Lang、相違時の要素ごとの LangISO 14289-2 §8.4.4
テキスト代替を持つ非テキストコンテンツAlt/ActualText の figure/non-text 構造要素への付与ISO 14289-2 §8.5.1
テーブルの関係Table/TR/TH/TD の役割(ヘッダー関連付けを伴う)ISO 14289-2 §8.2.5.26
パート識別メタデータ保存時にスケジュールされるドキュメントレベルの識別ISO 14289-2 の §序論(pdfua2#p17

PDF/UA-2 は、ISO 32000-2 のタグ付き PDF の仕組みの上に、アクセシビリティ要件を重ねます。NextPDF が依拠するマッピングは次のとおりです。

NextPDF の出力ISO 32000-2 §14 の機能条項
論理構造ツリー(StructTreeRootタグ付き PDF の論理構造§14.7(iso32000_2_sec14#x1.x38.p13
カタログ MarkInfo << /Marked true >>タグ付き PDF のマーカー§14.7(iso32000_2_sec14#x1.x40.p3
構造順序に従うページごとの Tabs エントリ構造ナビゲーション / タブ順序§14.8(iso32000_2_sec14#x1.x50

PDF/UA-2 は、WCAG 2.2 がフォーマット非依存で示す構造要件を、PDF フォーマットとして表現したものです。関連する対応関係は次のとおりです。

WCAG 2.2 の達成基準このレシピが実現する PDF/UA-2 のメカニズム
1.3.1 情報および関係性(レベル A)構造ツリーによる、見出し、リスト、テーブルの関係性のプログラム的な判別可能性(wcag_2_2#x2.x3.x3.x1.p3
1.3.2 意味のあるシーケンス(レベル A)構造順序による、視覚的レイアウトから独立した読み上げ順序の定義
3.1.1 ページの言語(レベル A)BCP-47 タグ由来のカタログ Lang エントリ
1.1.1 非テキストコンテンツ(レベル A)Alt/ActualText の非テキスト構造要素への付与(ISO 14289-2 §8.5.1)

このマッピングは、出力された構造が WCAG 2.2 の基準をどこでサポートするかを示すものです。これは WCAG 適合の主張ではありません。WCAG 適合はユーザーエクスペリエンス全体を対象とし、プロデューサーではなくアクセシビリティ評価によって判定されます。

記述仕様条項リファレンス ID
実体コンテンツに必要な論理構造ISO 14289-2§8.2.2
定義されたネストと読み上げ順序に従う構造要素ISO 14289-2§8.2.3
直接または役割マッピングによる、すべての構造要素の既知の名前空間への解決ISO 14289-2§8.2.4
ドキュメントレベルおよび構造要素レベルでの自然言語の宣言ISO 14289-2§8.4.4
非テキストコンテンツのテキスト代替ISO 14289-2§8.5.1
row/header/data の関係性を保持するテーブルセルISO 14289-2§8.2.5.26
カタログの MarkInfoMarked フラグによるタグ付き PDF のマーカーISO 32000-2§14.7
プロデューサーの主張ではなく、パートに対する適合性判定ISO 14289-2§8.14.2

NextPDF は、アクセシブルなオーサリングをサポートするタグ付き構造を出力します。サポートは適合ではありません。 このレシピは PDF/UA-2 適合を主張しません。その判定は、独立したチェッカー(たとえば veraPDF)が下します。ファイルが適合していると述べる前に、チェッカーを実行してください。