Comment parcourir le DOM du document OneNote dans Python

Comment parcourir le DOM du document OneNote dans 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, itération directe, et DocumentVisitor.


Le modèle d’objet de document

Le DOM OneNote est un arbre strict :

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

Chaque nœud hérite de Node. Les nœuds qui ont des enfants héritent de CompositeNode.


Méthode 1 : GetChildNodes (récursif, filtré par type)

CompositeNode.GetChildNodes(Type) effectue une recherche récursive en profondeur de tout le sous‑arbre et renvoie une liste plate de tous les nœuds correspondant au type donné. C’est l’approche la plus pratique pour l’extraction de contenu :

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

Limitez la recherche à une seule page en appelant GetChildNodes sur Page au lieu de 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")

Méthode 2 : itération directe des enfants

for child in node itère le immédiat enfants d’un CompositeNode. Utilisez ceci lorsque vous avez besoin d’un niveau spécifique de la hiérarchie :

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

Méthode 3 : DocumentVisitor

DocumentVisitor fournit un visitor pattern pour le parcours structuré. Surchargez uniquement le VisitXxxStart/End méthodes dont vous avez besoin. Le visiteur est déclenché en appelant 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())

Méthodes de visiteur disponibles

Paire de méthodesType de nœud
VisitDocumentStart/EndDocument
VisitPageStart/EndPage
VisitTitleStart/EndTitle
VisitOutlineStart/EndOutline
VisitOutlineElementStart/EndOutlineElement
VisitRichTextStart/EndRichText
VisitImageStart/EndImage

Navigation vers le haut de l’arbre

Chaque nœud expose ParentNode et un Document propriété pour naviguer vers le haut :

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

Méthodes de gestion des enfants

CompositeNode expose également la gestion des enfants in-memory (utile pour la construction programmatique de documents, bien que la réécriture vers .one n’est pas pris en charge) :

MéthodeDescription
node.FirstChildPremier enfant direct ou None
node.LastChildDernier enfant direct ou None
node.AppendChildLast(child)Ajouter un enfant à la fin
node.AppendChildFirst(child)Ajouter un enfant au début
node.InsertChild(index, child)Insérer à la position
node.RemoveChild(child)Supprimer un enfant

Compter les nœuds avec un visiteur

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

Choisir la bonne méthode de traversée

ScénarioMeilleure approche
Trouver tous les nœuds d’un type (par ex. tous les RichText)GetChildNodes(RichText)
Itérer uniquement les enfants directsfor child in node
Parcourir l’arbre avec le contexte (profondeur, état du parent)DocumentVisitor
Naviguer depuis le contenu vers le parent ou la racinenode.ParentNode / node.Document

Ressources associées :

 Français