1.EXI概念
高效 XML 交换(EXI)格式的开发遵循了五个设计原则,即:该格式必须是通用的、最小的、高效的、灵活的,并且具有互操作性。EXI 格式满足了这些前提条件,在实现通用性、高效性和灵活性的同时,保持了较低的复杂性。
EXI 格式采用的许多概念也适用于任何可以通过语法描述的语言的编码。尽管 EXI 利用模式信息来提高紧凑性和处理效率,但它并不依赖于准确、完整或当前的模式才能正常工作。
2.EXI格式
EXI 将 XML 文档的内容表示为 EXI 流。如下所示,EXI 流由 EXI 头部和 EXI 正文组成。
EXI 流结构
EXI 头部传递格式版本信息,并且可能还包括在编码过程中使用的选项集。如果这些选项被省略,假定解码器可以通过带外机制访问这些选项。EXI 正文由描述被编码的文档(或文档片段)的事件序列组成。更详细的信息如下:
2.1EXI 头部
EXI 头部传达了解码 EXI 正文所需的编码属性。最小的头部可以用一个字节表示,这样可以将开销和复杂度降到最低,并且不会牺牲紧凑性,特别是对于小文档来说,头部可能会引入较大的常数因子。
EXI 头部的结构如下图所示:
表 1. EXI 头部结构
EXI 头部以可选的四字节 EXI Cookie 开始。四字节字段由四个字符 " $ "、" E "、" X " 和 " I " 组成,按此顺序排列,每个字符都表示为一个 ASCII 八位字节,这可以用来区分 EXI 流与其他数据流。
EXI Cookie 后面跟着一对区分位。这个二进制序列(1 0)可以用来区分 EXI 文档和文本 XML 文档,并且足以基于广泛的字符编码区分 EXI 流和 XML 流。
EXI 选项存在位紧跟在区分位之后。该位的值用于指示是否存在 EXI 选项,这些选项稍后会出现在头部中。
EXI 格式版本标识正在使用的 EXI 版本,并允许未来的改进和修改。前导的 0(零)位表示文档是根据最终版本的推荐编码的,而前导的 1(一个)位表示这是预览版本。引入这种区分是为了方便早期发布预览版本,这些版本的互操作性要求较低。只有最终版本才要求被符合要求的处理器处理。前导位后跟一个或多个 4 位序列,整体解释为从 1 开始的格式版本号。例如,4 位序列 0000 被解释为版本 1,两个 4 位序列 1111 0001 被解释为 15 + 2 或版本 17。
EXI 选项指定了如何编码 EXI 流的正文,正如前面所述,它们的存在由头部中的存在位控制。由于 EXI 选项是通过 XML Schema 正式描述的,并且也是使用 EXI 编码的,因此它们引入的开销相对较小。下表描述了可以在 EXI 头部中指定的 EXI 选项。当 EXI 选项文档没有为某个特定选项指定值时,假定使用默认值。
表 2. EXI 选项
EXI 选项 | 描述 | 默认值 |
---|---|---|
alignment | 事件代码和内容项的对齐方式 | 位打包 |
compression | 指示是否使用 EXI 压缩以提高紧凑性 | false |
strict | 使用严格的模式解释以提高紧凑性 | false |
fragment | 指示是否将正文编码为 EXI 片段而不是 EXI 文档 | false |
preserve | 控制是否保留注释、处理指令等的一组选项 | 全部为 false |
selfContained | 启用自包含元素。自包含元素可以独立于 EXI 正文的其余部分读取 | false |
schemaId | 标识用于编码正文的模式信息(如果有) | 无默认值 |
datatypeRepresentationMap | 为 EXI 正文中的类型值指定替代的数据类型表示 | 无默认值 |
blockSize | 指定用于 EXI 压缩的每个块中的属性(AT)和字符(CH)值的数量 | 1,000,000 |
valueMaxLength | 指定考虑添加到字符串表中的值内容项的最大字符串长度 | 无限制 |
valuePartitionCapacity | 指定字符串表中值分区的总容量 | 无限制 |
[用户定义的元数据] | 可以添加用户定义的选项 | 无默认值 |
大多数选项都是直接的,作为布尔值启用或禁用某个功能。它们通过可选的 XML 元素表示,并且也通过 EXI 编码。关于用于编码这些选项的 XML Schema 的更多信息,请参见 EXI 选项头部的 XML Schema。
上表中的 preserve
选项实际上是一组选项,控制哪些 XML 项目被保留,哪些 XML 项目被忽略。它们统称为保真度选项。可以使用这些选项来消除传输未使用的 XML 项目所带来的开销。某些 XML 项目,如处理指令或 DTD(文档类型定义),可能永远不会出现(例如,在 SOAP 中),或者对用例或应用程序领域来说根本不重要。保真度选项用于管理某些 XML 项目的过滤器,具体如以下表所示。
表 3. 保真度选项
保真度选项 | 效果 |
---|---|
Preserve.comments | 保留语法中的 CM(注释)事件 |
Preserve.pis | 保留语法中的 PI(处理指令)事件 |
Preserve.dtd | 保留 DOCTYPE 和 ER(实体引用)事件的生成 |
Preserve.prefixes | 保留 NS(命名空间声明)事件和命名空间前缀 |
Preserve.lexicalValues | 保留元素和属性值的词法形式 |
自然地,编码时丢弃的 XML 项目(由于保真度选项的特定设置)在解码时无法精确恢复。
2.2 EXI 正文
EXI 文档的正文由一系列 EXI 事件组成。XML 项目被编码为一个或多个 EXI 事件;例如,名为 foo
的属性可以编码为 AT("foo")
,而名为 bar
的元素可以编码为一对事件:SE("bar")
和 EE
。EXI 事件可能具有与其相关联的附加内容。例如,属性事件 AT("foo")
可能与值 foo1
关联。下表展示了所有可能的事件类型及其与结构和内容相关的项。在 EXI 术语中,内容指的是属性和值,而所有其他信息项被视为属于结构类别。
表 2-5. EXI 事件类型
EXI 事件类型 | 语法符号 | 结构信息项 | 内容信息项 |
---|---|---|---|
开始文档 | SD | ||
结束文档 | ED | ||
开始元素 | SE (qname) | [prefix] | |
开始元素 | SE (uri:*) | local-name, [prefix] | |
开始元素 | SE (*) | qname, [prefix] | |
结束元素 | EE | ||
属性 | AT (qname) | [prefix] | value |
属性 | AT (uri:*) | local-name, [prefix] | |
属性 | AT (*) | qname, [prefix] | |
字符 | CH | value | |
命名空间声明¹ | NS | uri, prefix, local-element-ns | |
注释¹ | CM | text | |
处理指令¹ | PI | name, text | |
DOCTYPE¹ | DT | name, public, system, text | |
实体引用¹ | ER | name | |
自包含¹ | SC |
对于命名的 XML 项目,如元素和属性,存在三种类型的事件:SE(qname)
、SE(uri:*)
和 SE(*)
,以及 AT(qname)
、AT(uri:*)
和 AT(*)
。这些事件在其相关联的结构上有所不同:当使用 SE(qname)
或 AT(qname)
时,XML 项目的实际 qname
不会作为事件的一部分进行编码,而 SE(uri:*)
和 AT(uri:*)
事件则不会编码 uri
。选择使用哪种类型的事件将在引入 EXI 语法的概念后进行解释。此外,保真度选项可能允许保留命名空间前缀。