python-docx - 如何添加 w:altChunk 及其与 python-docx 的关系
问题描述
我有一个用例,它<w:altChunk/>
通过将 HTML 文件注入(片段)作为备用块来使用 Word 文档中的元素,并在文件打开时让 Word 执行它。当前的实现是使用 XML/XSL 来编写 WordML XML、修改关系以及手动完成所有打包工作,这真的很痛苦。
我想迁移到 python-docx,但 API 不直接支持。目前我找到了一种<w:altChunk/>
在文档 XML 中添加的方法。但是仍然很难找到一种将关系和相关文件添加到包中的方法。
我认为我应该制作一个兼容的部分并将其传递给document.part.relate_to
函数来完成它的工作。但仍然无法弄清楚如何:
from docx import Document
from docx.oxml import OxmlElement, qn
from docx.opc.constants import RELATIONSHIP_TYPE as RT
def add_alt_chunk(doc: Document, chunk_part):
''' TODO: figuring how to add files and relationships'''
r_id = doc.part.relate_to(chunk_part, RT.A_F_CHUNK)
alt = OxmlElement('w:altChunk')
alt.set(qn('r:id'), r_id)
doc.element.body.sectPr.addprevious(alt)
更新:
根据scanny的建议,以下是我的工作代码。非常感谢史蒂夫!
from docx import Document
from docx.oxml import OxmlElement
from docx.oxml.ns import qn
from docx.opc.part import Part
from docx.opc.constants import RELATIONSHIP_TYPE as RT
def add_alt_chunk(doc: Document, html: str):
package = doc.part.package
partname = package.next_partname('/word/altChunk%d.html')
alt_part = Part(partname, 'text/html', html.encode(), package)
r_id = doc.part.relate_to(alt_part, RT.A_F_CHUNK)
alt_chunk = OxmlElement('w:altChunk')
alt_chunk.set(qn('r:id'), r_id)
doc.element.body.sectPr.addprevious(alt_chunk)
doc = Document()
doc.add_paragraph('Hello')
add_alt_chunk(doc, "<body><strong>I'm an altChunk</strong></body>")
doc.add_paragraph('Have a nice day!')
doc.save('test.docx')
注意:altChunk 部分仅在使用 MS Word 打开文档时工作/出现
解决方案
好吧,无论如何这里有一些提示。也许您可以在最后发布您的工作代码作为完整的“答案”:
alt-chunk 部分需要作为一个
docx.opc.part.Part
对象开始它的生命。参数应该是文件的
blob
字节,通常但不总是纯文本。它必须是字节,而不是 unicode(字符),所以任何编码都必须在调用Part()
.我希望您可以解决其他论点:
package
是整体 OPC 包,可在document.part.package
.- 您可以使用
docx.opc.package.OpcPackage.next_partname()
来获取基于根模板的可用部件名称,例如:“altChunk%s”,用于“altChunk3”等名称。检查 Word 为这些使用的部件名前缀,可能使用unzip -l has-an-alt-chunk.docx
; 应该很容易发现。 - 内容类型是
docx.opc.constants.CONTENT_TYPE
. 检查[Content_Types].xml
具有 altChunk 的 .docx 文件中的部分以查看它们使用的内容。
一旦形成,该
document_part.relate_to()
方法将创建适当的关系。如果有多个关系(不常见),那么您需要分别创建每个关系。特定部分只会有一种关系,只有一些部分与其他部分相关。检查现有 .docx 中的关系以查看,但很好猜测在这种情况下它只是一个。
所以你的代码看起来像:
package = document.part.package
partname = package.next_partname("altChunkySomethingPrefix")
content_type = docx.opc.constants.CONTENT_TYPE.THE_RIGHT_MIME_TYPE
blob = make_the_altChunk_file_bytes()
alt_chunk_part = Part(partname, content_type, blob, package)
rId = document.part.relate_to(alt_chunk_part, RT.A_F_CHUNK)
etc.
推荐阅读
- mysql - 为什么ansible无法连接MySql?
- katalon-studio - Katalon Analytics 未显示从测试集合执行的所有测试套件的结果
- c# - 从可观察集合中绑定组合框项目源时遇到问题
- java - 使用 ContentCachingRequestWrapper 后缺少所需的请求正文
- javascript - 在服务器上创建 Zip 存档并在客户端下载
- jena - 有谁知道如何让 tdb2.dump 命令真正做任何事情
- sql - 在 oracle sql 中从包含 XML 格式字符串的列中获取子字符串
- apache-spark - 如何将多个列作为参数传递给 Spark 数据框
- express - Vue.js devServer.proxy 的问题
- r - 用 R 中的另一个特定模式重命名多个文件的特定模式