如何使用Python保存已编辑的Word文档?

时间:2014-12-15 20:44:08

标签: python xml docx zipfile

我正在尝试创建一个脚本,它可以从Word文档中提取XML,修改它,最后保存新的Word文档,所有这些都使用Python。这是我使用的代码,它实际上是从here中窃取的:

import zipfile
import os
import tempfile
import shutil


def getXml(docxFilename):
    zip = zipfile.ZipFile(open(docxFilename,"rb"))
    xmlString = str(zip.read("word/document.xml"))
    return xmlString

def createNewDocx(originalDocx,xmlContent,newFilename):
    tmpDir = tempfile.mkdtemp()
    zip = zipfile.ZipFile(open(originalDocx,"rb"))
    zip.extractall(tmpDir)
    with open(os.path.join(tmpDir,"word/document.xml"),"w") as f:
        f.write(xmlContent)
    filenames = zip.namelist()
    zipCopyFilename = newFilename
    with zipfile.ZipFile(zipCopyFilename,"w") as docx:
        for filename in filenames:
            docx.write(os.path.join(tmpDir,filename),filename)
    shutil.rmtree(tmpDir)

我的代码和Virantha之间的一个重要区别是他将createNewDocx表示为一个类。不幸的是我不知道哪些类或它们是如何工作的,所以我认为编写一个函数会更容易。

getXML从Word文档中提取XML。我在一个测试文档(名为test.docx)上试用了它,效果很好。理论上,createNewDocx应该将原始docx文件(在本例中为test.docs)和修改后的XML作为字符串来创建一个名为newFileName的新Word文档。

作为测试,我使用原始XML运行createNewDocx,看看我是否会获得text.docx的复制版本。也就是说,我跑了

originalXml = getXml("test.docx")
createNewDocx("test.docx",originalXml,"test2.docx")

这确实创建了一个名为“test2.docx”的Word文档,但是当我尝试打开文件时,它就无法打开; Word会崩溃。

有谁知道如何修改我的代码才能使其正常工作?

编辑:我决定加入originalXml以防万一格式化问题。

b'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n<w:document xmlns:ve="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml"><w:body><w:p w:rsidR="00000000" w:rsidRDefault="00971B91"><w:r><w:t>You owe me ${debt}. Pay back soon.</w:t></w:r></w:p><w:p w:rsidR="00971B91" w:rsidRPr="00971B91" w:rsidRDefault="00971B91"><w:pPr><w:rPr><w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman" w:cs="Times New Roman"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr></w:pPr><w:r><w:rPr><w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman" w:cs="Times New Roman"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t xml:space="preserve">You owe me </w:t></w:r><w:r><w:rPr><w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman" w:cs="Times New Roman"/><w:b/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>${debt}</w:t></w:r><w:r><w:rPr><w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman" w:cs="Times New Roman"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t xml:space="preserve">. Pay back </w:t></w:r><w:r><w:rPr><w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman" w:cs="Times New Roman"/><w:i/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>soon.</w:t></w:r></w:p><w:sectPr w:rsidR="00971B91" w:rsidRPr="00971B91"><w:pgSz w:w="12240" w:h="15840"/><w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440" w:header="708" w:footer="708" w:gutter="0"/><w:cols w:space="708"/><w:docGrid w:linePitch="360"/></w:sectPr></w:body></w:document>'

EDIT2:我更仔细地查看上面的XML代码,并意识到开头有一个不寻常的“b”,最后有一个紧密的括号。我删除了这些异常并再次运行代码。现在Word给了我一个更明智的错误,即“第1行,第56列”存在问题。这对应于上面XML代码中的“\ r \”。

显然我的代码没有正确地提取XML。任何人都知道如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

通过转换&#34; zip.read(&#34; word / document.xml&#34;)&#34;,您将一个字节转换为字符串,以便保持&#39; b&#39;作为一个角色。

def getXml(docxFilename):
zip = zipfile.ZipFile(open(docxFilename,"rb"))
xmlString = str(zip.read("word/document.xml"))
return xmlString

这就是&#34; xmlString&#34;没有属性,因为它是一个字符串。 你必须删除你在返回之前转换解码:

def getXml(docxFilename):
zip = zipfile.ZipFile(open(docxFilename,"rb"))
xmlString = zip.read("word/document.xml")
return xmlString.decode('utf-8')

希望它对其他人有所帮助!