有人把一个 Word 模板和紧迫的截止日期交给你。它需要什么数据?通常的做法是打开它,滚动查看,猜测,运行,阅读错误信息,然后再运行一次。使用本地运行的 GroupDocs.Assembly.Mcp(dnx GroupDocs.Assembly.Mcp --yes),Claude Desktop、Cursor 或 Copilot 可以直接询问模板:get_template_fields 会返回所有标签、使用的数据名称以及用于填充的 JSON 骨架,而无需运行引擎;如果运行失败,错误会告诉你需要更改什么:

order-lines.docx 需要哪些数据?如果它无法生成,请告诉我原因以及如何修复模板。

一步步的配置和故障排除方法请参见文档:如何找出模板需要哪些内容以及为何会失败。

为什么在填充之前先检查?

因为反复试错是学习模式的高成本方式。一个仅从文档可见文本猜测字段名的代理会在模板使用 customer.Name 时猜出 CustomerName,每一次错误的猜测都会导致一次往返请求和令人困惑的错误。模板不是散文;它是带有数据契约的程序,而这个契约是可以读取的。

这就是 get_template_fields 所做的全部工作。它解析 <<…>> 标签,算出名称,并构建骨架:

-> get_template_fields {"template":{"filePath":"order-lines.docx"}}
<- { "tagCount": 3,
     "dataSourceNames": [ "lines" ],
     "fields": [ "lines[].Title", "lines[].Quantity" ],
     "dataSkeleton": { "lines": [ { "Title": "", "Quantity": "" } ] },
     "notes": [ "fields and dataSkeleton are inferred from the tags,
       not from the engine; values computed by Select/GroupBy
       projections are not followed." ] }

注释诚实地说明了方法:这是一种静态检查。Select 投影中产生的字段不会被追踪。对于普通的合同、信函或发票模板,骨架正好是需要填充的内容。

骨架还会改变与你的对话方式。代理不再说“我尝试生成订单但失败了”,而是可以说“此模板需要一个包含标题和数量的行列表;我在你的邮件中找到了三条,这里是它们”,随后再进行生成。检查成本低,不需要任何数据,也不触及文档本身,因此是对任何未见过的模板的首选调用,也是每当有人编辑模板后再次调用的正确方式。

三种失败,三种答案

template problem          what the server says          the fix
------------------------  ----------------------------  -------------------
{{name}} placeholders     "2 '{{...}}' placeholder(s).  write <<[name]>>
                          ... does not process that
                          syntax"
<<foreach>> never closed  "Unexpected end of template.  add <</foreach>>
                          A block tag is not closed"
data lacks a field        "The template reads 'Email',  add it, or
                          which the data does not have" allowMissingMembers

错误的语法。 许多流行的模板是为其他引擎编写的,使用了 {{name}}。GroupDocs.Assembly 会把这些当作普通文本保留下来,检查时会提前提示:

-> get_template_fields {"template":{"filePath":"shipping-notice.docx"}}
<- { "tagCount": 0, "notes": [ "No <<…>> tags were found: ...",
     "The template contains 2 '{{…}}' placeholder(s). GroupDocs.Assembly
      does not process that syntax and leaves it as text; write
      <<[name]>> instead." ] }

未闭合的块。 我们的 order-lines.docx 打开了一个 <<foreach>> 却从未关闭。检查会愉快地列出所有标签;生成时则会报错:

-> assemble_document {"template":{"filePath":"order-lines.docx"},
     "dataJson":"{\"lines\":[{\"Title\":\"Cable\",\"Quantity\":2}]}"}
<- Document assembly failed for 'order-lines.docx': ...
   Unexpected end of template. A block tag is not closed: every
   <<foreach>> needs <</foreach>> and every <<if>> needs <</if>>.

缺失的字段。 当数据中缺少模板读取的某个字段时,错误会指出该字段,说明名称区分大小写,并提供开关:allowMissingMembers: true 会对缺失的成员输出空值或空列表,而不是报错。

当模板充满错误时

有些模板存在多个错误,一次一次地修复每次失败的运行非常慢。inlineErrors: true 会把模板本身变成错误报告:文档仍会生成,每个有问题的标签旁边会写入相应的错误信息。以下是来自 GroupDocs.Assembly 示例的模板:

-> assemble_document {"template":{"filePath":"inline-error.docx"},
     "dataJson":"{\"name\":\"x\"}","inlineErrors":true}
<- Assembled 'inline-error.docx' ... The template has errors: each one
   is written into the output next to its tag, starting with 'Error!'

输出中会出现 << var [name] Error! An assignment operator is expected. >>,位于文档中标签所在的位置。打开文件,修复每个标记的错误,然后在不使用该标志的情况下再次运行。

检查无法看到的情况

二进制 Outlook 模板是例外。.msg 文件的标签在不生成的情况下无法读取,服务器会如此说明,而不是返回一个看似“没有字段”的空列表:

-> get_template_fields {"template":{"filePath":"contracts-table.msg"}}
<- { "readable": false, "notes": [ "Tags cannot be read from a .msg
     template without generating it. Save the template as DOCX, XLSX,
     PPTX or EML to inspect it, or generate it with assemble_document
     and inlineErrors=true to see which fields fail." ] }

我们遇到的另一个陷阱是:数据中为空的列表没有成员类型。我们的合同模板会计算 item.Quantity * item.UnitPrice;当 "items": [] 且 allowMissingMembers: true 时,生成仍会因 “Can not apply operator ‘’ to operands of type ‘System.Object’ and ‘System.Object’”* 而失败。让代理在生成前检查列表是否为空,并询问你空合同应是什么样子。

诚实的限制

  • 检查是静态的:不会跟踪 Select 和 GroupBy 投影,.msg 模板无法读取。
  • 模板被视为可信输入;图片和文档标签会加载其表达式返回的路径和 URL。
  • 评估模式:每个输出都会以 “Evaluation Only. Created with GroupDocs.Assembly 26.7…” 开头。
  • 日期:传入 2026-11-12T00:00:00 并在模板中使用 :"d MMMM yyyy" 格式化;在 UTC+2 的机器上,仅日期字符串会被提前一天,而 "12.11.2026" 会被读取为 11 月 12 日。

FAQ

我如何查看一个 Word 模板需要哪些字段?
让代理调用 get_template_fields。你可以在本地获取标签、数据名称以及 JSON 骨架,而无需生成任何内容。

为什么我的模板会打印 {{name}} 而不是实际值?
因为 GroupDocs.Assembly 的标签是 <<[name]>>。服务器的检查会标记 {{…}} 占位符,并告诉你应该改写为什么。

Markdown 可以作为模板吗?
可以。我们的 product-readme.md 中的 <<[product]>> 和 <<[description]>> 标签会像 Word 文件一样被检查,并直接生成 DOCX。

深入了解