【问题标题】:Problems extracting XML code from Word with Python使用 Python 从 Word 中提取 XML 代码的问题
【发布时间】:2014-12-18 03:05:06
【问题描述】:

我正在尝试使用 Python 从 Word 文档中提取 XML 代码。这是我尝试过的代码:

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

我创建了一个测试文档并在上面运行了函数getXML。结果如下:

 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="00971B91" w:rsidRPr="00971B91" w:rsidRDefault="00B52719"><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:t>Test</w:t></w:r></w:p><w:sectPr w:rsidR="00971B91" w:rsidRPr="00971B91" w:rsidSect="009C4305"><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>'

有一些明显的问题。一种是 XML 代码以“b”开头并以撇号结尾。其次,在第一组尖括号后面有一个“\r\n”。

我的最终目标是修改 XML 代码以创建一个新的 Word 文档——请参阅this 问题——但提取的 XML 异常使我无法这样做。

有谁知道为什么提取的 XML 有这些奇怪的特性,以及如何删除它们?

编辑:我尝试使用 lxml 模块来解析这段代码,但我得到了不同的错误。

我创建了一个新函数getXmlTree

from lxml import etree

def getXmlTree(xmlString):
    return etree.fromstring(xmlString)

然后我运行代码 etree.tostring(getXmlTree(getXml("test.docx")),pretty_print=True) 并收到更合理的 XML 代码。

当我尝试创建新的 Word 文档时出现问题。我创建了以下函数来将 XML 代码转换为 Word 文档(无耻地从 here 窃取):

import zipfile
from lxml import etree
import os
import tempfile
import shutil

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:
        xmlString = etree.tostring(xmlContent,pretty_print=True)
        f.write(xmlString)
    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)

在尝试创建新的 Word 文档之前,我想看看是否可以通过将 xmlContent = getXmlTree(getXml("test.docx")) 替换为上述函数中的参数来创建原始测试文档的副本。然而,当我运行代码时,我收到一条错误消息:

f.write(xmlString)

TypeError: must be str, not bytes

改用f.write(str(xmlString)) 并没有帮助;它创建了一个新的 Word 文档,但如果我试图打开它,Word 会崩溃。

EDIT2:尝试使用f.write(xmlString.decode("utf-8")) 运行上述代码,但没有帮助; Word 仍然崩溃。

【问题讨论】:

标签: python xml docx zip


【解决方案1】:

我的猜测是 XML 没有被正确编码。首先,使用"wb"作为模式将文档文件写入二进制文件。其次,告诉etree.tostring() 编码是什么并包含XML 声明。

with open(os.path.join(tmpDir, "word/document.xml"), "wb") as f:
    xmlBytes = etree.tostring(xmlContent, encoding="UTF-8", xml_declaration=True, pretty_print=True)
    f.write(xmlBytes)

【讨论】:

  • 谢谢。我没有遵循您的确切解决方案;相反,我只是将getXml 中的xmlString= str(zip.read("word/document.xml")) 替换为xmlString = zip.read("word/document.xml").decode("uft-8"),这样就成功了。不过,我仍然遇到一些问题,这些问题在here 中进行了概述;如果您能看一看,我将不胜感激。
猜你喜欢
  • 2015-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多