Cách Duyệt DOM Tài liệu OneNote trong Python

Cách Duyệt DOM Tài liệu OneNote trong Python

Aspose.Note FOSS for Python represents a OneNote section file as a tree of typed Python objects. Understanding how to traverse this tree efficiently is the foundation for all content extraction tasks. This guide covers all three traversal approaches: GetChildNodes, lặp lại trực tiếp, và DocumentVisitor.


Mô hình Đối tượng Tài liệu

DOM OneNote là một cây chặt chẽ:

Document
  ├── Page
  │     ├── Title
  │     │     ├── TitleText (RichText)
  │     │     ├── TitleDate (RichText)
  │     │     └── TitleTime (RichText)
  │     └── Outline
  │           └── OutlineElement
  │                 ├── RichText
  │                 ├── Image
  │                 ├── AttachedFile
  │                 └── Table
  │                       └── TableRow
  │                             └── TableCell
  │                                   └── RichText / Image
  └── Page  (next page ...)

Mỗi nút kế thừa từ Node. Các nút có con kế thừa từ CompositeNode.


Phương pháp 1: GetChildNodes (Đệ quy, Lọc theo Kiểu)

CompositeNode.GetChildNodes(Type) thực hiện một tìm kiếm đệ quy theo chiều sâu trên toàn bộ cây con và trả về một danh sách phẳng của tất cả các nút khớp với kiểu đã cho. Đây là cách tiếp cận thuận tiện nhất để trích xuất nội dung:

from aspose.note import Document, RichText, Image, Table, AttachedFile

doc = Document("MyNotes.one")

##All RichText nodes anywhere in the document
texts = doc.GetChildNodes(RichText)
print(f"RichText nodes: {len(texts)}")

##All images
images = doc.GetChildNodes(Image)
print(f"Image nodes: {len(images)}")

##All tables
tables = doc.GetChildNodes(Table)
print(f"Table nodes: {len(tables)}")

##All attachments
attachments = doc.GetChildNodes(AttachedFile)
print(f"AttachedFile nodes: {len(attachments)}")

Giới hạn phạm vi tìm kiếm trong một trang duy nhất bằng cách gọi GetChildNodes trên Page thay vì Document:

from aspose.note import Document, Page, RichText

doc = Document("MyNotes.one")
for page in doc.GetChildNodes(Page):
    page_texts = page.GetChildNodes(RichText)
    print(f"  Page has {len(page_texts)} text nodes")

Phương pháp 2: Lặp Trực Tiếp Các Con

for child in node lặp qua trực tiếp các nút con của một CompositeNode. Sử dụng điều này khi bạn cần một cấp độ cụ thể của cây phân cấp:

from aspose.note import Document

doc = Document("MyNotes.one")

##Direct children of Document are Pages
for page in doc:
    title = (
        page.Title.TitleText.Text
        if page.Title and page.Title.TitleText
        else "(untitled)"
    )
    print(f"Page: {title}")
    # Direct children of Page are Outlines (and optionally Title)
    for child in page:
        print(f"  {type(child).__name__}")

Phương pháp 3: DocumentVisitor

DocumentVisitor cung cấp một mẫu visitor cho việc duyệt có cấu trúc. Ghi đè chỉ các VisitXxxStart/End phương thức bạn cần. Visitor được kích hoạt bằng cách gọi doc.Accept(visitor):

from aspose.note import (
    Document, DocumentVisitor, Page, Title,
    Outline, OutlineElement, RichText, Image,
)

class StructurePrinter(DocumentVisitor):
    def __init__(self):
        self._depth = 0

    def _indent(self):
        return "  " * self._depth

    def VisitPageStart(self, page: Page) -> None:
        t = page.Title.TitleText.Text if page.Title and page.Title.TitleText else "(untitled)"
        print(f"{self._indent()}Page: {t!r}")
        self._depth += 1

    def VisitPageEnd(self, page: Page) -> None:
        self._depth -= 1

    def VisitOutlineStart(self, outline) -> None:
        self._depth += 1

    def VisitOutlineEnd(self, outline) -> None:
        self._depth -= 1

    def VisitRichTextStart(self, rt: RichText) -> None:
        if rt.Text.strip():
            print(f"{self._indent()}Text: {rt.Text.strip()!r}")

    def VisitImageStart(self, img: Image) -> None:
        print(f"{self._indent()}Image: {img.FileName!r} ({img.Width}x{img.Height}pts)")

doc = Document("MyNotes.one")
doc.Accept(StructurePrinter())

Các Phương Thức Visitor Có Sẵn

Cặp phương thứcKiểu nút
VisitDocumentStart/EndDocument
VisitPageStart/EndPage
VisitTitleStart/EndTitle
VisitOutlineStart/EndOutline
VisitOutlineElementStart/EndOutlineElement
VisitRichTextStart/EndRichText
VisitImageStart/EndImage

Duyệt Lên Trên Cây

Mỗi nút cung cấp ParentNode và một Document thuộc tính để di chuyển lên trên:

from aspose.note import Document, RichText

doc = Document("MyNotes.one")
for rt in doc.GetChildNodes(RichText):
    parent = rt.ParentNode   # OutlineElement, TableCell, Title, etc.
    root = rt.Document       # always the Document root
    print(f"  '{rt.Text.strip()!r}' parent={type(parent).__name__}")
    break

Các phương pháp quản lý con

CompositeNode cũng cung cấp quản lý con trong bộ nhớ (hữu ích cho việc xây dựng tài liệu bằng chương trình, mặc dù việc ghi lại vào .one không được hỗ trợ):

Phương phápMô tả
node.FirstChildCon trực tiếp đầu tiên hoặc None
node.LastChildCon trực tiếp cuối cùng hoặc None
node.AppendChildLast(child)Thêm con vào cuối
node.AppendChildFirst(child)Thêm con vào đầu
node.InsertChild(index, child)Chèn vào vị trí
node.RemoveChild(child)Xóa một con

Đếm các nút bằng Visitor

from aspose.note import Document, DocumentVisitor, Page, RichText, Image

class Counter(DocumentVisitor):
    def __init__(self):
        self.pages = self.texts = self.images = 0

    def VisitPageStart(self, page: Page) -> None:
        self.pages += 1

    def VisitRichTextStart(self, rt: RichText) -> None:
        self.texts += 1

    def VisitImageStart(self, img: Image) -> None:
        self.images += 1

doc = Document("MyNotes.one")
c = Counter()
doc.Accept(c)
print(f"Pages={c.pages}  RichText={c.texts}  Images={c.images}")

Chọn phương pháp duyệt phù hợp

Kịch bảnCách tiếp cận tốt nhất
Tìm tất cả các nút của một loại (ví dụ: tất cả RichText)GetChildNodes(RichText)
Duyệt chỉ các nút con trực tiếpfor child in node
Duyệt cây với ngữ cảnh (độ sâu, trạng thái của nút cha)DocumentVisitor
Điều hướng từ nội dung lên tới nút cha hoặc gốcnode.ParentNode / node.Document

Tài nguyên liên quan:

 Tiếng Việt