Doclingdocling 2.127.0 · Python 3.10+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
26 small wins to finish your pathNext lesson

The order the document is meant to be read in

The flat lists from lesson 5 are storage. The order a person would read the document in lives in a separate tree, and for a PDF the two are not the same.

document.body is the root of that tree. Its children are references, in order, to the pieces that sit at the top level of the document.

Example
from docling.document_converter import DocumentConverter

document = DocumentConverter().convert("shipping.md").document
for ref in document.body.children:
    print(ref.cref, "->", ref.resolve(document).label)

Five children for six texts, because the two list items are not here: they are inside #/groups/0. Reading order is the tree walked depth first, which is exactly what iterate_items did in lesson 4.

Upwards as well as downwards

Example
item = document.texts[4]
print(item.text)
print("sits inside", item.parent.cref)

Every piece knows its parent, so you can start from a search hit and walk up to find out where it came from. The chunker in part 6 does exactly this to work out which headings a piece of text sat under.

Storage order is not reading order

For this file they happen to agree. They do not have to. A PDF with two columns stores its pieces in whatever order the layout model emitted them and puts the reading order in the tree, so a program that loops over document.texts can read a page down the middle.

Loop over iterate_items when order matters, and over document.texts when it does not. Getting this backwards on a two column paper produces text that looks right until you read a sentence of it.

Furniture, which is not in the body

Page headers, footers and footnotes are content nobody wants in the middle of a sentence, so they go into a second tree called furniture and are left out of exports by default. Lesson 10 shows the argument that puts them back in.

Example
print(len(document.body.children), "in the body")
print(len(document.furniture.children), "in the furniture")
Try it yourself
  • Walk from document.texts[5] up through parent until you reach #/body.
  • Print ref.cref for the children of refunds.html's body and compare it with the Markdown one.
  • Count how many pieces iterate_items yields and compare it with len(document.texts).

You understood something today that you didn't yesterday.