كيفية التنقل عبر شجرة 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.
الطريقة 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/End | Document |
VisitPageStart/End | Page |
VisitTitleStart/End | Title |
VisitOutlineStart/End | Outline |
VisitOutlineElementStart/End | OutlineElement |
VisitRichTextStart/End | RichText |
VisitImageStart/End | Image |
التنقل صعوداً في الشجرة
كل عقدة تكشف عن 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 |
الموارد ذات الصلة: