Hur man traverserar OneNote-dokumentets DOM i Python

Hur man traverserar OneNote-dokumentets 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, direkt iteration, och DocumentVisitor.


Dokumentobjektmodellen

OneNote-DOM:en är ett strikt träd:

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

Varje nod ärver från Node. Noder som har barn ärver från CompositeNode.


Metod 1: GetChildNodes (rekursiv, typfiltrerad)

CompositeNode.GetChildNodes(Type) utför en rekursiv djup-först-sökning av hela underträdet och returnerar en platt lista över alla noder som matchar den angivna typen. Detta är det mest bekväma tillvägagångssättet för innehållsextraktion:

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

Begränsa sökningen till en enskild sida genom att anropa GetChildNodesPage istället för 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")

Metod 2: Direkt barniteration

for child in node itererar omedelbara barn till en CompositeNode. Använd detta när du behöver en specifik nivå i hierarkin:

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

Metod 3: DocumentVisitor

DocumentVisitor tillhandahåller ett besökar-mönster för strukturerad traversering. Åsidosätt endast de VisitXxxStart/End metoder du behöver. Besökaren anropas genom att kalla 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())

Tillgängliga besöksmetoder

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

Navigera uppåt i trädet

Varje nod exponerar ParentNode och en Document egenskap för att navigera uppåt:

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 för barnhantering

CompositeNode exponerar också minnesbaserad barnhantering (användbart för programmatisk dokumentkonstruktion, även om återskrivning till .one stöds inte):

MetodBeskrivning
node.FirstChildFörsta direkta barn eller None
node.LastChildSista direkta barn eller None
node.AppendChildLast(child)Lägg till barn i slutet
node.AppendChildFirst(child)Lägg till barn i början
node.InsertChild(index, child)Infoga på position
node.RemoveChild(child)Ta bort ett barn

Räkna noder med en besökare

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

Välja rätt traverseringsmetod

ScenarioBästa tillvägagångssättet
Hitta alla noder av en typ (t.ex. alla RichText)GetChildNodes(RichText)
Iterera endast direkta barnfor child in node
Gå igenom trädet med kontext (djup, föräldratillstånd)DocumentVisitor
Navigera från innehåll upp till föräldern eller rotennode.ParentNode / node.Document

Relaterade resurser:

 Svenska