Jak przeglądać DOM dokumentu OneNote w Python

Jak przeglądać DOM dokumentu OneNote w 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, bezpośrednia iteracja i DocumentVisitor.


Model obiektowy dokumentu

DOM OneNote jest ścisłym drzewem:

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

Każdy węzeł dziedziczy po Node. Węzły, które mają dzieci, dziedziczą po CompositeNode.


Metoda 1: GetChildNodes (rekursywne, filtrowane typem)

CompositeNode.GetChildNodes(Type) wykonuje rekurencyjne przeszukiwanie w głąb całego poddrzewa i zwraca płaską listę wszystkich węzłów pasujących do podanego typu. Jest to najwygodniejsze podejście do wyodrębniania treści:

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)}")

Ogranicz wyszukiwanie do jednej strony, wywołując GetChildNodes na Page zamiast 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")

Metoda 2: Bezpośrednia iteracja dzieci

for child in node iteruje bezpośrednie dzieci CompositeNode. Użyj tego, gdy potrzebujesz jednego konkretnego poziomu hierarchii:

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__}")

Metoda 3: DocumentVisitor

DocumentVisitor udostępnia wzorzec odwiedzającego do strukturalnego przeglądania. Nadpisz tylko VisitXxxStart/End metody, które potrzebujesz. Odwiedzający jest wywoływany przez wywołanie 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())

Dostępne metody odwiedzającego

Para metodTyp węzła
VisitDocumentStart/EndDocument
VisitPageStart/EndPage
VisitTitleStart/EndTitle
VisitOutlineStart/EndOutline
VisitOutlineElementStart/EndOutlineElement
VisitRichTextStart/EndRichText
VisitImageStart/EndImage

Nawigacja w górę drzewa

Każdy węzeł udostępnia ParentNode i Document właściwość do nawigacji w górę:

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

Metody zarządzania dziećmi

CompositeNode również udostępnia zarządzanie dziećmi w pamięci (przydatne przy programowym tworzeniu dokumentu, choć zapis zwrotny do .one nie jest obsługiwane):

MetodaOpis
node.FirstChildPierwszy bezpośredni element potomny lub None
node.LastChildOstatni bezpośredni element potomny lub None
node.AppendChildLast(child)Dodaj element potomny na końcu
node.AppendChildFirst(child)Dodaj element potomny na początku
node.InsertChild(index, child)Wstaw na pozycję
node.RemoveChild(child)Usuń dziecko

Zliczanie węzłów przy użyciu odwiedzającego

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}")

Wybór odpowiedniej metody przeglądania

ScenariuszNajlepsze podejście
Znajdź wszystkie węzły jednego typu (np. wszystkie RichText)GetChildNodes(RichText)
Iteruj tylko bezpośrednie dziecifor child in node
Przejdź po drzewie z kontekstem (głębokość, stan rodzica)DocumentVisitor
Nawiguj z treści do elementu nadrzędnego lub korzenianode.ParentNode / node.Document

Powiązane zasoby:

 Polski