如何将等式从 docx 复制到另一个 docx 中的特定位置?

How can I copy equations from docx to a specific location in another docx?

您好,我目前正在尝试编写结合 docx 文件的代码。这些文件可能包含文本、图像、table 或方程式。该代码旨在复制这些对象并将它们附加到基本 docx。我可以使用 docx 模块的 'add_picture' 和 'add_paragraph' 方法复制和合并文本、图像和 tables,但我不能对单词方程式执行此操作。我决定尝试深入研究 docx 的 xml 并从那里复制方程式部分。我可以将方程附加到我的基本文档中,但是当我继续附加图片、文本和 table 时,这些方程会出现在 docx 的 end 处。我的问题是:为什么如果我按照我希望它们出现的顺序循环遍历附加对象并且有一种方法会发生这种情况防止代码将方程式放在 docx 的末尾。

这里是代码的一些概述:

  1. 创建基础文档:

    文档=文档('basedoc.docx')

  2. 获取要追加的子文档列表
  3. 通过子文档列表开始循环
  4. 我遍历每个子文档并找到不同的父对象和子对象。我在这个名为 'iter_block_items'(https://github.com/python-openxml/python-docx/issues/276) 的网站上找到了这个函数 文档项称为块。
  5. 对于子文档的每个块项目,我都对类型、样式以及是否存在方程进行了分类:

    if isinstance(块,段落):

    if "r:embed" in block._element.xml:
    
        append content,style, and equation arrays, content being a drawing/image
    
    elif "m:oMathPara" in block._element.xml:
    
        append content,style, and equation arrays, content being an equation
        equationXml.append(block._element.xml)
    
    elif 'w:br w:type="page"' in block._element.xml:
    
        append content,style, and equation arrays, content being a page break
    
    else:
    
        append content,style, and equation arrays), content being text
    

    其他:

    append content,style, and equation arrays, content being a table
    
  6. 获得内容和样式数组后,我循环遍历内容数组并附加 table、绘图、分页符和文本。

        if equationXml[i]=='0': #the content is either an image, table, text, or page break
            if "Table" in str(contentStyle[i]):
                    insert table and caption
            else:
                if "drawing" in content[i]:
                    insert image and caption
    
                elif "pageBreak" in content[i]:
                    document.add_page_break()
                else:
                    insert text
        else:                        #there is an equation present
          document=EquationInsert.(document,equationXml[i])
    

我的 EquationInsert 文件有一个名为 'AddEquation' 的函数,我基本上重写了我的文档对象(其中 UpdateableZipFile 是我在网上找到的一个代码,可以快速更新 zip 文件中的文件):

def AddEquation(self,document,equationContent):
    document.save('temp.docx')
    z = zipfile.ZipFile('temp.docx')
    tree=etree.parse(z.open('word/document.xml'))
    nmspcDict = tree.getroot().iter().next().nsmap

    for key in nmspcDict:
        ET.register_namespace(key, nmspcDict[key])
    tree2=etree.ElementTree(etree.fromstring(equationContent))
    xmlRoot2=tree2.getroot()
    xmlRoot=tree.getroot()
    xmlRoot[1].append(xmlRoot2) #note that [1] had to be used bc [0] was a comment. need to see if general case or not


    tree.write("document.xml",encoding="utf-8", xml_declaration=True, standalone="yes", pretty_print=True)

    with UpdateableZipFile.UpdateableZipFile("temp.docx","a") as o:
        o.write("document.xml","word/document.xml")

    document = Document('temp.docx') 
    os.remove('document.xml')
    z.close()
    os.remove('temp.docx')
    return document

此代码添加了方程式,但随着主代码继续遍历子文档项,方程式只是以某种方式被推到基本文档的末尾。我试过从 Insert equation 函数返回一个 docx 并从中创建一个新文档,但这没有做任何事情。如果有人对如何使方程式不到达文件末尾有任何建议,我们将不胜感激。否则我将不得不冒险看看如何将这些方程式转换为图像 =/ 或 docx 可以处理的东西。我对 solutions/suggestions/comments 持开放态度。谢谢!

我相信您会在 XML 中找到答案。您可以使用 opc-diag.

方便地浏览 .docx "package" 中的 XML "part"

Word 文档中的段落和表格位于 document.xml 部分,作为 <w:body> 元素下的子元素。 <w:body> 中的最后一个元素是节元素 (<w:sectPr> IIRC)。如果您在该元素之后附加方程式,随着新段落和表格被添加到该 sectPr 元素上方,它们将继续浮动到底部。

我会使用一个尽可能短的测试文档并检查您的代码生成的 XML,将其与看起来像您想要的方式(可能是在 Word 中手工创建的)进行比较。这应该可以快速指出您的代码中存在的任何元素排序问题。