Python에서 OneNote 문서 DOM을 탐색하는 방법

Python에서 OneNote 문서 DOM을 탐색하는 방법

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.


문서 객체 모델

OneNote DOM은 엄격한 트리 구조입니다:

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

검색 범위를 단일 페이지로 제한하려면 다음을 호출하십시오 GetChildNodesPage 대신에 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

트리 위쪽으로 이동하기

모든 노드는 다음을 노출합니다 ParentNodeDocument 위로 탐색하기 위한 속성:

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

관련 자료:

 한국어