Pro edition
Extraction
At a glance
Section titled “At a glance”NextPDF\Pro\Extraction walks a parsed document AST and produces text and
table blocks, each carrying a citation anchor (page index, bounding box,
node reference). It is a deterministic structural extractor for source-
attribution pipelines, not a search or understanding engine.
Availability & licensing
Section titled “Availability & licensing”This capability ships in NextPDF Pro (nextpdf/pro) and activates with a
Pro-tier license envelope. A deployment without that entitlement does not load the capability’s classes. No runtime capability
flag gates this module; the Extraction classes are available whenever
nextpdf/pro is installed. Compare editions and get a license.
Install
Section titled “Install”composer require nextpdf/pro:^3Conceptual overview
Section titled “Conceptual overview”Both extractors take a NextPDF\Ast\AstDocument — a parsed document tree
produced by the Core AST subsystem. They do not parse raw PDF bytes
themselves; the AST is the input boundary.
CitedTextExtractorwalks the tree and emits aCitedTextBlockfor each substantive text node (paragraph, heading, list item, table cell, code, annotation) whose trimmed text meets a minimum length. An optional token budget splits long text at sentence boundaries. Each block carries aCitationAnchorwith node id, page index, bounding box, and a confidence read from the node (default 1.0). Nodes without a bounding box receive a zero-area sentinel box so the anchor is always valid.CitedTableExtractorfindsTablenodes, reads their rows and cells, and builds a rectangular row-major matrix padded to the widest row. Nested tables are not recursed into. Cell confidence defaults to 0.8 unless the node carries an explicit value.
The structural hierarchy these extractors traverse corresponds to the PDF logical-structure model (ISO 32000-2:2020 §14.7) and table structure elements (§14.8) when the source document is tagged.
Why it works this way
Section titled “Why it works this way”The extractor takes a parsed AST as its input boundary, not raw PDF bytes, so parsing risk stays separate from extraction logic. Confidence is read straight from the AST node and passed through unchanged; the module never computes, ranks, or improves it. Output stays in document order, not relevance order, because source attribution needs verifiable provenance rather than a heuristic guess the extractor cannot defend. Every block carries a citation anchor — node id, page index, bounding box — so a downstream pipeline can trace each quotation back to its origin. This deliberately keeps the module a deterministic structural extractor: it reports what the AST asserts and declines to invent anything the document does not state.
Design background: An API that refuses to guess.
Behavior contract
Section titled “Behavior contract”- Input. A
NextPDF\Ast\AstDocument. The module does not accept raw PDF bytes; produce the AST with the Core AST subsystem first. - Output.
list<CitedTextBlock>orlist<CitedTableBlock>in document order. - Confidence is passthrough. It is read from the AST node attributes (or a fixed default). This module does not compute or improve confidence.
- No semantic processing. The extractor performs no embedding, vector similarity, ranking, or document understanding. Output ordering is document order, not relevance order.
- Determinism. For an identical AST the produced blocks, anchors, and chunk indices are stable.
Public API surface
Section titled “Public API surface”| Type | Kind | Key members |
|---|---|---|
NextPDF\Pro\Extraction\CitedTextExtractor | final class | __construct(?int $maxTokensPerChunk = null, int $minChunkLength = 10), extract(AstDocument $document): list<CitedTextBlock> |
NextPDF\Pro\Extraction\CitedTableExtractor | final class | extract(AstDocument $document): list<CitedTableBlock> |
NextPDF\Pro\Extraction\CitedTextBlock | final readonly class | string $text, CitationAnchor $anchor, float $confidence, int $chunkIndex, array $metadata, estimatedTokens(): int |
NextPDF\Pro\Extraction\CitedTableBlock | final readonly class | string $nodeId, int $pageIndex, int $rowCount, int $colCount, array $matrix |
NextPDF\Pro\Extraction\CitedTableCell | final readonly class | int $row, int $col, ?string $textContent, float $confidence |
Code sample — Quick start
Section titled “Code sample — Quick start”<?php
declare(strict_types=1);
use NextPDF\Pro\Extraction\CitedTextExtractor;
/** @var \NextPDF\Ast\AstDocument $ast */$blocks = (new CitedTextExtractor())->extract($ast);
foreach ($blocks as $block) { printf( "p%d chunk#%d (%d tokens): %s\n", $block->anchor->pageIndex, $block->chunkIndex, $block->estimatedTokens(), $block->text, );}Code sample — Production
Section titled “Code sample — Production”<?php
declare(strict_types=1);
use NextPDF\Pro\Extraction\CitedTextExtractor;
function chunkForCitation(\NextPDF\Ast\AstDocument $ast): array{ // Token-bounded chunks for downstream citation storage. $extractor = new CitedTextExtractor( maxTokensPerChunk: 400, minChunkLength: 16, );
$rows = []; foreach ($extractor->extract($ast) as $block) { $rows[] = [ 'text' => $block->text, 'page' => $block->anchor->pageIndex, 'node_id' => $block->anchor->nodeId, 'chunk' => $block->chunkIndex, ]; }
return $rows;}Edge cases & gotchas
Section titled “Edge cases & gotchas”- Untagged or poorly tagged documents yield fewer text nodes; the AST quality is the upper bound on extraction quality.
- Nodes without a bounding box get a zero-area sentinel
BoundingBox(0,0,0,0)— detect it viawidth === 0.0 && height === 0.0if a real region is required. - Nested tables are not recursed; only the outermost
Tablenode is emitted. - Short rows are padded with synthetic zero-confidence cells so every row has the same column count.
Data Residency & PII Mitigations
Section titled “Data Residency & PII Mitigations”This module processes whatever text the supplied AST contains and returns it unchanged inside blocks. It performs no network calls, no external storage, and no logging of extracted content. PII handling, redaction, and residency controls are the caller’s responsibility on the produced blocks. See the Core PII handling guidance.
Safe Telemetry & Log Scrubbing
Section titled “Safe Telemetry & Log Scrubbing”The extractor emits no telemetry and does not log extracted text. If a caller
wraps it with logging, scrub text, metadata, and any cell content before
emitting logs.
Performance
Section titled “Performance”Extraction is a single tree walk, linear in node count. Chunk splitting adds
work proportional to text length. See performance_budget.
Security notes
Section titled “Security notes”Input is a pre-parsed AST, so this module does not parse hostile PDF bytes itself. Treat extracted text as untrusted and escape it for its destination.
Conformance
Section titled “Conformance”| Claim | Spec clause | Status |
|---|---|---|
| Logical-structure node traversal | ISO 32000-2:2020 §14.7 | Verified (unit suite, tagged AST) |
| Table row/cell extraction | ISO 32000-2:2020 §14.8 | Verified (unit suite) |
| Semantic search / embeddings | — | Not supported (out of scope) |
Core fallback / alternative
Section titled “Core fallback / alternative”The Core AST subsystem produces the AstDocument consumed here; there is no
Core equivalent for the citation-block extraction itself. See
/modules/core/ast/.
Enterprise boundary note
Section titled “Enterprise boundary note”This module is a structural extractor only. It does not perform semantic search, vector embedding, similarity ranking, or document intelligence.
Publication boundary
Section titled “Publication boundary”This page documents externally observable behavior and the supported public API surface only. Internal namespace paths, helper classes, mechanism tables, runbook filenames, and ticket prefixes are out of scope.