TemplatePart

featherdoc::TemplatePart 是正文、页眉和页脚部件的统一编辑入口。 它把同一组模板操作应用到不同的 .docx 包部件上,适合处理书签填充、 内容控件替换,以及部件级模板校验。

常用任务入口

可以把本页当作部件级参考手册使用:

  • 填充命名书签:调用 list_bookmarks()、find_bookmark(...)、 replace_bookmark_text(...) 或 fill_bookmarks(...)。

  • 填充内容控件:使用 find_content_controls_by_tag(...) 和 replace_content_control_text_by_tag(...)。

  • 用生成内容替换模板槽位:使用书签或内容控件的段落、表格、表格行和图片替换方法。

  • 用同一套 API 编辑页眉/页脚:先从 Document 获取 TemplatePart, 再调用 paragraphs()、tables()、append_paragraph(...) 或 append_table(...)。

  • 校验局部模板表面:写入前调用 validate_template(...)。

成功/失败语义

返回形态

成功含义

失败或无变化含义

operator bool()

true 表示当前部件指向可用的包内 XML 部件。

false 表示正文、页眉或页脚部件无法解析。

std::size_t

非零值表示匹配并修改或追加的槽位数量。

0 表示没有匹配的书签、内容控件、超链接或图片插入目标。

bool

true 表示请求的 XML 修改已应用。

false 表示目标不可用、不支持,或没有发生变化。

bookmark_fill_result

查看 matched 和 replaced 判断填充是否命中。

在认为模板完整前,应检查 missing_bookmarks。

template_validation_result

结果为真表示必需槽位通过校验。

缺失或类型不匹配的槽位会记录在结果详情中。

短示例

auto body = doc.body_template();
if (!body) return 1;

body.replace_bookmark_text("invoice_no", "INV-2026-001");
body.replace_content_control_text_by_tag("status", "approved");

类型化签名导读

TemplatePart 用于部件级编辑。只有 operator bool() 返回 true 时, 它才指向可用的包内 XML 部件。返回 std::size_t 的方法表示匹配并修改了 多少个书签或内容控件;返回 bool 的方法表示请求的 XML 修改是否成功应用。

签名

参数

返回语义

explicit operator bool() const noexcept

无。

指向可用包内 XML 部件时为 true。

std::string_view entry_name() const noexcept

无。

包内条目名,例如 word/document.xml。

Paragraph append_paragraph(const std::string &text = {}, formatting_flag formatting = formatting_flag::none)

text:插入段落文本。formatting:可选首个 run 格式。

返回当前部件中新建的段落句柄。

Table append_table(std::size_t row_count = 1U, std::size_t column_count = 1U)

row_count 和 column_count:初始表格形状。

返回当前部件中新建的表格句柄。

bookmark_fill_result fill_bookmarks(std::span<const bookmark_text_binding> bindings)

bindings:书签名和文本绑定。

返回匹配、替换和缺失书签统计。

std::size_t replace_bookmark_text(const std::string &bookmark_name, const std::string &replacement)

bookmark_name:目标书签。replacement:插入文本。

返回被替换的书签实例数量。

std::size_t replace_content_control_text_by_tag(std::string_view tag, std::string_view replacement)

tag:内容控件 tag。replacement:插入文本。

返回被替换的匹配控件数量。

std::size_t replace_content_control_with_table_by_tag(std::string_view tag, const std::vector<std::vector<std::string>> &rows)

tag:目标控件。rows:生成表格的行/单元格文本矩阵。

返回被替换为表格的匹配控件数量。

template_validation_result validate_template(std::span<const template_slot_requirement> requirements) const

requirements:当前部件必需的书签/内容控件槽位。

返回缺失和类型不匹配槽位的校验结果。

std::size_t append_hyperlink(std::string_view text, std::string_view target)

text:超链接显示文本。target:URL 或关系目标。

返回创建的超链接数量;0 表示未追加。

部件基础

每个 TemplatePart 都对应文档包中的一个 XML 部件。正文通常来自 Document::body_template(),页眉和页脚则来自对应的 header/footer 入口。

方法

返回值

用途

entry_name()

std::string_view

返回当前部件在 .docx 包中的条目名。

paragraphs()

Paragraph

遍历当前部件中的段落。

append_paragraph(text, formatting)

Paragraph

在当前部件末尾追加段落。

tables()

Table

遍历当前部件中的表格。

append_table(row_count, column_count)

Table

在当前部件末尾追加表格。

书签

书签 API 适合处理合同、报价单、通知书等模板中的命名占位区域。可以只替换 文本,也可以把书签位置替换成段落、表格或图片。

方法

返回值

用途

list_bookmarks() const

std::vector<bookmark_summary>

枚举当前部件中的书签。

find_bookmark(std::string_view bookmark_name) const

std::optional<bookmark_summary>

按书签名查找单个书签。

replace_bookmark_text(bookmark_name, replacement)

std::size_t

替换匹配书签内部的文本。

fill_bookmarks(std::span<const bookmark_text_binding> bindings)

bookmark_fill_result

一次填充多个书签,并返回填充结果。

replace_bookmark_with_paragraphs(bookmark_name, paragraphs)

std::size_t

用段落内容替换指定书签。

replace_bookmark_with_table(bookmark_name, rows)

std::size_t

用表格替换指定书签。

replace_bookmark_with_image(bookmark_name, image_path)

std::size_t

用图片替换指定书签。

set_bookmark_block_visibility(bookmark_name, visible)

std::size_t

显示或隐藏带书签的块级内容。

内容控件

内容控件对应 Word 中的结构化文档标记。实际模板中通常使用 tag 作为稳定标识, 因此按 tag 替换文本、表格、图片或表单状态是最常见的工作流。

方法

返回值

用途

list_content_controls() const

std::vector<content_control_summary>

枚举当前部件中的内容控件。

find_content_controls_by_tag(std::string_view tag) const

std::vector<content_control_summary>

按 tag 查找内容控件。

find_content_controls_by_alias(std::string_view alias) const

std::vector<content_control_summary>

按 alias 查找内容控件。

replace_content_control_text_by_tag(tag, replacement)

std::size_t

按 tag 替换内容控件中的纯文本。

replace_content_control_with_paragraphs_by_tag(tag, paragraphs)

std::size_t

按 tag 用段落替换内容控件。

replace_content_control_with_table_by_tag(tag, rows)

std::size_t

按 tag 用表格替换内容控件。

replace_content_control_with_image_by_tag(tag, image_path)

std::size_t

按 tag 用图片替换内容控件。

set_content_control_form_state_by_tag(tag, options)

std::size_t

设置复选框、日期、下拉框、组合框、锁定或数据绑定状态。

Custom XML 同步

Document::sync_content_controls_from_custom_xml() 会重新打开当前路径对应的源包, 并根据 Custom XML 数据解析内容控件绑定。它使用 open(options) 保留的限制(调用 create_empty() 后使用默认限制),先复验当前完整包;item、properties 和 relationships 即使关系目标使用二进制扩展名,也按语义 XML 应用限制。

包枚举、资源限制、entry 读取和 reader 关闭失败会返回 std::nullopt,并在 last_error() / entry_name 中保留精确上下文;这些失败都在修改任何内容控件 之前发现。可以安全跳过的缺失、未绑定或格式错误 Custom XML 仍保持兼容行为,并由 同步结果报告,不会被误写成 archive I/O 成功。

正文、页眉和页脚的同步采用同一个内存事务:解析、结果构建、XML 克隆或任一文本 重写发生分配失败时返回 std::errc::not_enough_memory,并保持调用前的 DOM、 尚未保存的编辑、dirty 状态和现有 XML 句柄代次不变。成功且实际同步了至少一个 内容控件时会原子发布重建后的 WML DOM;此前取得的 Paragraph、Run、 Table 和 TemplatePart 句柄随即失效,调用方必须重新获取。没有匹配同步项的 成功调用不会重建 DOM,也不会使句柄失效。

模板校验

模板校验 API 用于把当前部件的必需槽位显式化,并检查必需书签和内容控件。

方法

返回值

用途

validate_template(requirements) const

template_validation_result

按必需槽位校验书签和内容控件。

文档级 Schema 工作流

validate_template_schema(...)、scan_template_schema(...)、 build_template_schema_patch_from_scan(...) 和 onboard_template(...) 是 featherdoc::Document API,因为它们会聚合正文、页眉、页脚和分节目标槽位。 TemplatePart 负责部件级填充和 validate_template(...) 校验; 整篇文档的 schema 治理应从 Document 入口执行。

示例

featherdoc::Document doc{"template.docx"};
if (doc.open()) {
    return 1;
}

auto body = doc.body_template();
body.fill_bookmarks({
    {"invoice_no", "INV-2026-001"},
    {"customer_name", "Ada Lovelace"},
});
body.replace_content_control_text_by_tag("status", "approved");

auto validation = body.validate_template({
    {"invoice_no", featherdoc::template_slot_kind::text, true},
    {"status", featherdoc::template_slot_kind::text, false},
});
auto onboarding = doc.onboard_template();

return (!validation || doc.save_as("filled.docx")) ? 1 : 0;