Hvordan man traverserer OneNote-dokument-DOM i Python

Hvordan man traverserer OneNote-dokument-DOM i 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, direkte iteration, og DocumentVisitor.


Dokumentobjektmodellen

OneNote-DOM’en er et strikt træ:

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

Hver node arver fra Node. Noder, der har børn, arver fra CompositeNode.


Metode 1: GetChildNodes (rekursiv, typefiltreret)

CompositeNode.GetChildNodes(Type) udfører en rekursiv dybde‑først søgning af hele undertræet og returnerer en flad liste over alle noder, der matcher den givne type. Dette er den mest bekvemme tilgang til indholdsudtræk:

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

Afgræns søgningen til en enkelt side ved at kalde GetChildNodesPage i stedet for 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")

Metode 2: Direkte børneiteration

for child in node itererer umiddelbare børn af en CompositeNode. Brug dette, når du har brug for ét specifikt niveau i hierarkiet:

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

Metode 3: DocumentVisitor

DocumentVisitor leverer et besøgs‑mønster til struktureret gennemløb. Overskriv kun VisitXxxStart/End metoder du har brug for. Besøgeren udløses ved at kalde 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())

Tilgængelige besøgsmetoder

MetodeparNodetype
VisitDocumentStart/EndDocument
VisitPageStart/EndPage
VisitTitleStart/EndTitle
VisitOutlineStart/EndOutline
VisitOutlineElementStart/EndOutlineElement
VisitRichTextStart/EndRichText
VisitImageStart/EndImage

Navigering op i træet

Hver node eksponerer ParentNode og en Document egenskab til at navigere opad:

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

Metoder til håndtering af underordnede

CompositeNode eksponerer også in-memory børneadministration (nyttig til programmatisk dokumentkonstruktion, selvom skrivning tilbage til .one understøttes ikke):

MetodeBeskrivelse
node.FirstChildFørste direkte barn eller None
node.LastChildSidste direkte barn eller None
node.AppendChildLast(child)Tilføj barn i slutningen
node.AppendChildFirst(child)Tilføj barn i starten
node.InsertChild(index, child)Indsæt på position
node.RemoveChild(child)Fjern et barn

Tæl noder med en 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}")

Valg af den rigtige traverseringsmetode

ScenarioBedste tilgang
Find alle noder af en type (fx alle RichText)GetChildNodes(RichText)
Iterer kun direkte børnfor child in node
Gå gennem træet med kontekst (dybde, forældrestatus)DocumentVisitor
Naviger fra indholdet op til forælderen eller rodennode.ParentNode / node.Document

Relaterede ressourcer:

 Dansk