كيفية استعراض شجرة DOM لمستند OneNote في بايثون

كيفية استعراض شجرة DOM لمستند OneNote في بايثون

Aspose.Note FOSS for Python يمثل ملف قسم OneNote كشجرة من كائنات Python ذات نوع محدد. فهم كيفية استعراض هذه الشجرة بكفاءة هو الأساس لجميع مهام استخراج المحتوى. يغطي هذا الدليل جميع أساليب الاستعراض الثلاثة: 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.


الطريقة 1: 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")

الطريقة 2: التكرار على الطفل المباشر

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

الطريقة 3: 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

الموارد ذات الصلة:

 العربية