Bỏ qua để đến nội dung

Ast: cây tài liệu ngữ nghĩa và cơ chế tuần tự hóa

Module Ast cung cấp cây cú pháp trừu tượng (AST) ngữ nghĩa cho tài liệu của engine. Module này mô hình hóa tài liệu thành cây phân cấp gồm các nút có kiểu: Document, Section, Heading, Paragraph, List, Table, Figure, CodeFormField. Mô hình này ghi lại các hộp bao và neo trích dẫn, đồng thời tuần tự hóa thành JavaScript Object Notation (JSON) có phiên bản. Lớp gắn thẻ trợ năng dùng cây này để tạo cây cấu trúc.

Độ ổn định: thử nghiệm. Đây là một bề mặt mô hình nội bộ. Các lớp của nó không có bảo đảm rằng giao diện lập trình ứng dụng (API) công khai sẽ được đóng băng theo bất kỳ phiên bản nào. Tập hợp nút và các thuộc tính nút có thể thay đổi. Lược đồ tuần tự hóa được tạo phiên bản độc lập (AstDocument::CURRENT_SCHEMA_VERSION = '1.0.0'). Bộ serializer phát hiện và từ chối lược đồ không tương thích, nhờ đó JSON AST đã lưu vẫn giữ một hợp đồng ổn định ngay cả khi API trong bộ nhớ thay đổi.

Terminal window
composer require nextpdf/core:^3

Ở đây, AST biểu diễn cấu trúc logic của tài liệu. Nó không phải là cây cú pháp của parser cho một định dạng đầu vào cụ thể. AstDocument là vùng chứa. Nó giữ AstNode gốc (vốn phải là NodeType::Document), phiên bản lược đồ, hash của tệp Portable Document Format (PDF) nguồn và số trang. Nó từ chối các lần khởi tạo không hợp lệ, bao gồm phiên bản lược đồ rỗng, số trang nhỏ hơn một hoặc kiểu nút gốc sai.

AstNode là nút đệ quy. NodeType liệt kê các loại ngữ nghĩa. Một nút mang theo các nút con, một BoundingBox tùy chọn, nội dung văn bản tùy chọn và các thuộc tính được NodeAttributeSchema kiểm tra hợp lệ. API của nút hỗ trợ phái sinh bất biến. withBboxAndText() trả về một nút mới. deepClone() sao chép một cây con. NodeId là danh tính của value object. CitationAnchor liên kết một nút với vị trí nguồn để truy vết. AstNodeCollection là tập hợp Countable/IteratorAggregate có bộ lọc ofType().

AstSerializer là ranh giới lưu trữ. serialize() ghi một AstDocument ra JSON. deserialize() đọc nó trở lại. canDeserialize()extractSchemaVersion() cho phép bạn kiểm tra khả năng tương thích trước khi phân tích, nhờ đó lỗi không khớp lược đồ trở thành tình huống được phát hiện thay vì một lần nạp bị hỏng. AstDocument::estimateTokenCount() giúp ước lượng kích thước nội dung cho bước xử lý phía sau có giới hạn token.

LớpThành viên chínhVai trò
AstDocumenttoJson(), nodeCount(), estimateTokenCount(), CURRENT_SCHEMA_VERSIONVùng chứa gốc; kiểm tra hợp lệ kiểu nút gốc và lược đồ
AstNodeaddChild(), children(), childCount(), totalNodeCount(), withBboxAndText(), deepClone()Nút ngữ nghĩa đệ quy
NodeType (enum)Document, Heading, Table, Figure, FormField, …Loại nút ngữ nghĩa
AstNodeCollectionadd(), count(), isEmpty(), ofType(), toArray()Tập hợp nút có thể lặp và lọc theo kiểu
AstSerializerserialize(), deserialize(), canDeserialize(), extractSchemaVersion()Lưu trữ JSON có phiên bản
BoundingBoxtoArray(), equals()Value object hình học (so sánh bằng epsilon)
NodeId / CitationAnchortoString(), equals(), toArray()Danh tính nút và neo truy vết nguồn
NodeAttributeSchemakiểm tra hợp lệ thuộc tínhLược đồ cho các thuộc tính nút

Chạy composer docs:generate-api-php -- --module=Ast để tạo bảng PHPDoc đầy đủ.

Dựng một cây nhỏ rồi tuần tự hóa nó.

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Ast\AstNode;
use NextPDF\Ast\AstSerializer;
use NextPDF\Ast\NodeType;
$root = new AstNode(NodeType::Document);
$heading = new AstNode(NodeType::Heading);
$root->addChild($heading);
$root->addChild(new AstNode(NodeType::Paragraph));
echo "Nodes: {$root->totalNodeCount()}\n";
$json = (new AstSerializer())->serialize(/* an AstDocument wrapping $root */);

Nạp lại và lưu lại AST đã lưu trữ theo cách phòng thủ. Hãy kiểm tra khả năng tương thích của lược đồ trước khi giải tuần tự hóa JSON không đáng tin cậy.

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Ast\AstDocument;
use NextPDF\Ast\AstSerializer;
use Psr\Log\LoggerInterface;
final readonly class AstStore
{
public function __construct(
private AstSerializer $serializer,
private LoggerInterface $logger,
) {}
public function load(string $json): ?AstDocument
{
if (!$this->serializer->canDeserialize($json)) {
$this->logger->warning('AST JSON schema incompatible; rejected.', [
'found_schema' => $this->serializer->extractSchemaVersion($json),
'expected' => AstDocument::CURRENT_SCHEMA_VERSION,
]);
return null;
}
return $this->serializer->deserialize($json);
}
}
  • AstDocument yêu cầu nút gốc phải là NodeType::Document. Cây có nút gốc khác sẽ ném ngoại lệ khi khởi tạo.
  • AstNode::withBboxAndText()deepClone() trả về các thực thể mới. Các hàm thay đổi nút hiện có (addChild()) sẽ biến đổi chính nút đó. Các hàm trợ giúp phái sinh thì không. Hãy nắm rõ bạn đang gọi phương thức nào.
  • Luôn kiểm soát deserialize() bằng canDeserialize() đối với JSON đến từ bên ngoài. Việc không khớp phiên bản lược đồ là tình huống đã lường trước và có thể phát hiện được.
  • estimateTokenCount() là ước lượng dùng để xác định kích thước cho bước xử lý phía sau, không phải số token chính xác từ tokenizer. Đừng coi nó là con số chính thức.
  • BoundingBox::equals() là phép so sánh bằng epsilon (mặc định 0.001). Module không cam kết sự bằng nhau chính xác của số thực.

Việc dựng và duyệt cây có độ phức tạp O(n) theo số nút. Tuần tự hóa có độ phức tạp tuyến tính theo kích thước cây. Hồ sơ khả năng tái lập là bitwise. Cùng một cây sẽ tuần tự hóa thành cùng các byte JSON, nhờ đó lược đồ luôn ổn định như một hợp đồng lưu trữ. Khối lượng công việc tham chiếu mặc định luôn nằm gọn trong ngân sách 1500 ms thời gian thực / 64 MB đỉnh.

AstSerializer::deserialize() phân tích JSON có thể được lưu trữ hoặc truyền đi. Hãy kiểm tra khả năng tương thích bằng canDeserialize() trước. Hãy coi nội dung văn bản và các thuộc tính của cây đã giải tuần tự hóa là các chuỗi không đáng tin cậy khi chúng quay lại ứng dụng hoặc được kết xuất. Bản thân module không thực hiện input/output (I/O) nào và không nhúng dữ liệu bên ngoài. Xem mô hình mối đe dọa của engine tại /modules/core/security/.

Module này không đưa ra tuyên bố quy phạm nào theo đặc tả PDF. AST ngữ nghĩa là một trừu tượng nội bộ của engine. Nó không hiện thực một mô hình tài liệu được chuẩn hóa cần trích dẫn các điều khoản. Ở những nơi AST cung cấp dữ liệu cho việc gắn thẻ trợ năng, tính tuân thủ PDF/UA và tagged-PDF của đầu ra được ghi lại và kiểm tra hợp lệ tại /modules/core/accessibility//modules/core/conformance/, không phải ở đây.