阅读文本 / Reading text
This paper uses synthetic samples to demonstrate the processing method. The code has been verified using examples in an isolated environment; this does not guarantee effectiveness for all real files or products. Before processing important files, please retain the original copies and verify them against the boundaries and acceptance criteria outlined in this document.
The amounts in the two rows of details are identical, which does not indicate that they are duplicate data; nor does the sorted table, which appears more organized, demonstrate that it still corresponds to the original text on a line-by-line basis. When extracting detailed records, what is most easily overlooked is not the fields themselves, but rather the relationships between the rows and their sources.
first saves the stable row identity
retains the source page, table number, and source row number for each detail entry, or a stable identifier composed of these pieces of information. Product names and amounts may be duplicated and are therefore unsuitable as standalone identifiers. When downstream systems need to sort by amount, a display view can be created; however, the sorted sequence numbers should not be written back into the original source.
The JSON array itself preserves its order, but in the schema,
uniqueItems
is not a shorthand for “uniqueness of a particular field.” Two objects may still be considered distinct as long as their other fields differ. Field-level uniqueness must be checked separately.
A set of details with the same amount but different sources
from collections import Counter
rows = [{"source_id": "p1-t1-r1", "item": "Bolt", "amount": "10.00"},
{"source_id": "p1-t1-r2", "item": "Nut", "amount": "10.00"}]
def check_ids(items):
counts = Counter(row["source_id"] for row in items)
return [key for key, count in counts.items() if count > 1]
assert check_ids(rows) == []
assert len(rows) == 2
assert check_ids(rows + [dict(rows[0])]) == ["p1-t1-r1"]
display = sorted(rows, key=lambda row: row["item"], reverse=True)
assert [r["source_id"] for r in rows] == ["p1-t1-r1", "p1-t1-r2"]
assert {r["source_id"] for r in display} == {r["source_id"] for r in rows}
This is an identity check for synthetic data, not a table recognizer. The code deliberately does not deduplicate identical amounts, nor does it treat display order as source order. The rules for generating true source IDs must account for file versions; otherwise, the same page and the same line in two different versions could be mistakenly treated as the same piece of evidence.
When the number of lines is incorrect, first identify the missing segment.
phenomenon
should check
should not immediately adopt
amount duplicate
Whether it is a different project or a different source line
deduplication by amount
source ID duplicate
whether it has been imported repeatedly or mapped incorrectly
randomly adds a new ID
number of lines reduced
Merge cells, blank rows, and filtering rules
uses the previous line to complete
sequence variation
Is it merely for display purposes?
overwrites the original line number
cross-page header is not a regular data row
Duplicate header rows, continuation notes, and subtotal rows may all end up in the detail array. Removing them requires interpretable rules; “first row” or “shorter text” cannot serve as the sole criteria. Retaining the excluded rows along with their justification can help reviewers detect inadvertent deletions, rather than having to trace back only when the final total does not match.
carries the source relationship to post-editing verification
multilingual detail table should be alignable by source ID and cannot rely solely on the post-translation product name for lookup. Evaluate
OmniDoc (product entry point)
When translating tabular documents, the row–column relationships, quantities, and units should all be checked separately. The source identifier in this paper is an external engineering convention, not a description of the platform’s internal implementation.
Reference:
JSON Schema array
。
- 1 -
Updated 2026-10-08