Office 文件解析入门

概述 - Office 解析相关协议

这里所讲的 Office 文件指的是微软 Office2007 及以后的 PPT/EXCEL/WORD 等文件格式,因为 Office2007 以前的文件是用二进制格式定义的,不在本文的讨论内容中。

Office2007 以后的文件格式属于 OOXML 文件格式,OOXML 是基于 zip+xml 定义的。

OOXML 全称 Office Open XML File Formats,最初是由 ECMA-376 定义的,它目前已经到第六版。后来 ISO/IEC 29500 也开始掺和OOXML格式的定义,不过可以认为从 ECMA-376 的第2版开始,这两个标准是一样的。目前最新的 OOXML 标准是在 2016 年发布的 ECMA-376 5th edition 或者 ISO/IEC 29500:2016

微软的 Office 实现了OOXML格式,但不是全部,微软在 这篇文章 中描述了其对标准的支持情况。

OOXML = OPC + *ML ,下面会分别介绍 OPC*ML

由于 EMCA 文档可以免费在网上下载的,而 ISO 文档需要付费才能获取,因此下文的内容都是基于 ECMA-376 文档。

OPC - Open Package Convention

关于 OPC 的详细内容请参考 ECMA-376,Fourth Edition,Part 2

OPC 中文名开放打包协定,是一种基于 zip+xml 定义的文件存储格式。一个 OPC 文件(不管其文件后缀是什么)本质上就是一个 zip 文件,你可以用任何常见的解压软件进行解压,解压后你看到的那些文件的组织结构,就是以 OPC 定义的方式存储的。下图是一个PPTX文件解压后的目录结构:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qDbyGMsj-1601820950235)(./ppt-decompress.png)]

OPC 中有3个重要的概念要理解:Part , Relationship , ContentTypes

Part

Part 可以简单理解为 zip 中的文件,每一个文件都是一个 Part ,它可以是任何格式,比如图片,xml文件等。在 Office 文件中,各种 Markup Language 定义的内容就作为 XML 存储在 Part 中。

Relationship

Relationship 是一种特殊的 Part ,它描述了各 Part 之间的依赖关系。根据OPC协议的规定,所有的 Relationship 都必须存储在名为 _rels 的文件夹中,并且所有 Relationship 的文件名都必须以 .rels 为后缀。

每一个 Part 根据业务需求都可以有对应的 Relationship 文件,比如在 PPTX 文件中,有一个 Part 为 /ppt/presentation.xml ,它对应的 Relationship 文件(只能)为/ppt/_rels/presentation.xml.rels ,不能是任何其它名字或者位置的文件。下面是一个 PPTX 文件中的 presentation.xml.rels 文件:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide" Target="slides/slide2.xml"/><Relationship Id="rId7" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/tableStyles" Target="tableStyles.xml"/><Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide" Target="slides/slide1.xml"/><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster" Target="slideMasters/slideMaster1.xml"/><Relationship Id="rId6" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="theme/theme1.xml"/><Relationship Id="rId5" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/viewProps" Target="viewProps.xml"/><Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/presProps" Target="presProps.xml"/>
</Relationships>

Relationship 文件的根节点是 RelationShips, 它是 Relationship 节点的集合,每一个 Relationship 节点都代表一个依赖关系。它的各个属性的意义如下:

属性名 是否必须 说明
Id 唯一标识符,在当前文件中是唯一的,不同文件中可以重复
Type Target 的文件类型
Target 目标 Part 的路径,可以用相对路径也可以用绝对路径
TargetMode 目标的类型,值可以是 Internal 或者 External (默认是Internal),表示 Target 是OPC文件内部的还是外部的

ContentTypes

ContentTypes 在zip压缩包的根目录下,文件名为 [Content_Types].xml ,它记录了该OPC文件中除了他自己以外的所有文件的类型。下面是一个PPTX文件的 ContentTypes 文件:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="jpeg" ContentType="image/jpeg"/><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Override PartName="/ppt/presentation.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml"/><Override PartName="/ppt/slideMasters/slideMaster1.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml"/><Override PartName="/ppt/slides/slide1.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slide+xml"/><Override PartName="/ppt/slides/slide2.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slide+xml"/><Override PartName="/ppt/presProps.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.presProps+xml"/><Override PartName="/ppt/viewProps.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.viewProps+xml"/><Override PartName="/ppt/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml"/><Override PartName="/ppt/tableStyles.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.tableStyles+xml"/><Override PartName="/ppt/slideLayouts/slideLayout1.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml"/><Override PartName="/ppt/slideLayouts/slideLayout2.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml"/><Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/><Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/>
</Types>

其中有两种标签 DefaultOverride , Default 指明了拥有文件后缀名和文件类型的对应关系, Override 指明了某一个文件的文件类型。

比如:<Default Extension="jpeg" ContentType="image/jpeg"/> 的意思是后缀为 jpeg 的文件都是 image/jpeg 类型的文件,因此在OPC中不建议根据文件后缀名来判断一个文件的类型,而应该根据 ContentTypes 文件中记录的信息来判断文件类型。

*ML (* Markup Language)

关于各种 ML 语言的详细信息请参考 ECMA-376,Fifth Edition,Part 1

Markup Language (ML) 译为 标记语言,是一种用 XML 来描述数据的"语言",比如:

*ML 全名 说明
PML Presentation Markup Language PPT 中各种数据的描述
WML Wordprocessing Markup Language Word 中数据的描述
SML Spreadsheet Markup Language Excel 中数据的描述
DML Drawing Markup Language Office 所有格式中都可以使用,用来描述矢量图形,图表等
SharedML Shared Markup Language 描述了文档属性,音视频,图片,文档主题等内容,它被所有Office文件使用

比如之前提到的 presentation.xml 文件,它的文件内容就是在 PML 中定义的。具体信息可以查看 ECMA-376,Fifth Edition,Part 1。但是,ECMA-376 太长了,还没看就头疼,怎么办。

首先了解一下在 EMCA-376 中用来定义各种 ML 语言的 XSD:

XSD - XML Schema Definition 或者 XML Schema

XSD 类似 DTD,它们有相似的作用。在 ECMA-376 中,所有的 Markup Language 都是 XML 格式的,而这些 XML 的具体节点内容,都是用 XSD 来定义的,所以我们要对它有一定的了解:

XML Schema(XSD) 的作用:

  • 定义可出现在文档中的元素
  • 定义可出现在文档中的属性
  • 定义哪个元素是子元素
  • 定义子元素的次序
  • 定义子元素的数目
  • 定义元素是否为空,或者是否可包含文本
  • 定义元素和属性的数据类型
  • 定义元素和属性的默认值以及固定值
    (可以在 这里 找到 XSD 的详细内容。)

XSD 中,有两个比较重要的概念:Simple Type(简单类型)Complex Type(复杂类型)

名称 说明
Simple Type Element 简单类型元素,指那些仅包含文本的元素。它不会包含任何其他的元素或属性。 比如:<id>123</id>,这里元素 id 就是简单类型元素。
Complex Type Element 复杂类型元素,指那些可以包含其他任意元素或者属性的元素。

比如在 PML 中定义 页面大小(SlideSize) 这个元素(节点)的 XSD 如下:

<xsd:complexType name="CT_SlideSize"> <xsd:attribute name="cx" type="ST_SlideSizeCoordinate" use="required"/> <xsd:attribute name="cy" type="ST_SlideSizeCoordinate" use="required"/> <xsd:attribute name="type" type="ST_SlideSizeType" use="optional" default="custom"/>
</xsd:complexType>

可以看出 CT_SlideSize 是个 complexType(复杂类型) 的元素,并且它有三个 attribute(属性) ,分别是 cx , cytype,根据它们 type 的前缀 ST_ ,可以看出这三个属性都是简单类型的,并且是 required 的。如果你明白了这里的描述,再去看 ECMA-376 中各种 ML 语言的定义应该会简单一点。

PS: 在看 ECMA-376 的时候可以先只看前 16 章的内容,只有160页左右,如果只算内容的话更少,后面的将近 5000 页都可以解析哪部分就去看哪部分就行了。言外之意就是,其实也没有想象中的那么唬人。JUST DO IT !

PPTX 解析的基本流程

这里以 PPTX 的解析为例,其它的 WORD 或者 EXCEL 可以触类旁通。

基本流程如下:

  1. 读取 /[Content_Types].xml 文件,获取到所有文件的类型;
    这部分需要了解 OPC 中关于 ContentTypes 的内容。
  2. 读取 /_rels/.rels 这个所谓的 Package Relationship 文件,获取 presentation.xml 文件的位置,比如 /ppt/presentation.xml
    这部分需要了解 OPC 中关于 Relationship 的内容以及 PML 的基本内容。
  3. 读取 /ppt/presentation.xml 文件以及其关联的 Relationship 文件 /ppt/_rels/presentation.xml.rels,得到该PPT所有页面文件的存储位置,比如 /ppt/slides/slide1.xml,以及 slideMaster(母版)文件的存储位置,比如 /ppt/slideMasters/slideMaster1.xml,以及 slideLayout(板式)等相关文件的存储位置;
    这部分需要了解 PML 中关于 Presentation 的定义,也就是 PML 的 XSD 中定义的 CT_Presentation 类型。这个时候可以去详细的阅读 Presentation 章节的详细信息了。
  4. 读取 /ppt/slides/slide1.xml 文件内容以及其关联的 Relationship /ppt/slides/_rels/slide1.xml.rels,可以得到该页面的所有元素信息;
    这部分要完整解析就需要了解所有 PML、DML、SharedML 中的内容了。

不知道看到这里你还要不要自己解析啊?如果不愿意了,那大名鼎鼎的 POI 也许可以救你于水深火热。

POI/NPOI

POI 是 Apache 的项目,这里 是它的官网(NPOI 是 POI 的 .NET 版本)。背景知识我就不介绍了,这里摘自维基百科对它模块划分的介绍,可以在自己解析的时候参考:

POIFS (Poor Obfuscation Implementation File System) – This component reads and writes Microsoft's OLE 2 Compound document format. Since all Microsoft Office files are OLE 2 files, this component is the basic building block of all the other POI elements. POIFS can therefore be used to read a wider variety of files, beyond those whose explicit decoders are already written in POI.(也就是OPC模块)
HSSF (Horrible SpreadSheet Format) – reads and writes Microsoft Excel (XLS) format files. It can read files written by Excel 97 onwards; this file format is known as the BIFF 8 format. As the Excel file format is complex and contains a number of tricky characteristics, some of the more advanced features cannot be read.()
XSSF (XML SpreadSheet Format) – reads and writes Office Open XML (XLSX) format files. Similar feature set to HSSF, but for Office Open XML files.
HPSF (Horrible Property Set Format) – reads "Document Summary" information from Microsoft Office files. This is essentially the information that one can see by using the File|Properties menu item within an Office application.
HWPF (Horrible Word Processor Format) – aims to read and write Microsoft Word 97 (DOC) format files. This component is in initial stages of development.
XWPF (XML Word Processor Format) – similar feature set to HWPF, but for Office Open XML files.
HSLF (Horrible Slide Layout Format) – a pure Java implementation for Microsoft PowerPoint files. This provides the ability to read, create and edit presentations (though some things are easier to do than others)
HDGF (Horrible DiaGram Format) – an initial pure Java implementation for Microsoft Visio binary files. It provides an ability to read the low level contents of the files.
HPBF (Horrible PuBlisher Format) – a pure Java implementation for Microsoft Publisher files.
HSMF (Horrible Stupid Mail Format[7][better source needed]) – a pure Java implementation for Microsoft Outlook MSG files.[8]
DDF (Dreadful Drawing Format) – a package for decoding the Microsoft Office Drawing format.

需要注意的是 POI 貌似对 PPT 的支持比较弱?

最后

你应该只是需要部分解析 Office 格式吧?难道你想过完全解析么?太可怕了。

Office 文件解析入门相关推荐

  1. Office文件的奥秘——.NET平台下不借助Office实现Word、Powerpoint等文件的解析(完)...

    原文 http://www.cnblogs.com/mayswind/archive/2013/04/01/2991271.html [题外话] 这是这个系列的最后一篇文章了,为了不让自己觉得少点什么 ...

  2. Office文件的奥秘——.NET平台下不借助Office实现Word、Powerpoint等文件的解析(一)...

    [题外话] 这是2010年参加比赛时候做的研究,当时为了实现对Word.Excel.PowerPoint文件文字内容的抽取研究了很久,由于Java有POI库,可以轻松的抽取各种Office文档,而.N ...

  3. Office文件的奥秘——.NET平台下不借助Office实现Word、Powerpoint等文件的解析

    转载http://www.cnblogs.com/mayswind/archive/2013/03/17/2962205.html [题外话] 这是2010年参加比赛时候做的研究,当时为了实现对Wor ...

  4. 分布式.RPC-WebService入门案例(java实现,注解实现,xsd文件解析,wsdl文件解析)

     系列博文: 分布式.RPC调用-RMI & Hessian框架_闲猫的博客-CSDN博客 分布式.RPC-WebService三要素,三个规范, Soap协议_闲猫的博客-CSDN博客 分布 ...

  5. Office文件的解析

    Office文件的解析 引用:http://www.langye.com/a/2013417/237.shtml [题外话] 这是这个系列的最后一篇文章了,为了不让自己觉得少点什么,顺便让自己感觉完美 ...

  6. AUTOSAR从入门到精通100讲(十五)-AURIX TC3xx MCAL中Link文件解析以及代码变量定位方法详解

    一 TC3xx系列MCAL中TASKING Link文件解析以及代码变量定位方法 1 TASKING Link文件解析 1.1 DSRAM中的数据存放: 在AURIX™ 2G中(以TC387为例),每 ...

  7. 所有人都可以是开发人员——《Office 365开发入门指南》视频教程即将上市

    今天是春节假期的最后一天,在这里给全国的朋友们拜个晚年,祝大家身体健康,晚年幸福啊.这个春节大家过的怎么样啊,我自己是在老家过的年,家乡的年味还是比较浓的,也再次感谢朋友圈的大家给我看了各地的风光和不 ...

  8. dump文件解析之探索.Net的内存

    前言: 对于需要长时间运行的.net程序,有时需要我们查看内存的使用有没有内存泄露问题. 我们可以从dump文件中找到答案. Dump的看点 用dump文件来分析内存,到底我们需要关心哪些点呢? 内存 ...

  9. 让你久等了《开源安全运维平台OSSIM疑难解析--入门篇》正式出版

    2019年暑期,众所期待的新书<开源安全运维平台OSSIM疑难解析--入门篇>由人民邮电出版社正式出版发行.此书从立意到付梓,历时超过两年,经过数十次大修,历经曲折与艰辛,希望为大家代奉献 ...

最新文章

  1. deeplearning模型量化实战
  2. android 默认打开服务器地址,Android开发实现任意切换服务器地址
  3. linux下模拟CPU占用100%小程序
  4. php文件放到html中,怎么把HTML作为模板放到PHP中
  5. AGS API for JavaScript 图表上地图
  6. HTML5日期输入类型
  7. deepin--更改最低亮度
  8. 今日arXiv精选 | 11篇ICCV 2021最新论文
  9. 中国风古典传统中式花纹边框图案PSD素材
  10. 前端架构最全总结——GUI 应用程序架构的十年变迁:MVC、MVP、MVVM、Unidirectional、Clean...
  11. sphinx系列之中文分词LibMMSeg安装(三)
  12. imp 数据导入_墨天轮数据库周刊—第7期
  13. 接口没获取到就被使用_使用CompletableFuture时,那些令人头疼的问题
  14. html 字体样式 幼圆,设置字体样式:字号大小,字体种类,字体粗细
  15. python除法运算定律有哪些_运算定律有哪些
  16. 关于计算机名的相关讨论 【好帖 好帖 哈哈。。】
  17. Phun:一个巨牛B的物理引擎
  18. 三、项目分工(华为项目管理法-孙科炎读书摘要)
  19. 数学基础:反三角函数
  20. 北京联通KD-YUN-811E改桥接

热门文章

  1. 计算机桌面标题栏怎么锁定,win10如何将便利贴固定在桌面任务栏
  2. 慧鱼控制器可以用单片机控制吗_为什么工业设备都是没有用单片机控制的?
  3. 常见功能点测试用例大全
  4. java 栈的使用
  5. SMT贴片加工产生焊点剥离的原因和方法
  6. Mac系统安装python3并安装pip3进行下载第三方库
  7. win8修复计算机u盘,联想一键恢复8.0专用WIN8PE
  8. 鼠标拾取(光线拾取)
  9. 人工智能科普教材:初中
  10. 计算机二级复习资料完整版