Word文件的OpenXML解析

自Office 2007以来,新推出的.docx文件可以无损转换成OpenXML格式,以便于第三方工具生成、修改Word文件。本文以Python为背景,简单解析OpenXML中的常用元素,主要用作个人备忘。

个人邮箱为qxsoftware@163.com,欢迎来信交流。

本文目前仍在施工中,因疫情影响,完工日期未定QAQ
12/1/2020更新:感觉这个坑应该不会填了,如果大家有问题欢迎邮件讨论。

本文目录:

  • 准备工作
  • 初识OpenXML
  • 获取Word XML
    • 手动将Word文件另存为XML文件
    • 使用python-docx获取OpenXML
  • Word OpenXML常用结构
    • 整体结构:body、styles、setting等
    • 段落Paragraph结点:<w:p>
    • 基本格式单位Run结点:<w:r>
    • 格式Properties结点:<w:pPr><w:rPr>
      • 字体<w:rFonts>
      • 字号<w:sz><w:szCs>
    • 看的见的文字Text:<w:t>
    • 修订版本号rsid
    • 注音系统Ruby:<w:ruby>

准备工作

Python解析OpenXML的两个常用库:python-docx与lxml,可通过pip安装,若对两个库不熟悉请参阅以下资料:

  • 使用python-docx读取word文件
  • lxml学习笔记(含增删改查)
  • lxml.etree.Element中的.addprevious().addnext()

本文举例所用的文本内容,为唐朝诗人张若虚的《春江花月夜》,全文如下:

《春江花月夜》
【唐·张若虚】
春江潮水连海平,海上明月共潮生。
滟滟随波千万里,何处春江无月明?
江流宛转绕芳甸,月照花林皆似霰。
空里流霜不觉飞,汀上白沙看不见。
江天一色无纤尘,皎皎空中孤月轮。
江畔何人初见月?江月何年初照人?
人生代代无穷已,江月年年只相似。
不知江月待何人,但见长江送流水。
白云一片去悠悠,青枫浦上不胜愁。
谁家今夜扁舟子?何处相思明月楼?
可怜楼上月徘徊,应照离人妆镜台。
玉户帘中卷不去,捣衣砧上拂还来。
此时相望不相闻,愿逐月华流照君。
鸿雁长飞光不度,鱼龙潜跃水成文。
昨夜闲潭梦落花,可怜春半不还家。
江水流春去欲尽,江潭落月复西斜。
斜月沉沉藏海雾,碣石潇湘无限路。
不知乘月几人归?落月摇情满江树。
  • 将全文以纯文本方式粘贴到新建的word文档中,不修改任何格式,直接将文件保存为”春江花月夜.docx“。

  • (非必需) 之后,再将文件另存为”word xml(*.xml)“文件,命名为”春江花月夜.xml“,并使用喜欢的xml查看器打开(个人推荐安装了XML Tools插件的Notepad++ 不再推荐Notepad++,原因中国人都懂,我现在自己用VSCode)。

本文将以此为例。


初识OpenXML

准备工作完成后,先看一个OpenXML的简单例子(注意这不是一个完整的word文件):

<w:body xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex"><w:p w:rsidR="00691F43" w:rsidRDefault="00691F43" w:rsidP="00691F43"><w:r><w:rPr><w:rFonts w:hint="eastAsia"/></w:rPr><w:t>《春江花月夜》</w:t></w:r></w:p><w:p w:rsidR="00691F43" w:rsidRDefault="00691F43" w:rsidP="00691F43"><w:r><w:rPr><w:rFonts w:hint="eastAsia"/></w:rPr><w:t>【唐·张若虚】</w:t></w:r></w:p>
</w:body>

这是body中的开头两个自然段。OpenXML采用了命名空间(namespaces),参考XML命名空间。在本例中,根标签是<w:body>, 根标签的属性xmlns:XX就是用来说明命名空间的,本例中的命名空间有3个:wwpccx,实际上一个word文件可能有十几个命名空间,但常用的就是w

获取Word XML

手动将Word文件另存为XML文件

在word中依次选择:文件——另存为——保存类型选择“Word XML 文档(*.xml)“——保存。

使用python-docx获取OpenXML

一、仅读取,不修改:

from docx import Document
from lxml import etreedoc = Document('春江花月夜.docx')
body_xml_str = doc._body._element.xml # 获取body中的xml
body_xml = etree.fromstring(body_xml_str) # 转换成lxml结点
print(etree.tounicode(body_xml)) # 打印查看for p in doc.paragraphs:p_xml_str = p._p.xml # 按段落获取xmlp_xml = etree.fromstring(p_xml_str) # 转换成lxml结点print(etree.tounicode(p_xml)) # 打印查看

注意:修改此方式获取的xml,不会影响原word文件。

二、如果想直接修改原word文件的xml,可以将docx.Document中,变量类型type是以CT_开头的(如doc._body._elementp._pdoc.styles._element等)直接当作lxml.etree.Element使用(虽然它们之间似乎没有继承关系) 。

print(type(doc._body._element)) # <class 'docx.oxml.document.CT_Body'>
print(type(p._p)) # <class 'docx.oxml.text.paragraph.CT_P'>
print(type(doc.styles._element)) # <class 'docx.oxml.styles.CT_Styles'>

例如:

from docx import Document
from lxml import etreedoc = Document('春江花月夜.docx')
body_xml = doc._body._element # 获取body中的xml
print(etree.tounicode(body_xml)) # 打印查看for p in doc.paragraphs:p_xml = p._p # 按段落获取xmlprint(etree.tounicode(p_xml)) # 打印查看

Word OpenXML常用结构

本节的主要参考资料为OpenXML微软官方文档。

(打不开的朋友可复制地址到浏览器:https://docs.microsoft.com/en-us/dotnet/api/documentformat.openxml.wordprocessing,将地址中的en-us改成zh-cn可浏览机翻的简体中文版本)

整体结构:body、styles、setting等

  • body就是正文结点,视觉可见的文本信息都应该是在这一部分。
  • styles相当于Word里的样式表,但应该还有更高端的用法,个人猜测Word中的主题设置应该也在这里,但是还没验证。
  • setting包含文件版本信息、作者信息等。

段落Paragraph结点:<w:p>

用于分段的结点,段落的格式也在这一级别设置,即<w:pPr>

段落结点不直接包含文字,而是先包含更下一级的<w:r>结点,再包含文字。

基本格式单位Run结点:<w:r>

还没想好这里的run应该怎么翻译,您有好的建议的话欢迎留言或来信交流。

一段独立格式的文本即占用一个Run结点<w:r>,其格式结点为<w:rPr>

实测发现,有的时候前后格式明明是一致的,却还是会划分出两个Run结点,具体原因目前不明,但(非完整)测试后发现,把两个Run合并成一个后,并不影响文件打开后的视觉效果。

格式Properties结点:<w:pPr><w:rPr>

  • pRr意为Paragraph Properties,通常用作表示段落的相关属性。
  • rPr意为Run Properties,通常用作表示字体的相关属性。

字体<w:rFonts>

rFonts意为RunFonts,用于表示不同语系下的字体,以及当前语种,点此查看官方文档。

用”语系“这个词可能不太恰当,但一时想不到别的词来描述了。您有好的建议的话欢迎留言或来信交流。

如果不显式指明字体,此段文字会使用上一级指明的字体。

目前rFonts支持四个语系,分别为:

{'ascii':'ASCII Font. Represents the following attribute in the schema: w:ascii','eastAsia':'East Asian Font. Represents the following attribute in the schema: w:eastAsia','hAnsi':'High ANSI Font. Represents the following attribute in the schema: w:hAnsi','cs':'Complex Script Font. Represents the following attribute in the schema: w:cs',
}

rFonts使用w:hint说明此段文本具体使用哪种语系的字体。

例如,将一段汉字的中文字体与西文字体全部设置为宋体:

<w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体" w:hAnsi="宋体" w:cs="宋体" w:hint="eastAsia"/></w:rPr><w:t>这一段文字字体为宋体。</w:t>
</w:r>

字号<w:sz><w:szCs>

sz表示Non-Complex Script Font Size,简单理解的话,就是单字节字符(如ASCII编码字符等)的大小。

szCs表示Complex Script Font Size,可以简单理解为双字节字符(如中日韩文字、阿拉伯文等)的大小。

如果不显式指明字号,此段文字会使用上一级指明的字号。

sz的官方资料中这句话The font sizes specified by this element’s val attribute are expressed as half-point values 说明,<w:sz><w:szCs>中的数值是实际磅值的两倍(原文翻译为”此元素的数值代表的字体大小,表示半点值)。

例如,一个五号汉字,考虑如下中文字号与磅值的对应关系,其磅值为10.5,翻倍为21,所以应该有<w:szCs w:val="21"/>

<w:r><w:rPr><w:rFonts w:hint="eastAsia"/><w:sz w:val="21"/><w:szCs w:val="21"/></w:rPr><w:t>这一段文字是五号字</w:t>
</w:r>
SZ_ZH_PT = {    # 中文字号与磅值对应关系"八号": 5,"七号": 5.5,"小六": 6.5,"六号": 7.5,"小五": 9,"五号": 10.5,"小四": 12,"四号": 14,"小三": 15,"三号": 16,"小二": 18,"二号": 22,"小一": 24,"一号": 26,"小初": 36,"初号": 42,
}

看的见的文字Text:<w:t>

正常来说,每个run中都应该有<w:t>结点,此结点包含的内容就是真实显示在word中的文字。

python-docx中的paragraph.textrun.text函数,返回的就是<w:t>结点中的内容,例如:

from docx import Documentdoc = Document('春江花月夜.docx')
for paragraph in doc.paragraphs:print('本段内容长度为%d' % len(paragraph.text))for i, run in enumerate(paragraph.runs):print('第{}个run的内容:{}'.format(i, run.text))

修订版本号rsid

Word会记录每一次对于文件的修改,并对修订版本进行随机编号。在OpenXML中,修订版本号通过rsid表示,具体的有w:rsidRw:rsidRPr等。

具体的版本更迭信息,保存在<w:settings>下的<w:rsids>中。

注音系统Ruby:<w:ruby>

标注过拼音的字符,在word中表现为一块域(field)。在OpenXML中,可看作是在<w:r>中,用<w:ruby>结点替换了<w:t>结点。

一个典型的注音xml:

<w:ruby><w:rubyPr><w:rubyAlign w:val="center"/><w:lid w:val="zh-CN"/></w:rubyPr><w:rt><w:r><w:rPr></w:rPr><w:t>zhōng</w:t></w:r></w:rt><w:rubyBase><w:r><w:rPr></w:rPr><w:t>中</w:t></w:r></w:rubyBase>
</w:ruby>

Word文件的OpenXML解析(以Python3为例)相关推荐

  1. (五)、JAVA基于OPENXML的word文档插入、合并、替换操作系列之word文件合并[支持多文件]

    (五).JAVA基于OPENXML的word文档插入.合并.替换操作系列之word文件合并[支持多文件] 二.word合并的多种方案简单比较 三.基于Open Xml WordprocessingML ...

  2. JAVA Apache POI解析docx格式的word文件并提取带样式文本

    关于JAVA Apache POI读取word文档,网上资料很多,但是大多数还是仅仅提取文档中的纯文本,好一点的,也就提取所有图片,但是,word文档本身是具有样式的,这样简单粗暴的提取就会丢失字体. ...

  3. vue3 - 网页在线预览 office word 文档,打开 .doc / .docx 文件显示并解析文档内容功能效果(超详细示例功能源码,复制粘贴后开箱即用)

    效果图 本博客实现了在 vue3 项目中,实现预览 word 文档功能示例,打开后缀名为 .doc / .docx 的文件进行显示解析, 如下图真实运行所示,兼容任意浏览器,你可以一键复制示例源码稍微 ...

  4. Python如何实现Word文件批量信息提取与结构化解析

    数据示例: 文件内容分为两部分,一种为表格形式 Word中的第一个表格 一种为文本段落形式 Word文件中需要结构化处理的内容 需求: 将表格中文本进行提取,第一列为字段名,第二列为数据内容 将段落中 ...

  5. java如何解析word大纲_java解析word文件

    POI是Apache的一个开源项目,可以到Apache网站下载相应的jar包文件,及其源文件. POI提供了提取一些非TXT文本中文本内容的API,比如提取Word,Excel等,使用起来非常方便. ...

  6. 应用python的docx模块解析word文件内容

    目录 工作问题 涉及知识点 实现过程 目标 调用对应的库和模块 定义通用方法 1.[遍历全部的同格式文件]返回一个文件夹内,限定某类格式文件,返回全部这类文件的绝对路径 2.[提取段落&表格中 ...

  7. php文本书写格式,在PHP中读/写MS Word文件

    小编典典 读取二进制Word文档将涉及根据已发布的DOC格式的文件格式规范创建解析器.我认为这不是真正可行的解决方案. 您可以使用Microsoft OfficeXML格式来读写Word文件- 这与W ...

  8. python中的doc_基于Python获取docx/doc文件内容代码解析

    这篇文章主要介绍了基于Python获取docx/doc文件内容代码解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 整体思路: 下载文件并修改后缀 ...

  9. android启动---lk入口文件crt0.s解析

    android启动---lk入口文件crt0.s解析 // .section 伪操作, 用户可以通过.section 伪操作来自定义一个段,每一个段以段名为开始, //以下一个段名或者文件结尾为结束, ...

  10. 【Apache POI】Java Web根据模板导出word文件

    最近工作中遇到一个需求:根据word模板文档导出word文件. 查阅了一些资料,发现Apache POI可以实现文档读写的功能,于是就研究了一下,总结如下: Apache-POI在线Javadoc:h ...

最新文章

  1. HTML5API(2)
  2. RuoYi-Cloud 部署篇_02(windows环境 Oracle +nginx版本)
  3. Win7系统打印机删除不掉的解决方法
  4. 飞鸽类能记住传书的人类
  5. 【原创】线上环境 SYN flooding 问题排查
  6. mysql plus baomidou_com.baomidou.mybatisplus.core.mapper 不存在
  7. python 复制文件并重命名_潘石屹都开始学Python了,你还有什么理由放弃?
  8. 面试题:谈谈你对Mysql数据库优化的见解
  9. 麒麟系统安装打印机共享_银河麒麟 惠普打印机驱动怎么安装
  10. Snagit 2020 for mac(最好用的屏幕截图软件)
  11. 身份证地区码数据表-SqlServer版
  12. Unity2D愤怒的小鸟技术点总结 ---- 制作动画特效
  13. 公司来了阿里人,然后......
  14. 《安富莱嵌入式周报》第275期:2022.07.18--2022.07.24
  15. 一岁半女娃海中“游泳秀” 观众含泪观看
  16. jQuery 绑定3种键盘事件 keypress(键盘键按下,功能键和中文不触发),keydown(键盘键按下,所有键都触发),keyup(键盘键松开)
  17. Java---设计【运动会成绩管理系统】
  18. pythoncad官网_Pycad: Python Extension for AutoCad
  19. 响铃:跑错了道的VR,如何知途迷返
  20. 解决手机QQ邮箱提醒收不到消息

热门文章

  1. 51单片机最小系统及晶振电容的选择
  2. 华为手机怎么安装Google
  3. c语言注释工具,C语言注释删除小工具下载
  4. linux下安装mysql5.7.11全纪录_记一次linux下安装mysql5.7
  5. Linux--Ubuntu的使用
  6. html中class类怎么写,HTML class 属性 | 菜鸟教程
  7. form表单提交中,确定和取消效果的实现
  8. Word2010为图片批量插入题注
  9. POJ 2387.Til the Cows Come Home
  10. [十大谬论]常见的逻辑谬误与批判方法