使用 Note 文档

本指南解释了如何在 Python 中使用来自 Aspose.Note FOSS 的 Document 类加载、遍历和导出 Microsoft OneNote .one 文件。Document 类是文档对象模型 (DOM) 的根,所有读取、遍历或导出操作都从表示单个 .one 部分文件的 Document 实例开始。


加载文档

从文件路径加载

将 .one 文件的路径直接传递给 Document 构造函数:

from aspose.note import Document

doc = Document("MyNotes.one")

从二进制流加载

当数据来自网络响应、云存储 Blob 或内存缓冲区时,使用类似文件的对象:

from pathlib import Path
from aspose.note import Document

with Path("MyNotes.one").open("rb") as f:
    doc = Document(f)

创建空文档

构造一个 Document(不带参数)以以编程方式创建一个新的 OneNote 文档:

from aspose.note import Document, Page

doc = Document()
doc.AppendChildLast(Page())

使用选项加载

使用 LoadOptions 在构造时设置可选参数,例如历史加载:

from aspose.note import Document, LoadOptions

opts = LoadOptions()
opts.LoadHistory = True   # include page revision history in the DOM
doc = Document("MyNotes.one", opts)
LoadOptions 属性类型Default描述
LoadHistoryboolFalse当 True 时,页面历史修订会被包含在 DOM 中,并可通过 Document.GetPageHistory 访问。
DocumentPassword`strNone`None

文档格式检测

FileFormat 属性标识文件使用的 OneNote 格式变体:

from aspose.note import Document, FileFormat

doc = Document("MyNotes.one")

if doc.FileFormat == FileFormat.OneNote2010:
    print("OneNote 2010 format")
elif doc.FileFormat == FileFormat.OneNoteOnline:
    print("OneNote Online format")
elif doc.FileFormat == FileFormat.OneNote2007:
    print("OneNote 2007 format")
else:
    print("Format:", doc.FileFormat)
FileFormat 值描述
OneNote2010标准 .one 文件,由 OneNote 于 2010 年及以后编写
OneNoteOnline.one 文件,由 OneNote Online / Microsoft 365 编写
OneNote2007旧版 .one 格式,来自 OneNote 2007
Unknown无法识别格式

遍历页面

页面是 Document 的直接子节点。由于 Document 实现了枚举器,你可以使用简单的 for 循环来遍历它:

from aspose.note import Document

doc = Document("MyNotes.one")

for page in doc:
    title_text = (
        page.Title.TitleText
        if page.Title and page.Title.TitleText
        else "(untitled)"
    )
    print(title_text)

如果需要一次检索特定类型的所有子节点,请使用 GetChildNodes 方法并将所需的节点类作为参数传入:

# Replace DesiredNodeType below with the specific node class you want to collect
nodes = doc.GetChildNodes(DesiredNodeType)
print(f"Total nodes: {len(nodes)}")

遍历文档树

Document 继承自 CompositeNode,从而拥有完整的树遍历方法:

from aspose.note import Document, RichText

doc = Document("MyNotes.one")

# Extract all plain text from the entire document
all_text = [rt.Text for rt in doc.GetChildNodes(RichText) if rt.Text]
print("\n".join(all_text))

DOM 层次结构:

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

从 CompositeNode 继承的关键遍历方法:

方法描述
GetChildNodes(NodeType)返回一个类型化列表,包含所有匹配给定类型的后代
AppendChildLast(node)在子节点列表的末尾添加一个子节点
AppendChildFirst(node)在开头添加一个子节点
InsertChild(index, node)在特定索引处插入子节点
RemoveChild(node)移除子节点
GetEnumerator()遍历直接子节点

页面历史

使用 LoadHistory=True 加载时,Document.GetPageHistory 返回页面的所有已保存修订,按从最旧到最新的顺序排列:

from aspose.note import Document, LoadOptions

opts = LoadOptions()
opts.LoadHistory = True
doc = Document("MyNotes.one")

for page in doc.GetChildNodes(None.__class__.__mro__[0]):  # iterate pages
    pass

# Get revisions for a specific page
import aspose.note as an

doc2 = Document("MyNotes.one", opts)
pages = doc2.GetChildNodes(an.Page)
if pages:
    history = doc2.GetPageHistory(pages[0])
    print(f"Revision count: {history.Count}")
    for rev in history:
        print(f"  Modified: {rev.LastModifiedTime}")

Note: GetPageHistory 返回一个空的 PageHistory 对象,当 LoadHistory is False (默认)。始终设置 opts.LoadHistory = True 在加载之前,如果需要修订数据。


保存与导出

使用 Document.Save 导出为 PDF。PDF 是唯一受支持的导出格式。

保存到文件

使用文件路径调用 Document.Save() 并配合 SaveFormat.Pdf 将导出直接写入磁盘:

from aspose.note import Document, SaveFormat

doc = Document("MyNotes.one")
doc.Save("output.pdf", SaveFormat.Pdf)

保存到内存流中

传入可写的 io.BytesIO 缓冲区(而不是路径),以在内存中捕获 PDF 字节:

import io
from aspose.note import Document, SaveFormat

doc = Document("MyNotes.one")
buf = io.BytesIO()
doc.Save(buf, SaveFormat.Pdf)
pdf_bytes = buf.getvalue()

使用选项保存

使用来自 aspose.note.saving 的 PdfSaveOptions 来控制导出 PDF 输出中包含的页面:

import io
from aspose.note import Document
from aspose.note.saving import PdfSaveOptions

doc = Document("MyNotes.one")

# Export pages 2 and 3 only (zero-based index)
opts = PdfSaveOptions(PageIndex=1, PageCount=2)
buf = io.BytesIO()
doc.Save(buf, opts)
pdf_bytes = buf.getvalue()

Important: PDF 导出需要可选的 ReportLab 依赖。安装 [pdf] 额外组件以启用它。


检测布局更改

在修改文档后调用 DetectLayoutChanges 以在保存前重新计算布局指标:

from aspose.note import Document, Page

doc = Document()
page = Page()
doc.AppendChildLast(page)

# ... add content to page ...

doc.DetectLayoutChanges()
doc.Save("output.pdf")

提示与最佳实践

  • 加载一次,查询多次: Document 加载整个 .one 文件在构造时加载到内存中。保持一个 Document 实例并调用 GetChildNodes 重复执行,而不是为每个查询重新加载文件。
  • Check IsConflictPage: OneNote 同步可能会产生冲突页面。使用以下方式过滤 [p for p in doc if not p.IsConflictPage] 在处理内容之前。
  • 使用 LoadHistory=False (default) 以获得更快的速度: 页面历史会增加显著的内存和解析开销。仅在需要时设置 LoadHistory=True 当您明确需要修订数据时。
  • 对大文件使用流式处理: 在读取大型文件时,传递打开的文件对象而不是路径字符串 .one 文件,以避免在解析完成后保持文件打开.
  • Call DetectLayoutChanges before Save: 在以编程方式构建文档并追加节点时,调用 DetectLayoutChanges() 以确保在导出为 PDF 之前布局坐标保持一致。

常见问题

问题原因修复
IncorrectPasswordException 在加载时文件已加密;不支持加密文档获取该文件的未加密副本
FileCorruptedException 在加载时文件已被截断或内部格式不受支持请确认文件是有效的 .one 部分(而非 .onetoc2 目录)
UnsupportedSaveFormatException 在保存时尝试保存为 PDF 之外的格式导出仅支持 PDF 格式
GetPageHistory 结果为空LoadOptions.LoadHistory 在加载前未设置为 True使用 opts.LoadHistory = True 重新加载文档
ModuleNotFoundError: reportlab在没有 PDF extra 的情况下尝试导出 PDF安装 [pdf] extra

FAQ

哪些 OneNote 格式可以由 Aspose.Note 读取?

所有三种 OneNote 区段格式:OneNote2007、OneNote2010 和 OneNoteOnline。使用 doc.FileFormat 来识别已加载的变体。

读取后我可以写回 .one 文件吗?

Aspose.Note 用于 Python 是一个读取并导出的库。使用 Document.Save 生成 PDF 输出。此 FOSS 版中的 OneNote 二进制格式为只读。

如何按标题读取特定页面?

使用生成器表达式遍历页面,并将 title 文本属性与目标字符串进行比较:

from aspose.note import Document

doc = Document("MyNotes.one")
target = next(
    (p for p in doc
     if p.Title and p.Title.TitleText and p.Title.TitleText.Text == "My Page"),
    None,
)

我如何将子页面的计数与顶级页面分开?

使用 page.Level:第 1 级是顶级,第 2 级是子页面,依此类推。

from aspose.note import Document

doc = Document("MyNotes.one")
top_level = [p for p in doc if (p.Level or 1) == 1]
sub_pages  = [p for p in doc if (p.Level or 1) > 1]
print(f"Top-level: {len(top_level)}, Sub-pages: {len(sub_pages)}")

Aspose.Note 是否支持 .onetoc2 目录文件?

不。仅支持 .one 部分文件。.onetoc2 笔记本将触发 FileCorruptedException。


API Reference 摘要

类 / 方法描述
Document(path_or_stream, options?)加载 .one 文件或创建空文档
Document.FileFormat检测到的格式变体(FileFormat 枚举)
Document.GetChildNodes(NodeType)检索给定类型的所有后代节点
Document.GetPageHistory(page)获取页面的修订历史(需要 LoadHistory=True)
Document.Save(target, format_or_options)按文件路径或流导出为 PDF
Document.DetectLayoutChanges()在程序化编辑后重新计算布局度量
Document.Accept(visitor)使用 DocumentVisitor 子类遍历 DOM
LoadOptions.LoadHistory设置为 True 以在 DOM 中包含页面修订
LoadOptions.DocumentPassword保留;加密文件会引发 IncorrectPasswordException
FileFormat枚举:OneNote2010, OneNoteOnline, OneNote2007, Unknown
SaveFormat.Pdf唯一受支持的导出格式;对其他格式会抛出 ValueError
PageHistory.Count可用的页面修订次数
Page.Level子页面深度(1 = 顶层)
Page.IsConflictPageTrue 用于同步冲突副本

另请参阅

 中文