我正在寻找一种方法,将机器可读的元数据添加到我生成的 DOCX 报告中。目标是允许用户修改文档的样式,然后将其重新上传到系统,同时保留元数据。
第一次尝试时,我天真地尝试将元数据存储在评论中,但我注意到一些编辑器,特别是 Microsoft Word,在修改后会删除我的评论并生成没有它们的 DOCX 文件。
我也尝试了结构化文档标签,但 Google Docs 和 Microsoft Word 都会在样式修改后删除它们。
最后,我尝试使用自定义 XML,但 Google Docs 和 Microsoft Word 都删除了我添加的属性和标签。
我搜索了很多,但还是没找到有效的解决方案。有人遇到过类似的问题吗?可以分享一些建议吗?
PS1
由于即使是小型 DOCX 文件中也包含太多行,因此我创建了一个极简的 repo,以便更好地展示我迄今为止的尝试。每次尝试都放在一个单独的目录中。每个目录包含:
- Document.docx — 使用一些隐藏元数据手动创建的基础文件。
- ModifiedWithGoogle.docx 和 ModifiedWithWord.docx — 在 Google Docs 或 Microsoft Word 中编辑文档后的结果。
- 解压每个 .docx 文件的内容,以便更轻松地检查内部 XML。
仓库:https://github.com/kishieel/docx-metadata
第一次尝试时,我使用注释添加了元数据。这在 Google Docs 上效果很好,即使使用剪切粘贴移动文本,注释也能保留。然而,Microsoft Word 删除了所有注释。也许 Word 需要一种不同的注释创建方式?
示例输入:
<!-- 1_comments/Document/word/document.xml -->
<w:document ...>
<w:body>
<w:p>
<w:commentRangeStart w:id="0" />
<w:r>
<w:t xml:space="preserve">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris quis mollis tellus. Aenean at maximus nunc.</w:t>
</w:r>
<w:commentRangeEnd w:id="0" />
</w:p>
</w:body>
</w:document>
<!-- 1_comments/Document/word/comments.xml -->
<w:comments ...>
<w:comment w:id="0" w:date="2025-04-07T09:10:21.783Z">
<w:p>
<w:r>
<w:t xml:space="preserve">Some metadata #1</w:t>
</w:r>
</w:p>
</w:comment>
</w:comments>
在第二种方法中,我尝试使用 SDT。在这种情况下,Microsoft Word 保留了它们(尽管它将每个句子拆分成了单独的单词,这可能是默认行为,也可能是出了什么问题)。Google Docs 将它们从修改后的文件中完全删除了。
示例输入:
<!-- 2_structured_document_tags/Document/word/document.xml -->
<w:document ...>
<w:body>
<w:p>
<w:sdt>
<w:sdtPr>
<w:tag w:val="Some metadata #1" />
<w:alias w:val="Some alias #1" />
</w:sdtPr>
<w:sdtContent>
<w:r>
<w:t xml:space="preserve">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris quis mollis tellus. Aenean at maximus nunc.</w:t>
</w:r>
</w:sdtContent>
</w:sdt>
</w:p>
</w:body>
</w:document>
准备好后我将提供自定义 XML 示例。
我最近没有通过您提到的三种方法(Microsoft Word、Google Docs 和 LibreOffice Writer)保存元数据的实际经验,但尝试了在 Word 中存储我所知道的材料的各种方法。
为了进行测试,我一直在使用
Microsoft 365 MSO (Version 2503 Build 16.0.18623.20116) 64-bit
、Windows 10
LibreOffice Writer Version: 24.2.7.2 (X86_64) / LibreOffice Communit Build ID: 420(Build:2)
和Linux
当前的免费版本Google Docs
(我不知道 Google 是否有功能更强大的付费版本。我直接在 Word 中创建文档,根据需要使用 VBA,例如添加自定义 XML 部分或文档变量。我从未尝试以 .docx 以外的任何格式保存或下载。关于 .docx 格式有很多文档,还有一些关于 WOrd 实现的相当不错的 MS 文档,但我没有寻找 Google Docs 和 LibreOffice 的等效文档。你可能确实需要知道 MS、LibreOffice 和 Google“官方支持”哪些功能Word 中用于存储元数据的类型有两种:一种是“文档范围的”,另一种是“与文档中某个位置相关的”。对于“文档范围的”,有
{ DOCVARIABLE }
字段显示值{ DOCPROPERTY }
字段显示值。对于“与文本中的位置相关”,原则上至少可以使用以下内容:
{ DOCPROPERTY }
具有自定义文档属性的字段(可见){ DOCVARIABLE }
带有文档变量的字段(可见){ SET }
字段(可见,取决于用户的设置和操作),例如{ SET ABookMarkName "to some metadata" }
我知道你尝试过注释,而且我认为它们应该能正常工作,尽管你发现了一些问题,但我认为它们不太容易隐藏。隐藏文本、脚注、尾注或内容控件也一样,所以我没有真正尝试过这些。此外,大量的脚注或尾注往往会干扰文档布局。
LibreOffice 成功完成了我在 Word 中尝试的大多数操作。然而,保存时会弹出“部分内容可能无法正确保存”之类的提示框。
Google Docs 丢失了我尝试过的大部分内容,但至少保留了注释、自定义文档属性,甚至还保留了
{ DOCPROPERTY }
在文档中插入这些值所需的字段。它删除了:{ DOCVARIABLE }
域代码{ SET }
域代码这让我觉得,唯一可能与 Google Docs 兼容的就是自定义文档属性。它们确实存在限制(我认为自定义文档属性的数量、每个属性的长度或总长度都有限制)。
对于“文档级”元数据,您可能需要将数据分成更小的块。
对于“位置”元数据,这些最大值很可能存在问题。即使没有问题,使用适当的
{ DOCPROPERTY }
字段标记位置也意味着显示属性值——如果您不想这样做,您可能需要执行以下操作:{ DOCPROPERTY mymark }
标记位置,因此您只会得到一个带有单个空格的结果。在 Word 中,可以利用 Word 对字段代码中的额外信息不太挑剔的事实,因此您可以拥有一个名为blank 的空白属性和一个字段代码
{ DOCPROPERTY blank myprop }
,但不幸的是,Google Docs 会删除“myprop”部分。就是这样。
只是为了涵盖我最初在评论中提出的一些观点:
在您的“comments_1”示例中,初始版本(您发布的 xml 代码和相关的 Document.docx)中没有出现注释的原因是因为Word需要一个 <w:commentReference> 元素才能使注释显示在 UI 中。
例如,如果您将问题中发布的标记更改为此并重新创建.docx,则在 Word 中打开 .docx 时您应该会看到第一条注释。
(您不必拥有该
<w:rPr>
元素,但 Word 会插入一个)。正如我最初在评论中提到的,您的 1_comments .docx 文件无法打开的原因是 docProps/custom.xml 文件包含两个具有相同 FMTID 和名称的元素(这是不允许的)。该文件的长度也接近 600 个字符,虽然我以为 Word 对自定义文档属性的限制是 255 个字符,但它似乎并没有报错或截断。
因此,在这里,我还将 custom.xml 更改为以下内容以解决此问题: