# 1. OOXML OPC 标准介绍

OOXML是 Office Open XML的简称,是以XML文件格式为基础的office文档规范,目前包括word,excel,ppt等。
其规范最初版本由Microsoft发布并在2006年由ECMA采纳成为Office文件标准(ECMA-376),
其后在2008年发布第二版本,2011.6月发布第三版本。
并且被ISO、IEC采纳成为国际标准(ISO/IEC 29500).

OPC 不是一种文件格式,而是以不同格式文件作为基础,组织成新文件格式的一种文件技术。

# 2. Package (包模型)

OPC的包模型描述了一个逻辑包模型和一个物理包模型,用于使用 XML、Unicode、ISO/IEC 10646、ZIP 和其他相关技术和规范来组织包中文档的内容和资源。包结构旨在支持各种应用程序和内容类别的构成资源的组织。 抽象包模型是一个包抽象,包含部分和关系的集合。这些部分根据一组规则进行组合、处理和持久化。部分可以与其他部分或外部资源有关系,而作为一个整体的包可以与其包含的部分或外部资源有关系。部件具有 MIME 媒体类型,并使用本文档中提供的明确定义的命名规则进行唯一标识。
物理包模型定义了抽象包模型的组件到特定物理格式(即 ZIP 文件)的特征的映射。
包模型描述了其他功能,包括包元数据的核心属性、包图形表示的缩略图以及包内容的数字签名。

# 2.1 Logic Model (逻辑包模型)

逻辑包模型的目的是将文档(或其他类型的内容)的组成部分聚合到单个对象中。

# 2.1.1 part

Part 类似于文件系统中的文件或HTTP服务器上的资源。在Package中所有的文件用Part来描述,Part在以OPC为标准的文件组织形式中应唯一存在,唯一性以Part Name来描述,它类似于文件系统中的文件路径。Part Name的定义有如下几条规则:

# 2.1.1.1 Part Name

  1. Part Name定义为Unicode字符串
    需符合RFC 5234中定义的ABNF语法中的以下生产规则:part_name = 1*( "/" isegment-nz )
    如: /segment1/segment2/segment3/.../segmentn
    /_rels/.rels 的Part Name为保留字段,代表了Package入口的Relationship描述。
  2. Part Name大小写不敏感
    /A 和 /a 应表示同一个Part Name
  3. Part Name不能是其他name的子路径
    如: /segment1/segment2 不能和 /segment1/segment2/segment3 同时存在,这样就破坏了路径的一致性(如本地文件系统中的例子:目录为 /a/b_dir, 则当前目录下不能存在名为/a/b_dir的文件)。

尽管Packge中Part Name可以支持非ASCII字符,但一般不建议,应以ASCII路径统一,防止一般兼容性问题。

# 2.1.1.2 media type

每个part应该都有一个MIME type (如RFC 2046中所定义),以表示标识该Part的实际文件类型,由顶级媒体类型和子类型组成。
如: core-properties Part的Type为: "application/vnd.openxmlformats-package.core-properties+xml".
如: image1.png Part的Type为: image/png.

# 2.1.1.3 Growth hint

有时,Physical Model中的某个部分会被修改,需要变大。 对于某些物理格式,创建包含较大部分的新物理包是一项昂贵的操作。 为了允许部分就地增长,移动尽可能少的字节,growth hint可用于在映射到特定物理格式时保留空间。

# 2.1.1.4 XML 使用规范

  1. XML内容应使用UTF-8或UTF-16编码。如果任何部分包含 XML 1.0 规范 4.3.3 中定义的编码声明,则该声明不得命名 UTF-8 或 UTF-16 以外的任何编码
  2. XML 1.0 规范允许使用文档类型定义 (DTD),这会启用拒绝服务攻击,通常是通过使用内部实体扩展技术。 作为对这种潜在威胁的缓解措施,DTD 声明不得用于本文档定义的 XML 标记中
  3. 应符合 XML 名称空间(引用时需要标明namespace)
  4. XML 内容应该是模式有效的,如符合W3C XML和W3C XML定义的XML标准 和 OOXML中定义的XSD标准。

# 2.1.1.5 Part Address

OPC 内使用IRI(RFC 3978)作为引用包内部资源的方式。 其定义的Pack Schema如下:

pack_IRI = "pack://" iauthority [ "/" | ipath ]
iauthority = ( iunreserved | sub-delims | pct-encoded )
ipath = 1
( "/" isegment )
isegment = 1*( ipchar )
ipchar = <ipchar, 如 [RFC3987], Section 2.2>
iunreserved = <iunreserved, 如 [RFC3987], Section 2.2>
sub-delims = <sub-delims, 如 [RFC3986], Section 2.2>
pct-encoded = <pct-encoded, 如 [RFC3986], Section 2.1>

使用了如上的IRI定义,则可以有如下的IRI解析方式:

  1. 将pack IRI 解析为scheme, authority, path等部分
  2. 在authority 中, 替换所有的',' 为 '/'
  3. 在authority 中, 解析所有百分比ASCII编码字符
  4. 解析完后如果不符合预期,则是错误的IRI(具体可以参考规范)

e.g.:

"pack://http%3c,,www.my.com,packages.aspx%3fmy.package/a/b/foo.xml" 解析为:

<authority> : http%3c,,www.my.com,packages.aspx%3fmy.package  
   [Package IRI : http://www.my.com/packages.aspx?my.package]
<path>= /a/b/foo.xml  [Path: /a/b/foo.xml]

有了Pack IRI的定义,则可以有如下的IRI访问方式:

  1. /b/bar.xml 包顶层路径
  2. bar.xml ./bar.xml ../bar.xml 相对路径

# 2.1.2 Relationship

OPC引入了一种间接机制来描述一个Part对其他Part或外部资源的引用,即Relationship。Relationship表示从源Part或源Package到目标Part或目标资源的连接。Relationship使连接无需查看部分内容即可直接发现,因此它们独立于特定于内容的模式并且可以快速解析。

Relationship在OPC中以XML表示。如果包本身或包中的任何部分是一个或多个Relationship的来源,则存在关联的关系部分。Relationship还有第二个重要功能:在不修改部件内容的情况下提供有关部件的附加信息。某些情况需要将信息附加到现有Part而不修改该Part,例如,因为该Part已加密且无法解密,或者因为它已进行数字签名并且更改它会使签名无效。

e.g.

<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
  <Relationship Target="a.xml" Id="IDI1" Type="http://example.com/relTypeInt1"/>
  <Relationship Target="a.xml" TargetMode="External" Id="IDE1" Type="http://example.com/relTypeExt1"/>
</Relationships>

| :----: | :----: | | Attributes | Description | | Target | 如果TargetMode为internal,则表示引用路径,否则,表示外部资源的引用路径,如可以为http链接 | | TargetMode | 值为External 或者 Internal, 默认为Internal, external表示为外部链接资源 | | Id | relationship 引用的id,唯一 | | Type | relationship type |

# 2.2 Physical Model (物理包模型)

Physical Model可以具有将媒体类型与部分相关联的本机机制。 如,MIME 实体标头中的 Content-Type 字段将媒体类型与该 MIME 实体相关联。

Content-Type的定义应该基于opc- contentTypes.xsd定义。 该 XML 文档应具有顶级类型元素,以及一个或多个默认和覆盖子元素。 默认元素应定义从部件名称扩展到媒体类型的默认映射。 覆盖元素应在未被默认映射覆盖或与默认映射不一致的部分上指定媒体类型。

e.g. :

<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
  <Default Extension="txt" ContentType="text/plain" />
  <Default Extension="jpeg" ContentType="image/jpeg" />
  <Default Extension="picture" ContentType="image/gif" />
  <Override PartName="/a/b/sample4.picture" ContentType="image/jpeg" />
</Types>

Default : Default 元素应指定从Part Name扩展到MIME type的默认映射,多为资源文件类型

Attributes Description
Extension 文件扩展名
ContentType 使用 RFC 7231, 3.1.1.1 中定义的语法指定媒体类型

Override : Override 元素应为未包含在默认映射中或与默认映射不一致的Part的MIME类型,多为自定义part

Attributes Description
PartName Part 名称
ContentType 使用 RFC 7231, 3.1.1.1 中定义的语法指定媒体类型

# 2.3 Core Properties 以及其他

参阅: Ecma Office Open XML Part 2 - Open Packaging Conventions

* 转载请注明出处