コンテンツにスキップ

契約 / 抽出

抽出ドメインは、PDF を読み取り、検証し、その内容を構造化データに変換するための契約を保持します。対象には、インスペクター、コンプライアンスバリデーター、PDF/A マネージャー、インポートされたオブジェクトの契約、埋め込みとベクトルインデックスの契約、そして e-invoice バリデーターのサブ名前空間が含まれます。

Terminal window
composer require nextpdf/core:^3

InspectorInterface は生の PDF を読み取り、構造化された InspectResult を返します。この結果には、ファイル内のオブジェクト一覧が含まれます。エンジンが書き込んだものではない PDF を読み取るすべてのツールで使用してください。

ExternalComplianceValidatorInterface は、veraPDF などの外部チェッカーとの橋渡しをします。チェッカーは PDF/A と PDF/UA をテストします。チェッカーが設定されていない場合、null バージョンは「利用不可」の結果を返します。これにより、veraPDF のないサイトでも引き続き動作します。ProfileValidatorInterface は、ランタイムをデプロイメントプロファイルと照合し、必須および推奨の拡張機能を確認して、型付きの判定結果を返します。

PdfAManagerInterface は、PDF/A ファイルの書き込み中、そのファイルを仕様準拠の状態に保ちます。JavaScript、JavaScript フォームアクション、組み込みの暗号化をブロックします。PDF/A はこの 3 つすべてを禁止しています。また、すべてのフォントが埋め込まれていることを確認し、仕様に準拠したメタデータを設定して、必要なオブジェクトをカタログの前に書き込みます。実際のクラスは Pro エディションに同梱されています。Core は class_exists() でそれを検出し、契約にキャストします。そのため、オープンソースエンジンには有償の依存関係がありません。

インポートされたオブジェクトは、ImportedFormObjectInterfaceEmbeddedPdfObjectInterface の 2 つの契約でカバーされます。これらは、既存の PDF から読み取られたオブジェクトへの型付きアクセスを提供します。その後、エンジンはそれらを再埋め込みできます。ロスレスパスでは、生の辞書バイトを保持します。フォールバックパスでは、オブジェクトストリームから取得したオブジェクトに対して、解析済みの辞書配列を提供します。再埋め込みされる各オブジェクトは PDF 間接オブジェクトです。オブジェクト番号と世代番号で識別されます — ISO 32000-2 §7.3.10。

埋め込み契約は、検索処理に役立ちます。EmbeddingServiceInterface はテキストを密ベクトルに変換し、モデルのサイズと名前を報告します。呼び出し側は実行時に適応します。Pro エディションは CPU モデルを実行し、Enterprise エディションは GPU モデルを実行します。VectorIndexInterface は、最近傍インデックスを構築し、検索します。これは、コアで使用するための小規模なインプロセスインデックスです。より大規模な検索は、Enterprise 専用の契約に含まれます。

EInvoice グループは、ティアをまたぐ e-invoice チェッカーを保持します。ValidatorInterface は、CII または UBL ペイロードに対してプリフライトチェックを実行します。SchematronRunnerInterface は、ビジネスルールのパスを実行します。ValidationResult は、検出結果とルール違反を収集します。チェッカーは、不正な入力を例外ではなく結果として拒否しなければなりません。また、DOCTYPE と過大なペイロードに対しても防御しなければなりません。

種別主なメンバー安定性導入バージョン
InspectorInterfaceインターフェイスinspect(string, InspectConfig): InspectResult実験的2.2.0
ExternalComplianceValidatorInterfaceインターフェイスvalidate(string, ComplianceFlavour), isAvailable()実験的2.4.0
ProfileValidatorInterfaceインターフェイスvalidate(DeploymentProfile): DeploymentProfileResult実験的2.4.0
PdfAManagerInterfaceインターフェイスvalidateNoJavaScript(), validateFont(), validateNoEncryption(), applyOutputProfile(), writeRequiredObjects()安定版1.10.0
ImportedFormObjectInterfaceインターフェイスgetWidth(), getHeight(), getEmbeddedObjects(), getResourcesDict(), getMediaBox(), getContentStream()安定版1.8.0
EmbeddedPdfObjectInterfaceインターフェイスgetRawDictionaryBytes(), getRawStreamData(), getDictionary()安定版1.8.0
EmbeddingServiceInterfaceインターフェイスembed(), batchEmbed(), getDimension(), getModelName()実験的2.1.0
VectorIndexInterfaceインターフェイスbuild(), search(), delete(), count()実験的2.1.0
EInvoice\ValidatorInterfaceインターフェイスvalidate(string, ValidatorContext): ValidationResult実験的5.1.0
EInvoice\ValidationResultfinal readonly クラス$isValid, getErrors(), getWarnings(), fail()実験的5.1.0

EInvoice 名前空間は、SchematronRunnerInterfaceProfileInterfaceValidationFindingRuleViolation、および ProfileTypeRuleSeverityValidationFindingLevel の各列挙型も公開します。

examples/contracts/extraction-quickstart.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\InspectorInterface;
use NextPDF\Inspect\InspectConfig;
/**
* Inspect a PDF and report its object count.
*
* @param InspectorInterface $inspector A configured inspector.
* @param string $pdfData Raw PDF bytes.
*/
function describe(InspectorInterface $inspector, string $pdfData): \NextPDF\Inspect\InspectResult
{
return $inspector->inspect($pdfData, new InspectConfig());
}

この関数は契約に依存します。インスペクターの実装であれば、どの実装でもこの契約を満たします。

examples/contracts/extraction-production.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\EInvoice\ValidatorInterface;
use NextPDF\Contracts\EInvoice\ValidatorContext;
use NextPDF\Contracts\ExternalComplianceValidatorInterface;
use NextPDF\ValueObjects\ComplianceFlavour;
use Psr\Log\LoggerInterface;
final readonly class InvoiceConformanceService
{
public function __construct(
private ValidatorInterface $invoiceValidator,
private ExternalComplianceValidatorInterface $pdfaValidator,
private LoggerInterface $logger,
) {}
/**
* Validate the invoice XML, then the PDF/A-3 carrier.
*
* @param string $xml The CII or UBL invoice payload.
* @param string $pdfPath Absolute path to the PDF/A-3 carrier.
*/
public function validate(string $xml, string $pdfPath, ValidatorContext $ctx): bool
{
$result = $this->invoiceValidator->validate($xml, $ctx);
if (!$result->isValid) {
$this->logger->warning('Invoice XML invalid', [
'errors' => \count($result->getErrors()),
]);
return false;
}
if (!$this->pdfaValidator->isAvailable()) {
$this->logger->info('PDF/A validator unavailable; skipping carrier check.');
return true;
}
$carrier = $this->pdfaValidator->validate($pdfPath, ComplianceFlavour::PdfA3b);
return $carrier->isConformant();
}
}

このサービスは、バリデーターの存在を仮定せず、利用不可のケースを明示的に処理します。

  • EInvoice\ValidatorInterface::validate() は、形式が不正な入力に対して、失敗した ValidationResult を返します。整形式違反に対して例外をスローしません。このケースでは $isValid を確認し、呼び出しを try/catch でラップしないでください。
  • ExternalComplianceValidatorInterface::isAvailable() は、判定結果に依存する前に確認しなければなりません。null 実装は「利用不可」を返します。それを「非準拠」として扱うと、偽陰性が生じます。
  • EmbeddedPdfObjectInterface::getRawDictionaryBytes() は、オブジェクトストリームから取得したオブジェクトに対しては null を返します。getDictionary() にフォールバックしてください。生のバイトが存在すると仮定しないでください。
  • EmbeddingServiceInterface::getDimension() はティアによって異なります。固定幅のベクトルを割り当てるコードは、次元をハードコードするのではなく、実行時に読み取らなければなりません。
  • VectorIndexInterface::build() は、ベクトルリストと ID リストの長さが等しく、一貫した次元を持つことを要求します。不一致がある場合は InvalidArgumentException が発生します。構築する前に検証してください。

検査と検証のコストは、ドキュメントのサイズとオブジェクト数に応じて増加します。ウォール時間 1500 ms およびピーク 64 MB という performance_budget は、中程度の単一ドキュメントをカバーします。外部 veraPDF 呼び出しでは、バリデーター自体のプロセス時間が加算されます。そのプロセス時間はエンジンの予算外であり、リクエストパスの外で実行すべきです。埋め込みのコストはテキストの長さに応じて増加し、特に GPU モデルでは、ループで処理するよりバッチ化するほうがはるかに安価です。batchEmbed() を優先してください。ベクトル検索は、インプロセスインデックスではインデックスサイズに対して準線形です。再現性プロファイルは structural です。検証レポートには、タイムスタンプと環境フィンガープリントが記録されます。2 回の実行ではこれらのフィールドが異なりますが、準拠の判定結果は同一のままです。

抽出では、エンジンが作成したものではないドキュメントを読み取るため、すべての入力は信頼できません。インスペクターと e-invoice バリデーターはどちらも、外部から提供されたバイトを解析します。e-invoice バリデーターは、XML 外部実体攻撃や billion-laughs 攻撃を防ぐために、解析の前に DOCTYPE、過大なペイロード、および禁止された制御文字を含むペイロードをゲートしなければなりません。インポートされたオブジェクトの再埋め込みでは、外部の PDF からバイトをコピーします。悪意のあるソースオブジェクトは敵対的なコンテンツを含む可能性があるため、再埋め込みではバイトを実行せずに保持します。PDF/A の強制は、JavaScript とアクションを除去します。PDF/A マネージャーが JavaScript と暗号化を拒否するのは、どちらもプロファイルで禁止されており、かつどちらも長期保存される保管ドキュメントにおける悪用ベクトルだからです。検査されたコンテンツ、インポートされたオブジェクト、および invoice XML は、全体を通じて敵対的な入力として扱ってください。

主張標準条項エビデンス
PDF/A-4 は JavaScript と JavaScript フォームアクションを禁止しており、PDF/A マネージャーは両方を拒否します。ISO 19005-4§6.7.1条項により引用(コーパス外)
再埋め込みされる各オブジェクトは、オブジェクト番号と世代で識別される PDF 間接オブジェクトです。ISO 32000-2§7.3.10

ISO 19005-4 は条項により参照されています。これは検証可能な引用コーパスに含まれていないため、reference_id は記録されません。ISO 32000-2 の間接オブジェクトに関する主張は、用語集にピン留めされています。どちらも言い換えられています。エンジンは規範的なテキストを一切再現しません。

Core は、抽出契約を定義し、それを凍結します。PdfAManagerInterfaceEmbeddingServiceInterface、および VectorIndexInterface の背後にある本番コードは、CPU および GPU の埋め込みモデルと完全な PDF/A 強制パスを含めて、Pro および Enterprise エディションに同梱されています。Core は、実行時に class_exists() でこれらを resolve(解決)します。そのため、オープンソースエンジンは商用の依存関係を持たず、API はアップグレード時に変更されません。