چگونه DOM سند OneNote را در Python پیمایش کنیم

چگونه DOM سند OneNote را در 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, تکرار مستقیم، و DocumentVisitor.


مدل شیء سند

DOM OneNote یک درخت سخت‌گیرانه است:

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

هر گره از Node. گره‌هایی که فرزندان دارند از CompositeNode.


روش ۱: GetChildNodes (بازگشتی، فیلتر شده بر اساس نوع)

CompositeNode.GetChildNodes(Type) یک جستجوی عمق‑اول بازگشتی در تمام زیردرخت انجام می‌دهد و فهرست مسطحی از تمام گره‌های مطابق با نوع داده‌شده برمی‌گرداند. این راحت‌ترین روش برای استخراج محتوا است:

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

جستجو را به یک صفحهٔ واحد محدود کنید با فراخوانی GetChildNodes روی Page به‌جای 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")

روش ۲: تکرار مستقیم فرزندان

for child in node تکرار می‌کند مستقیم فرزندان یک CompositeNode. از این استفاده کنید وقتی به یک سطح خاص از سلسله‌مراتب نیاز دارید:

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

روش ۳: DocumentVisitor

DocumentVisitor یک الگوی بازدیدگر برای پیمایش ساختاری فراهم می‌کند. فقط VisitXxxStart/End متدهایی که نیاز دارید. بازدیدگر با فراخوانی 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())

متدهای بازدیدگر موجود

جفت متدنوع گره
VisitDocumentStart/EndDocument
VisitPageStart/EndPage
VisitTitleStart/EndTitle
VisitOutlineStart/EndOutline
VisitOutlineElementStart/EndOutlineElement
VisitRichTextStart/EndRichText
VisitImageStart/EndImage

پیمایش به سمت بالا در درخت

هر گره در دسترس می‌گذارد ParentNode و یک Document ویژگی برای حرکت به سمت بالا:

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

روش‌های مدیریت فرزندان

CompositeNode همچنین مدیریت فرزندان در حافظه را در دسترس می‌گذارد (مفید برای ساخت برنامه‌نویسی سند، اگرچه نوشتن بازگشت به .one پشتیبانی نمی‌شود):

متدتوضیح
node.FirstChildاولین فرزند مستقیم یا None
node.LastChildآخرین فرزند مستقیم یا None
node.AppendChildLast(child)افزودن فرزند در انتها
node.AppendChildFirst(child)افزودن فرزند در ابتدا
node.InsertChild(index, child)درج در موقعیت
node.RemoveChild(child)حذف یک فرزند

شمارش گره‌ها با بازدیدکننده

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

انتخاب روش پیمایش مناسب

سناریوبهترین رویکرد
تمام گره‌های یک نوع را پیدا کنید (مثلاً تمام RichText)GetChildNodes(RichText)
فقط فرزندان مستقیم را تکرار کنیدfor child in node
درخت را با زمینه (عمق، وضعیت والد) پیمایش کنیدDocumentVisitor
از محتوا به سمت والد یا ریشه ناوبری کنیدnode.ParentNode / node.Document

منابع مرتبط:

 فارسی