浅谈 Word 文档结构

栏目: IOS · Android · 发布时间: 5年前

内容简介:近期工作中遇到一个增加导出为对于 docx 文件大部分人都停留在这是一种 Office 的文件格式,可以用 Word 软件打开,并没有深入去了解下它内部的组成结构是怎么样的。实际上 docx 是一个压缩文件(Zip 格式),可以用 Zip 软件进行解压。

近期工作中遇到一个增加导出为 Word 格式的需求,因此花了点时间仔细了解了下 docx 格式,发现原来一篇 Word 背后有如此复杂的结构。本文主要介绍 docx 文件的结构,但是 pptx、xlsx 的原理应该是类似的。

docx 格式的奥秘

对于 docx 文件大部分人都停留在这是一种 Office 的文件格式,可以用 Word 软件打开,并没有深入去了解下它内部的组成结构是怎么样的。实际上 docx 是一个压缩文件(Zip 格式),可以用 Zip 软件进行解压。

浅谈 Word 文档结构

解压之后可以看到,它是有一系列 XML 文件组成:

浅谈 Word 文档结构

这就是 docx 文件的奥秘。

OOXML 规范介绍

这些 XML 的用处、每个 XML 文件的定义格式、Zip 目录结构等,都是在 OOXML 规范定义的非常清楚,下面是 OOXML 官网 对此的介绍:

Office Open XML, also known as OpenXML or OOXML, is an XML-based format for office documents, including word processing documents, spreadsheets, presentations, as well as charts, diagrams, shapes, and other graphical material. The specification was developed by Microsoft and adopted by ECMA International as ECMA-376 in 2006. A second version was released in December, 2008, and a third version of the standard released in June, 2011. The specification has been adopted by ISO and IEC as ISO/IEC 29500.

由此可见,word/ppt/excel 等几种格式的组织结构都是在同一个规范下定义的,他们的原理以及解析的方法都一样。OOXML 是微软公司在 2006 年公布的规范。类似的还有 Open Document Format (ODF) ,它是 OpenOffice.org 开源软件所使用的规范。

从官网介绍可以看出 OOXML 规范主要包括两个方面,第一个显然是每个 XML 文件的语法定义,类似 markdown 语言的语法描述一样,word 文件的格式、样式、内容布局等等都是和 XML 里面的 TAG 一一对应。第二个,就是对文件的组织结构的定义,前面看到 docx 实际上是一个 Zip 文件,解压缩出来的目录结构是有规则的,这个通过 Open Packaging Conventions (OPC) 定义,具体可以查看 Anatomy of a WordProcessingML File

接下来简单介绍下解压后的内容,如果要更详细的了解,还是建议仔细阅读下上文的链接以及相关的资料。

在解压的根目录,一般会有以下几个文件及目录:

kodango -> ~/Downloads/test
$ ls -l
total 8
-rwxr-xr-x@  1 kodango  staff  2529  1  1  1980 [Content_Types].xml
drwxr-xr-x@  3 kodango  staff    96 11 20 18:07 _rels
drwxr-xr-x@  5 kodango  staff   160 11 20 18:07 customXml
drwxr-xr-x@  5 kodango  staff   160 11 20 18:07 docProps
drwxr-xr-x@ 17 kodango  staff   544  1 21 16:20 word

下面逐个介绍下它们的用处。

[Content_Types].xml

这个文件是定义里面每一个 XML 文件的内容类型,打开看其实一目了然:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
    <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
    <Default Extension="xml" ContentType="application/xml"/>
    <Default Extension="jpg" ContentType="image/jpeg"/>
    <Override PartName="/word/document.xml"
              ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml"/>
    <Override PartName="/customXml/itemProps1.xml"
              ContentType="application/vnd.openxmlformats-officedocument.customXmlProperties+xml"/>
    <Override PartName="/word/numbering.xml"
              ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml"/>
    <Override PartName="/word/styles.xml"
              ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"/>
    <Override PartName="/word/settings.xml"
              ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml"/>
    <Override PartName="/word/webSettings.xml"
              ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml"/>
    <Override PartName="/word/footnotes.xml"
              ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml"/>
    <Override PartName="/word/endnotes.xml"
              ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml"/>
    <Override PartName="/word/header1.xml"
              ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml"/>
    <Override PartName="/word/footer1.xml"
              ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml"/>
    <Override PartName="/word/header2.xml"
              ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml"/>
    <Override PartName="/word/footer2.xml"
              ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml"/>
    <Override PartName="/word/fontTable.xml"
              ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml"/>
    <Override PartName="/word/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+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"/>
    <Override PartName="/docProps/custom.xml"
              ContentType="application/vnd.openxmlformats-officedocument.custom-properties+xml"/>
</Types>

比如

1、/word/document.xml 的类型是 application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml,说明这是保存 word 实际内容的文件,并且也可以看出这是从一个模版文件(dotx)解压出来的。

2、/word/styles.xml 的类型是application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml ,说明这是一个 word 样式文件,样式的定义都是保存在这个文件里面。

其他还有页眉、页脚、列表、属性等等,一个 docx 文件就是有这样非常多的部分组成,每个部分其实都是一个 Part(PartName属性),Part 之间会相关的关系(Relation)。

_rels

_rels 目录下会有一个 .rels 后缀的文件,它里面保存了这个目录下各个 Part 之间的关系。_rels 目录不止一个,它实际上是有层级的。

其中,根目录下面的 _rels 目录下就一个文件 .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/extended-properties"
                  Target="docProps/app.xml"/>
    <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"
                  Target="docProps/core.xml"/>
    <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
                  Target="word/document.xml"/>
    <Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties"
                  Target="docProps/custom.xml"/>
</Relationships>

显而易见,这个文件定义了顶层的关系,即 Package(Zip 包)和它所直接包含的 Part 之间的关系。

而对于一个 Part 来说,如果它依赖其他 Part,那么需要为这个 Part 创建一个目录,并且也有一个 _rels 目录,目录下面会有一个 partname.rels 文件。比如 /word/document.xml 就是很典型的例子:

$ tree word
word
├── _rels
│   └── document.xml.rels
├── document.xml

document.xml.rels 文件的内容:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
    <Relationship Id="rId8" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
                  Target="media/image1.jpg"/>
    <Relationship Id="rId13" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer"
                  Target="footer2.xml"/>
    <Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"
                  Target="styles.xml"/>
    <Relationship Id="rId7" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes"
                  Target="endnotes.xml"/>
    <Relationship Id="rId12" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/header"
                  Target="header2.xml"/>
    <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering"
                  Target="numbering.xml"/>
    <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml"
                  Target="../customXml/item1.xml"/>
    <Relationship Id="rId6" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes"
                  Target="footnotes.xml"/>
    <Relationship Id="rId11" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer"
                  Target="footer1.xml"/>
    <Relationship Id="rId5" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings"
                  Target="webSettings.xml"/>
    <Relationship Id="rId15" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"
                  Target="theme/theme1.xml"/>
    <Relationship Id="rId10" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/header"
                  Target="header1.xml"/>
    <Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings"
                  Target="settings.xml"/>
    <Relationship Id="rId9" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
                  Target="media/image2.jpg"/>
    <Relationship Id="rId14" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable"
                  Target="fontTable.xml"/>
</Relationships>

上面的内容也很好理解,/word/document.xml 和样式、页眉、页脚等等 Part 是有关系的。

word

上面介绍关系(Relationship)的时候已经介绍了 word 这个目录,无外乎是我们所看到的 word 内容所对应的各个文件,可以查看 这里 了解。

docProps

从名字可以看出,这个目录下的 XML 文件是保存了 docx 文件的属性。其实你打开 word 文件的时候,可以从菜单栏 File -> Properties 打开属性的对话框看到对应的属性内容。

背后 OOXML 把属性分成三类,分别是 Core 、Extended 以及 Custom,分别对应 core.xml、app.xml 以及 custom.xml。其中 custom.xml 保存的是自定义的属性,一般这一类属性会在文件中被引用到,比如定义一个 documentName 的属性,然后在封面、页眉等地方引用(百度 DOCPROPERTY 进一步了解)。

理解了这些简单的概念之后,其实就可以开始用代码去解析或者处理 docx 文件了,当然每个文件的语法定义依然是一个很复杂的部分,这块本文不会详细介绍,还是需要结合业务场景,当用到的时候再去了解。

解析 docx 文件

有许多库已经实现了 OOXML 规范,因此可以解析和处理 docx 文件,比如 docx4j 或者 apache poi 。这里以 docx4j 为例,这两个库都是 Java 相关的库,其他语言也有类似的库。


以上所述就是小编给大家介绍的《浅谈 Word 文档结构》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

写给大忙人看的C++

写给大忙人看的C++

【美】Brian Overland(布莱恩.奥弗兰德) / 卢涛、李颖 / 电子工业出版社 / 2015-8 / 109.00

《写给大忙人看的C++》全面介绍了C++语言知识,既提供了学习C++语言最新功能的捷径,也为快速找到特定问题的答案提供了便利。《写给大忙人看的C++》简明地描述了C++核心语言和标准库中几乎所有的函数、对象和运算符,一目了然地显示了语法、结构和重要函数的信息,内容组织形式便于快速查找信息。《写给大忙人看的C++》精选了实用的例子来深入地讲解概念,还提供了富有挑战性的练习及参考答案,便于读者举一反三......一起来看看 《写给大忙人看的C++》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

随机密码生成器
随机密码生成器

多种字符组合密码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码